Repository: asteroid-lang/asteroid (language: python)

Issue:
type 'function-val' should become 'function'
The types 'function-val' and 'member-function-val' should become 'function' to make them consistent with the type pattern %function.
Issue 218

OS module
A module that allows the user to access OS functionality such as `argv` and path manipulation.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/generate_documentation.yml b/.github/workflows/generate_documentation.yml
index 7bf10a91..d0c4ddfd 100644
--- a/.github/workflows/generate_documentation.yml
+++ b/.github/workflows/generate_documentation.yml
@@ -1,8 +1,8 @@
 name: Documentation Generation
 on:
-    push:
+    pull_request:
         branches:
-            - dev-1.1.4
+            - '!master'
 env:
     PYTHONPATH: ${{ github.workspace }}
 jobs:
@@ -19,6 +19,7 @@ jobs:
 
       - name: Regenerate documentation
         run: |
+          pip install pcpp
           cd docs
           # This is to keep github actions happy
           bash generate_docs
diff --git a/README.md b/README.md
index 62a4a0e7..bf3338dd 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,24 @@ be found at the website [asteroid-lang.org](https://asteroid-lang.org).
 Documentation on Asteroid can be found at
 [asteroid-lang.readthedocs.io](https://asteroid-lang.readthedocs.io).
 
+## New in Release 1.1.4
+
+* Allows pattern constraint operator to map certain variables that a pattern 
+  matched to be bound into the current scope.
+
+* Supports a new OS module.
+
+* Supports iteration over tuple components
+
+* The `eval` function has been extended to strings for the interpretation of 
+  Asteroid programs in those strings.
+
+* Structures now support a `__str__` member function that allows the user
+  to specify a string representation of the structure.
+
+* Lots of bug fixes.
+
+
 ## New in Release 1.1.3
 
 * Fixes a fatal bug on Windows regarding the `readline` functionality in Python 3.10.
diff --git a/asteroid/__init__.py b/asteroid/__init__.py
index 2b005d97..b14400fd 100755
--- a/asteroid/__init__.py
+++ b/asteroid/__init__.py
@@ -8,6 +8,7 @@
 import cProfile
 import sys
 import os
+import os.path
 from asteroid.interp import interp
 from asteroid.repl import repl
 from asteroid.version import VERSION
@@ -52,21 +53,28 @@ def main():
     }
 
     flag_names = list(flags.keys())
-
-    if len(sys.argv) == 1:
-        repl(redundancy=flags['-r'],
-             prologue=flags['-p'],
-             functional_mode=flags['-F'])
-        sys.exit(0)
-
-    for fl in sys.argv:
-        if fl[0] != '-':
-            continue
-        elif fl not in flag_names:
-            print("unknown flag {}".format(fl))
-            sys.exit(0)
-        flags[fl] = not flags[fl]
-
+    argv_ix = 1
+    asteroid_ext = '.ast'
+
+    # logic of command line parameters
+    # - process all flags to Asteroid interpreter
+    # - determine if we need to respond to special flags and exit
+    # - determine if we are starting in interactive mode or not
+    #  if not in interactive mode execute the asteroid script
+
+    # process all flags to interpreter
+    while argv_ix < len(sys.argv):
+        fl = sys.argv[argv_ix]
+        if fl[0] == '-':
+            if fl not in flag_names:
+                raise ValueError("unknown flag {}".format(fl))
+            else:
+                flags[fl] = not flags[fl]
+            argv_ix += 1
+        else:
+            break
+
+    # determine if we need to respond to special flags and exit
     if flags['--help'] or flags['-h']:
         display_help()
         sys.exit(0)
@@ -75,25 +83,38 @@ def main():
         print("** Asteroid Version {} **".format(VERSION))
         sys.exit(0)
 
-    input_file = sys.argv[-1]
+    debug_flag = flags['--adb'] or flags['-g']
 
-    if input_file[0] == '-':
-        if flags['--adb']:
-            print("Please provide a file to debug")
-            sys.exit(1)
+    # determine if we are starting in interactive mode or not
+    # Note: first non-switch argument has to be an Asteroid source file
+    if len(sys.argv) == argv_ix:
+        input_file = ''
+    else:
+        input_file = sys.argv[argv_ix]
+    (input_root,input_ext) = os.path.splitext(input_file)
+    if input_file and input_ext != asteroid_ext:
+        print("error: file '{}' is not an Asteroid source file".format(input_file))
+        sys.exit(1)
+
+    # run the REPL
+    if input_ext == '' and not debug_flag:
         repl(redundancy=flags['-r'],
              prologue=flags['-p'],
              functional_mode=flags['-F'])
         sys.exit(0)
 
-    if not os.path.isfile(input_file):
-        print("unknown file {}".format(input_file))
-        sys.exit(0)
+    # we have an input file, check if it exists
+    if input_file and not os.path.isfile(input_file):
+        print("error: unknown file '{}'".format(input_file))
+        sys.exit(1)
 
-    if flags['--adb'] or flags['-g']:
+    # run the debugger
+    if debug_flag:
+        if input_ext == '':
+            print("error: please provide a file to debug")
+            sys.exit(1)
         # Create a new debugger
         db = adb.ADB()
-
         # Set the debugger's internal interpretation options
         db.interp_options = {
             'redundancy': flags['-r'],
@@ -101,10 +122,10 @@ def main():
             'functional_mode': flags['-F'],
             'exceptions': flags['-e'],
         }
-
         db.run(input_file)
         sys.exit(0)
 
+    # execute the interpreter
     f = open(input_file, 'r')
     input_stream = f.read()
     f.close()
diff --git a/asteroid/frontend.py b/asteroid/frontend.py
index 17a53c00..e93c94d8 100644
--- a/asteroid/frontend.py
+++ b/asteroid/frontend.py
@@ -571,7 +571,7 @@ def exp(self):
     ###########################################################################################
     # pattern
     #    : PATTERN WITH? exp
-    #    | '%[' exp ']%'
+    #    | '%[' exp ']%' binding_list?
     #    | head_tail
     def pattern(self):
         dbg_print("parsing PATTERN")
@@ -585,7 +585,11 @@ def pattern(self):
             self.lexer.match('LCONSTRAINT')
             v = self.exp()
             self.lexer.match('RCONSTRAINT')
-            return ('constraint', v)
+            if self.lexer.peek().type == 'BIND':
+                bl = self.binding_list()            
+                return ('constraint', v, bl)
+            else:
+                return ('constraint', v, ('nil',))
         else:
             v = self.head_tail()
             return v
@@ -804,7 +808,7 @@ def call_or_index(self):
     #    | FALSE
     #    | NONE
     #    | ID
-    #    | '*' call_or_index /* pattern dereferencing */
+    #    | '*' call_or_index binding_list? /* pattern dereferencing */
     #    | NOT call_or_index
     #    | MINUS call_or_index
     #    | PLUS call_or_index
@@ -850,7 +854,11 @@ def primary(self):
         elif tt == 'TIMES':
             self.lexer.match('TIMES')
             v = self.call_or_index()
-            return ('deref', v)
+            if self.lexer.peek().type == 'BIND': # binding list
+                l = self.binding_list()
+            else:
+                l = ('nil',)
+            return ('deref', v, l)
 
         elif tt == 'NOT':
             self.lexer.match('NOT')
@@ -917,6 +925,53 @@ def primary(self):
             #raise SyntaxError("syntax error at '{}'"
                 # .format(self.lexer.peek().value))
 
+    ###########################################################################################
+    # binding_list
+    #   : BIND binding_list_suffix
+    def binding_list(self):
+        dbg_print("parsing BINDING_LIST")
+        self.lexer.match('BIND')
+        bl = self.binding_list_suffix()
+        return bl
+
+    ###########################################################################################
+    # binding_list_suffix
+    #   : binding_term
+    #   | '[' binding_term (',' binding_term)* ']'
+    def binding_list_suffix(self):
+        dbg_print("parsing BINDING_LIST_SUFFIX")
+        if self.lexer.peek().type == 'ID':
+            bl = [ self.binding_term() ]
+            return ('binding-list', bl)
+        elif self.lexer.peek().type == 'LBRACKET':
+            self.lexer.match('LBRACKET')
+            bl = [ self.binding_term() ]
+            while self.lexer.peek().type == 'COMMA':
+                self.lexer.match('COMMA')
+                bl.append(self.binding_term())
+            self.lexer.match('RBRACKET')
+            return ('binding-list', bl)
+        else:
+            raise SyntaxError("syntax error at '{}'"
+                        .format(self.lexer.peek().value))
+
+    ###########################################################################################
+    # binding_term
+    #   : ID (AS ID)?
+    def binding_term(self):
+        dbg_print("parsing BINDING_TERM")
+        name_tok = self.lexer.match('ID')
+        if self.lexer.peek().type == 'AS':
+            self.lexer.match('AS')
+            as_name_tok = self.lexer.match('ID')
+            return ('binding-term', 
+                    ('id', name_tok.value), 
+                    ('id', as_name_tok.value))
+        else:
+            return ('binding-term', 
+                    ('id', name_tok.value), 
+                    ('id', name_tok.value))
+            
     ###########################################################################################
     # tuple_stuff
     #   : exp (',' exp?)*
diff --git a/asteroid/grammar.txt b/asteroid/grammar.txt
index be99e6ae..0c540c7b 100644
--- a/asteroid/grammar.txt
+++ b/asteroid/grammar.txt
@@ -9,7 +9,7 @@
  - Use C++ style comments for any comments that you DO want to be displayed
    in the target documentation.
  - C style comments for any comments that you DO NOT want to be displayed
-   in the target documentation.
+   in the target documentation -- like the one you are reading right now...
  **************************************************************************************/
   ////////////////////////////////////////////////////////////////////////////////////////
   // statements
@@ -72,7 +72,7 @@
 
   pattern
     : PATTERN WITH? exp
-    | '%[' exp ']%'      /* constraint-only pattern match */
+    | '%[' exp ']%' binding_list?    /* constraint-only pattern match */
     | head_tail
 
   head_tail
@@ -126,7 +126,7 @@
     | FALSE
     | NONE
     | ID
-    | '*' call_or_index   /* pattern dereferencing */
+    | '*' call_or_index  binding_list? /* pattern dereferencing */
     | NOT call_or_index
     | MINUS call_or_index
     | PLUS call_or_index
@@ -137,6 +137,18 @@
     | function_const
     | TYPEMATCH           // TYPEMATCH == '%'<typename>
 
+/* Note: binding lists are only supported for constraint patterns */
+
+  binding_list
+    : BIND binding_list_suffix
+    
+  binding_list_suffix
+     : binding_term
+     | '[' binding_term (',' binding_term)* ']'
+
+  binding_term
+    : ID (AS ID)?
+
   tuple_stuff
     : exp (',' exp?)*
     | empty
diff --git a/asteroid/lex.py b/asteroid/lex.py
index 95323399..f5c0d293 100644
--- a/asteroid/lex.py
+++ b/asteroid/lex.py
@@ -1,7 +1,7 @@
 ###########################################################################################
 # Lexer for Asteroid
 #
-# (c) Lutz Hamel, University of Rhode Island
+# (c) University of Rhode Island
 ###########################################################################################
 
 import re
@@ -13,7 +13,9 @@
 keywords = {
 #   value:          type:
     'and'           : 'AND',
+    'as'            : 'AS',
     'assert'        : 'ASSERT',
+    'bind'          : 'BIND',
     'break'         : 'BREAK',
     'catch'         : 'CATCH',
     'data'          : 'DATA',
@@ -188,7 +190,7 @@ def tokenize(code):
             (module, lineno) = state.lineinfo
             line_num += lines
             state.lineinfo = (module, line_num)
-            value = value[1:-1] # strip the quotes
+            value = value[1:-1].replace('\\"','"') # strip the quotes
         elif type == 'NEWLINE':
             line_num += 1
             state.lineinfo = (module,line_num)
diff --git a/asteroid/modules/bitwise.ast b/asteroid/modules/bitwise.ast
index 91bb887d..8ef19dc0 100644
--- a/asteroid/modules/bitwise.ast
+++ b/asteroid/modules/bitwise.ast
@@ -14,9 +14,9 @@ structure __BITWISE_MODULE__
 with
 
 ------------------------------------------------------------------
- -- Bitwise AND
 function band
 ------------------------------------------------------------------
+ -- Bitwise AND
 with(x:%integer, y:%integer) do return escape
 "
 global __retval__
@@ -28,9 +28,9 @@ __retval__ = ('integer', x_val[1] & y_val[1])
 end
 
 ------------------------------------------------------------------
- -- Bitwise OR
 function bor
 ------------------------------------------------------------------
+ -- Bitwise OR
 with(x:%integer, y:%integer) do return escape
 "
 global __retval__
@@ -42,9 +42,9 @@ __retval__ = ('integer', x_val[1] | y_val[1])
 end
 
 ------------------------------------------------------------------
- -- Bitwise NOT
 function bnot
 ------------------------------------------------------------------
+ -- Bitwise NOT
 with(x:%integer) do return escape
 "
 global __retval__
@@ -55,9 +55,9 @@ __retval__ = ('integer', ~x_val[1])
 end
 
 ------------------------------------------------------------------
- -- Bitwise XOR
 function bxor
 ------------------------------------------------------------------
+ -- Bitwise XOR
 with(x:%integer, y:%integer) do return escape
 "
 global __retval__
@@ -69,9 +69,9 @@ __retval__ = ('integer', x_val[1] ^ y_val[1])
 end
 
 ------------------------------------------------------------------
- -- Bitwise left shift
 function blshift
 ------------------------------------------------------------------
+ -- Bitwise left shift
 with(x:%integer, y:%integer) do return escape
 "
 global __retval__
@@ -83,9 +83,9 @@ __retval__ = ('integer', x_val[1] << y_val[1])
 end
 
 ------------------------------------------------------------------
- -- Bitwise right shift
 function brshift
 ------------------------------------------------------------------
+ -- Bitwise right shift
 with(x:%integer, y:%integer) do return escape
 "
 global __retval__
@@ -97,9 +97,9 @@ __retval__ = ('integer', x_val[1] >> y_val[1])
 end
 
 ------------------------------------------------------------------
--- Bitwise left rotate
 function blrotate
 ------------------------------------------------------------------
+-- Bitwise left rotate
 with(x:%integer, i:%integer) do return escape
 "
 global __retval__
@@ -117,9 +117,9 @@ __retval__ = ('integer', final)
 end
 
 ------------------------------------------------------------------
--- Bitwise right rotate
 function brrotate
 ------------------------------------------------------------------
+-- Bitwise right rotate
 with(x:%integer, i:%integer) do return escape
 "
 global __retval__
@@ -138,9 +138,9 @@ __retval__ = ('integer', final)
 end
 
 ------------------------------------------------------------------
--- Set the ith bit
 function bsetbit
 ------------------------------------------------------------------
+-- Set the ith bit
 with(x:%integer, i:%integer) do return escape
 "
 global __retval__
@@ -153,9 +153,9 @@ __retval__ = ('integer', final)
 end
 
 ------------------------------------------------------------------
--- Clear the ith bit
 function bclearbit
 ------------------------------------------------------------------
+-- Clear the ith bit
 with(x:%integer, i:%integer) do return escape
 "
 global __retval__
@@ -168,9 +168,9 @@ __retval__ = ('integer' , final)
 end
 
 ------------------------------------------------------------------
--- Get the bit size
 function bsize
 ------------------------------------------------------------------
+-- Get the bit size
 with(x:%integer) do return escape
 "
 global __retval__
diff --git a/asteroid/modules/hash.ast b/asteroid/modules/hash.ast
index 07449628..c57e3366 100644
--- a/asteroid/modules/hash.ast
+++ b/asteroid/modules/hash.ast
@@ -5,16 +5,19 @@
 --
 -- (c) Lutz Hamel, University of Rhode Island
 ------------------------------------------------------------------
+load system type.
 
 ------------------------------------------------------------------
-structure __HASHTABLE__
+structure __HASH__ with
 ------------------------------------------------------------------
 -- Asteroid hash table implementation using Python dictionaries
-with
 
+------------------------------------------------------------------
 data table.
 
+------------------------------------------------------------------
 function __init__
+------------------------------------------------------------------
 -- constructor for HashTable initializes the underlying dictionary
 with none do escape
 "
@@ -29,10 +32,11 @@ this_val = state.symbol_table.lookup_sym('this')
 # store the dictionary as a foreign object in this slot
 memory[0] = ('foreign', dict())
 "
-return none
-end
+end -- __init__
 
+------------------------------------------------------------------
 function insert
+------------------------------------------------------------------
 with (name,value) do escape
 "
 this_val = state.symbol_table.lookup_sym('this')
@@ -49,10 +53,15 @@ value_val = state.symbol_table.lookup_sym('value')
 (FOREIGN, dictionary) = memory[0]
 dictionary[name_val] = value_val
 "
-return none
-end
+with item_list:%list do
+  for (k,v) in item_list do
+    this @insert (k,v).
+  end
+end -- insert
 
+------------------------------------------------------------------
 function get
+------------------------------------------------------------------
 with name do return escape
 "
 global __retval__
@@ -73,9 +82,11 @@ if name_val not in dictionary.keys():
 else:
     __retval__ = dictionary[name_val]
 "
-end
+end -- get
 
+------------------------------------------------------------------
 function aslist
+------------------------------------------------------------------
 with none do return escape
 "
 global __retval__
@@ -104,9 +115,16 @@ for (i,t) in l:
 
 __retval__ = ('list', out_list)
 "
-end
+end -- aslist
+
+------------------------------------------------------------------
+function __str__
+------------------------------------------------------------------
+with none do
+  return type @tostring (this @aslist ()).
+end -- __str__
 
-end -- __HASHTABLE__
+end -- __HASH__
 
 ------------------------------------------------------------------
 structure __HASH_MODULE__
@@ -114,7 +132,7 @@ structure __HASH_MODULE__
 with
 
 function hash with none do
-   return __HASHTABLE__().
+   return __HASH__().
 end
 
 end -- __HASH_MODULE__
diff --git a/asteroid/modules/math.ast b/asteroid/modules/math.ast
index 3ac54a59..2e89c9e7 100644
--- a/asteroid/modules/math.ast
+++ b/asteroid/modules/math.ast
@@ -14,31 +14,23 @@ structure __MATH_MODULE__ with
 ------------------------------------------------------------------
 data pi.
 data e.
-data tau.
 
 function __init__ with none do
 
-let this @pi = escape
+let this @pi = escape -- init pi constant
 "
 from math import pi
 global __retval__
 __retval__ = ('real',pi)
 "
 
-let this @e = escape
+let this @e = escape -- init e constant
 "
 from math import e
 global __retval__
 __retval__ = ('real',e)
 "
 
-let this @tau = escape
-"
-from math import tau
-global __retval__
-__retval__ = ('real',tau)
-"
-
 end -- __init__
 
 ------------------------------------------------------------------
@@ -68,7 +60,7 @@ function log
 --
 -- With two arguments, return the logarithm of x to the given base,
 -- calculated as log(x)/log(base).
-with (x) do return escape
+with x do return escape
 "
 global __retval__
 import math
@@ -77,7 +69,7 @@ val_x = state.symbol_table.lookup_sym('x')
 
 __retval__ = ('real', math.log(val_x[1]))
 "
-with (x,base) do return escape
+with (x,base:%integer) do return escape
 "
 global __retval__
 import math
@@ -131,14 +123,13 @@ end
 function abs
 ------------------------------------------------------------------
 -- Return the absolute value of x.
-with (x) do return escape
+with x do return escape
 "
 global __retval__
-import math
 
 val_x = state.symbol_table.lookup_sym('x')
 
-__retval__ = (val_x[0], math.fabs(val_x[1]))
+__retval__ = (val_x[0], abs(val_x[1]))
 "
 end
 
@@ -180,7 +171,6 @@ function gcd
 with (a:%integer,b:%integer) do return escape
 "
 global __retval__
-from asteroid.state import state
 from math import gcd
 
 val_a = state.symbol_table.lookup_sym('a')
@@ -196,8 +186,6 @@ function isclose
 ------------------------------------------------------------------
 -- Return True if the values a and b are close to each other
 -- and false otherwise.  Default tolerance 1e-09
---
--- TODO: once we have scientific notation add a tolerance parameter.
 with (a,b) do return escape
 "
 global __retval__
diff --git a/asteroid/modules/os.ast b/asteroid/modules/os.ast
new file mode 100644
index 00000000..3e5c8106
--- /dev/null
+++ b/asteroid/modules/os.ast
@@ -0,0 +1,404 @@
+------------------------------------------------------------------
+-- os.ast
+--
+-- interface to the host OS
+--
+-- (c) University of Rhode Island
+------------------------------------------------------------------
+-- modeled after the Python os, os.path, and sys modules
+------------------------------------------------------------------
+load system hash.
+
+structure __OS_MODULE__ with
+
+------------------------------------------------------------------
+-- The list of command line arguments passed to an Asteroid script. 
+-- argv[0] is the name of the Asteroid script (it is operating 
+-- system dependent whether this is a full pathname or not).
+-- In interactive mode argv[0] will be the empty string.
+data argv.
+
+------------------------------------------------------------------
+-- A hash table where keys and values are strings that represent 
+-- the process environment. For example, 
+--    os @env @get "HOME"
+--  is the pathname of your home directory (on some platforms), 
+-- and is equivalent to getenv("HOME") in C.
+data env.
+
+------------------------------------------------------------------
+-- This string contains a platform identifier.
+data platform.
+
+------------------------------------------------------------------
+function __init__ 
+------------------------------------------------------------------
+-- constructor for the __OS_MODULE__
+with none do
+   let this @argv = this @__getargv().
+   let this @platform = this @__getplatform().
+   -- construct the env hashtable
+   let l = this @__getenv(). -- list of key/value pairs
+   let this @env = hash @hash ().
+   this @env @insert l.
+end
+
+------------------------------------------------------------------
+function __getargv 
+------------------------------------------------------------------
+with none do return escape
+"
+global __retval__
+import sys
+import copy
+import os
+import os.path
+argv = copy.copy(sys.argv)
+# pop the Asteroid interpreter
+argv.pop(0)
+# pop the flags to the Asteroid interpreter
+while len(argv) > 0 and argv[0][0] == '-':
+   argv.pop(0)
+if len(argv) == 0:
+   # if in interactive mode set argv[0] to the empty string
+   argv.append('')
+else:
+   # prepend current dir
+   if not os.path.dirname(argv[0]):
+      cwd = os.getcwd()
+      argv[0] = os.path.join(cwd,argv[0])
+# turn argv into an Asteroid list of strings
+out = []
+for e in argv:
+   out.append(('string',e))
+__retval__ = ('list', out)
+"
+end -- __getargv
+
+------------------------------------------------------------------
+function __getenv
+------------------------------------------------------------------
+with none do return escape
+"
+global __retval__
+from os import environ
+# turn dictionary into an Asteroid list
+outlist_val = []
+for (k,v) in environ.items():
+   outlist_val.append(('tuple',[('string',k),('string',v)]))
+__retval__ = ('list', outlist_val)
+"
+end -- __getplatform
+
+------------------------------------------------------------------
+function __getplatform
+------------------------------------------------------------------
+with none do return escape
+"
+global __retval__
+from sys import platform
+__retval__ = ('string', platform)
+"
+end -- __getplatform
+
+------------------------------------------------------------------
+function basename
+------------------------------------------------------------------
+-- Return the base name of pathname path. This is the second element of the pair
+-- returned by passing path to the function split(). Note that the result of this
+-- function is different from the Unix basename program; where basename for '/foo/bar/'
+-- returns 'bar', the basename() function returns an empty string ('').
+with path:%string do return escape
+"
+global __retval__
+from os.path import basename
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+__retval__ = ('string', basename(path_val))
+"
+end -- basename
+
+------------------------------------------------------------------
+function chdir
+------------------------------------------------------------------
+-- Change the current working directory to path.
+with path:%string do escape
+"
+from os.path import chdir
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+chdir(path_val)
+"
+end -- chdir
+
+------------------------------------------------------------------
+function dirname
+------------------------------------------------------------------
+-- Return the directory name of pathname path. This is the first element of the 
+-- pair returned by passing path to the function split().
+with path:%string do return escape
+"
+global __retval__
+from os.path import dirname
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+__retval__ = ('string', dirname(path_val))
+"
+end -- dirname
+
+------------------------------------------------------------------
+function exists
+------------------------------------------------------------------
+-- Return true if path refers to an existing path or an open file descriptor. 
+-- Returns false for broken symbolic links. On some platforms, this function 
+-- may return False if permission is not granted to execute os.stat() on 
+-- the requested file, even if the path physically exists.
+with path:%string do return escape
+"
+global __retval__
+from os.path import exists
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+__retval__ = ('string', exists(path_val))
+"
+end -- exists
+
+------------------------------------------------------------------
+function exit
+------------------------------------------------------------------
+-- Signaling an intention to exit the interpreter.
+-- When an argument value other than none is provided
+-- it is considered a status value. If it is 
+-- an integer, zero is considered “successful termination” and any 
+-- nonzero value is considered “abnormal termination” by shells and 
+-- the like. Most systems require it to be in the range 0–127, and 
+-- produce undefined results otherwise. Some systems have a 
+-- convention for assigning specific meanings to specific exit codes, 
+-- but these are generally underdeveloped; Unix programs generally 
+-- use 2 for command line syntax errors and 1 for all other kind 
+-- of errors. If none is given as an argument value then is it
+-- is considered to be a successful exit equivalent to passing a zero. 
+-- If a string is passed then it is printed printed to 
+-- __STDERR__ and results in an exit code of 1. In particular, 
+-- sys.exit("some error message") is a quick way to exit a program 
+-- when an error occurs.
+with none do escape
+"
+import sys
+sys.exit(0)
+"
+with v:%integer do escape
+"
+import sys
+v_val = state.symbol_table.lookup_sym('v')
+sys.exit(v_val[1])
+"
+with msg:%string do escape
+"
+import sys
+msg_val = state.symbol_table.lookup_sym('msg')
+sys.exit(msg_val[1])
+"
+end
+
+------------------------------------------------------------------
+function getdir
+------------------------------------------------------------------
+-- Return a string representing the current working directory.
+with none do return escape
+"
+global __retval__
+from os import getcwd
+__retval__ = ('string', getcwd())
+"
+end -- getdir
+
+------------------------------------------------------------------
+function getpathtime
+------------------------------------------------------------------
+-- Returns a triple with (creation,access,modification) times.
+-- By default the return value is a triple of real numbers
+-- giving the number of seconds since 1/1/1970.  If the flag is set
+-- to true then a triple of strings is returned where each string
+-- represents the respective local time. Throws an exception if the file 
+-- does not exist or is inaccessible.
+with path:%string do return escape
+"
+global __retval__
+from os.path import getctime, getatime, getmtime
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+ct = ('real', getctime(path_val))
+at = ('real', getatime(path_val))
+mt = ('real', getmtime(path_val))
+__retval__ = ('tuple',[ct, at, mt])
+"
+with (path:%string,flag:%boolean) do return escape
+"
+global __retval__
+from os.path import getctime, getatime, getmtime
+from time import ctime
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+(BOOLEAN, flag_val) = state.symbol_table.lookup_sym('flag')
+
+if not flag_val:
+   ct = ('real', getctime(path_val))
+   at = ('real', getatime(path_val))
+   mt = ('real', getmtime(path_val))
+else:
+   ct = ('string', ctime(getctime(path_val)))
+   at = ('string', ctime(getatime(path_val)))
+   mt = ('string', ctime(getmtime(path_val)))
+
+__retval__ = ('tuple',[ct, at, mt])
+"
+end -- getpathtime
+
+------------------------------------------------------------------
+function getsize
+------------------------------------------------------------------
+-- Return the size, in bytes, of path. Throws exception if the file 
+-- does not exist or is inaccessible.
+with path:%string do return escape
+"
+global __retval__
+from os.path import getsize
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+__retval__ = ('integer', getsize(path_val))
+"
+end -- getsize
+
+------------------------------------------------------------------
+function isfile
+------------------------------------------------------------------
+-- Return true if path is an existing regular file. This follows 
+-- symbolic links.
+with path:%string do return escape
+"
+global __retval__
+from os.path import isfile
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+__retval__ = ('boolean', isfile(path_val))
+"
+end -- isfile
+
+------------------------------------------------------------------
+function isdir
+------------------------------------------------------------------
+-- Return true if path is an existing directory. This follows 
+-- symbolic links.
+with path:%string do return escape
+"
+global __retval__
+from os.path import isdir
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+__retval__ = ('boolean', isdir(path_val))
+"
+end -- isdir
+
+------------------------------------------------------------------
+function join
+------------------------------------------------------------------
+-- Join path1 and path2 components intelligently. The return value 
+-- is the concatenation of path and any members of *paths with 
+-- exactly one directory separator following each non-empty part 
+-- except the last, meaning that the result will only end in a 
+-- separator if the last part is empty. If the second component is an 
+-- absolute path, the first component is thrown away. 
+--
+-- On Windows, the drive letter is not reset when an absolute 
+-- path component (e.g., r'\foo') is encountered. If a component 
+-- contains a drive letter, all previous components are thrown away 
+-- and the drive letter is reset. Note that since there is a current 
+-- directory for each drive, os.path.join("c:", "foo") represents a 
+-- path relative to the current directory on drive C: (c:foo), not c:\foo.
+with (path1:%string,path2:%string) do return escape
+"
+global __retval__
+from os.path import join
+(STRING, path1_val) = state.symbol_table.lookup_sym('path1')
+(STRING, path2_val) = state.symbol_table.lookup_sym('path2')
+__retval__ = ('string', join(path1_val,path2_val))
+"
+end -- join
+
+------------------------------------------------------------------
+function split
+------------------------------------------------------------------
+-- Split the pathname path into a pair, (head, tail) where tail is 
+-- the last pathname component and head is everything leading up to 
+-- that. The tail part will never contain a slash; if path ends in 
+-- a slash, tail will be empty. If there is no slash in path, head 
+-- will be empty. If path is empty, both head and tail are empty. 
+-- Trailing slashes are stripped from head unless it is the root 
+-- (one or more slashes only). Also see the functions dirname and 
+-- basename.
+with path:%string do return escape
+"
+global __retval__
+from os.path import split
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+(head, tail) = split(path_val)
+__retval__ = ('tuple', [('string',head),('string',tail)])
+"
+end -- split
+
+------------------------------------------------------------------
+function splitdrive
+------------------------------------------------------------------
+-- Split the pathname path into a pair (drive, tail) where drive is 
+-- either a mount point or the empty string. On systems which do not 
+-- use drive specifications, drive will always be the empty string. 
+-- In all cases, drive + tail will be the same as path.
+--
+-- On Windows, splits a pathname into drive/UNC sharepoint and 
+-- relative path.
+--
+-- If the path contains a drive letter, drive will contain everything 
+-- up to and including the colon.
+with path:%string do return escape
+"
+global __retval__
+from os.path import splitdrive
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+(drive, tail) = splitdrive(path_val)
+__retval__ = ('tuple', [('string',drive),('string',tail)])
+"
+end -- splitdrive
+
+------------------------------------------------------------------
+function splitext
+------------------------------------------------------------------
+-- Split the pathname path into a pair (root, ext) such that 
+-- root + ext == path, and the extension, ext, is empty or begins 
+-- with a period and contains at most one period. If the path contains 
+-- no extension, ext will be the empty string.
+with path:%string do return escape
+"
+global __retval__
+from os.path import splitext
+(STRING, path_val) = state.symbol_table.lookup_sym('path')
+(root, ext) = splitext(path_val)
+__retval__ = ('tuple', [('string',root),('string',ext)])
+"
+end -- splitext
+
+------------------------------------------------------------------
+function syscmd
+------------------------------------------------------------------
+-- Execute a command (a string) in a subshell. This is implemented 
+-- by calling the Standard C function system(), and has the same 
+-- limitations. If command generates any output, it will be 
+-- sent to the interpreter standard output stream. 
+-- The C standard does not specify the meaning of the return value of 
+-- the C function, so the return value of this function is 
+-- system-dependent.
+with cmd:%string do return escape
+"
+global __retval__
+from os import system
+(STRING, cmd_val) = state.symbol_table.lookup_sym('cmd')
+status = sytem(cmd_val)
+__retval__ = ('integer', status)
+"
+end -- syscmd
+
+end -- __OS_MODULE__
+
+------------------------------------------------------------------
+let os = __OS_MODULE__().
diff --git a/asteroid/modules/pick.ast b/asteroid/modules/pick.ast
index bb40b348..c1f2e79f 100644
--- a/asteroid/modules/pick.ast
+++ b/asteroid/modules/pick.ast
@@ -12,20 +12,24 @@ load system random.
 structure __PICK__
 ------------------------------------------------------------------
 -- A pick object holds a list of items that
--- we can randomly pick from with the 'pick'
+-- we can randomly pick from with the 'pickitems'
 -- member function
 
   with
 
   data items.
 
-  function pick with n:%integer do
-      let l = [].
-      for i in 1 to n do
-          let ix = random @randint(0, this @items @length()-1).
-          l @append(this @items @ix).
-      end
-      return l.
+  function pickitems
+    with none do
+        let ix = random @randint(0, this @items @length()-1).
+        return this @items @ix.
+    with n:%integer do
+        let l = [].
+        for i in 1 to n do
+            let ix = random @randint(0, this @items @length()-1).
+            l @append(this @items @ix).
+        end
+        return l.
   end
 
   --make sure that we only pass lists into the constructor
diff --git a/asteroid/modules/prologue.ast b/asteroid/modules/prologue.ast
index 1f952912..8f8ceef1 100644
--- a/asteroid/modules/prologue.ast
+++ b/asteroid/modules/prologue.ast
@@ -101,7 +101,7 @@ function range
 ------------------------------------------------------------------
 function getid
 ------------------------------------------------------------------
-# get the id (physical memory address) of 'x' as an Asteroid integer
+-- get the id (physical memory address) of 'x' as an Asteroid integer
 with x do return escape
 "
 global __retval__
@@ -116,12 +116,10 @@ function isdefined
 -- return true if a variable or type name is defined in the
 -- current environment otherwise return false
 -- the variable and type name is given as a string
-with __x__ do return escape
+with __x__:%string do return escape
 "
 global __retval__
 (STRING, v)  = state.symbol_table.lookup_sym('__x__')
-if STRING != 'string':
-   raise ValueError('expected a string argument')
 try:
    state.symbol_table.lookup_sym(v)
 except ValueError:
@@ -217,8 +215,7 @@ end
 function __list_extend__
 ------------------------------------------------------------------
 -- Extend the list by appending all the items
--- from the item where item is either a list,
--- a string or a tuple.
+-- from the item where item is either a list or a tuple.
 with item do return escape
 "
 global __retval__
@@ -226,7 +223,7 @@ global __retval__
 this_val = state.symbol_table.lookup_sym('this')
 item_val = state.symbol_table.lookup_sym('item')
 
-if item_val[0] not in ['list', 'string', 'tuple']:
+if item_val[0] not in ['list', 'tuple']:
     raise ValueError('extend expected a list, string, or tuple, got \'{}\''
                 .format(item_val[0]))
 
diff --git a/asteroid/modules/random.ast b/asteroid/modules/random.ast
index f160997e..6deaedbf 100644
--- a/asteroid/modules/random.ast
+++ b/asteroid/modules/random.ast
@@ -28,7 +28,7 @@ end
 function randint -- random interval
 ------------------------------------------------------------------
 -- return a random value N in the interval lo <= N <= hi.
--- The of the random value depends on the types of the
+-- The type of the random value depends on the types of the
 -- values specifying the interval.
 with (lo:%integer,hi:%integer) do return escape
 "
diff --git a/asteroid/modules/set.ast b/asteroid/modules/set.ast
index a3885203..af69f9a5 100644
--- a/asteroid/modules/set.ast
+++ b/asteroid/modules/set.ast
@@ -14,49 +14,49 @@ structure __SET_MODULE__
 with
 
 ------------------------------------------------------------------
-function toset
+function diff
 ------------------------------------------------------------------
-with (lst:%list) do return escape
+with (a:%list,b:%list) do return escape
 "
 global __retval__
-lst_val = state.symbol_table.lookup_sym('lst')
-__retval__ = ('list', list(set(lst_val[1])))
+a_val = state.symbol_table.lookup_sym('a')
+b_val = state.symbol_table.lookup_sym('b')
+__retval__ = ('list', list(set(a_val[1]) - set(b_val[1])))
 "
 end
 
 ------------------------------------------------------------------
-function diff
+function intersection
 ------------------------------------------------------------------
 with (a:%list,b:%list) do return escape
 "
 global __retval__
 a_val = state.symbol_table.lookup_sym('a')
 b_val = state.symbol_table.lookup_sym('b')
-__retval__ = ('list', list(set(a_val[1]) - set(b_val[1])))
+__retval__ = ('list', list(set(a_val[1]) & set(b_val[1])))
 "
 end
 
 ------------------------------------------------------------------
-function union
+function toset
 ------------------------------------------------------------------
-with (a:%list,b:%list) do return escape
+with (lst:%list) do return escape
 "
 global __retval__
-a_val = state.symbol_table.lookup_sym('a')
-b_val = state.symbol_table.lookup_sym('b')
-__retval__ = ('list', list(set(a_val[1]) | set(b_val[1])))
+lst_val = state.symbol_table.lookup_sym('lst')
+__retval__ = ('list', list(set(lst_val[1])))
 "
 end
 
 ------------------------------------------------------------------
-function intersection
+function union
 ------------------------------------------------------------------
 with (a:%list,b:%list) do return escape
 "
 global __retval__
 a_val = state.symbol_table.lookup_sym('a')
 b_val = state.symbol_table.lookup_sym('b')
-__retval__ = ('list', list(set(a_val[1]) & set(b_val[1])))
+__retval__ = ('list', list(set(a_val[1]) | set(b_val[1])))
 "
 end
 
diff --git a/asteroid/modules/stream.ast b/asteroid/modules/stream.ast
index b2c4a109..020c3f0e 100644
--- a/asteroid/modules/stream.ast
+++ b/asteroid/modules/stream.ast
@@ -25,6 +25,11 @@ function __init__
     let this @curr_ix = 0.
   end
 
+function append
+  with item do
+    this @stream @append item.
+  end
+
 function eof
   with none do
     if this @curr_ix == this @stream @length() do
@@ -34,15 +39,6 @@ function eof
     end
   end
 
-function peek
-  with none do
-    if this @eof() do
-      return none.
-    else do
-      return this @stream @(this @curr_ix).
-    end
-  end
-
 function get
   with none do
     if this @eof() do
@@ -54,11 +50,6 @@ function get
     end
   end
 
-function rewind
-  with none do
-    let this @curr_ix = 0.
-  end
-
 function map
   with f:%function do
     for i in range(this @stream @length()) do
@@ -66,9 +57,18 @@ function map
     end
   end
 
-function append
-  with item do
-    this @stream @append item.
+function peek
+  with none do
+    if this @eof() do
+      return none.
+    else do
+      return this @stream @(this @curr_ix).
+    end
+  end
+
+function rewind
+  with none do
+    let this @curr_ix = 0.
   end
 
 function __string__
diff --git a/asteroid/modules/type.ast b/asteroid/modules/type.ast
index 91d716bf..a943504c 100644
--- a/asteroid/modules/type.ast
+++ b/asteroid/modules/type.ast
@@ -47,45 +47,68 @@ structure __TYPE_MODULE__ with
 ------------------------------------------------------------------
 
 ------------------------------------------------------------------
-function tointeger
+function tobase
 ------------------------------------------------------------------
-with (item:%string,base:%integer) do return escape
+-- represent the given integer x as a numeral in different bases
+with (x:%integer,base:%integer) do return escape
 "
 global __retval__
-item_val = state.symbol_table.lookup_sym('item')
+
+x_val = state.symbol_table.lookup_sym('x')
 base_val = state.symbol_table.lookup_sym('base')
-__retval__ = ('integer', int(item_val[1], base=base_val[1]))
+
+if base_val[1] == 2:
+  __retval__ = ('string', format(x_val[1],'b'))
+elif base_val[1] == 8:
+  __retval__ = ('string', format(x_val[1],'o'))
+elif base_val[1] == 16:
+  __retval__ = ('string', format(x_val[1],'X'))
+else:
+  raise ValueError('illegal base value {}'
+          .format(base_val[1]))
 "
+end
+
+------------------------------------------------------------------
+function toboolean
+------------------------------------------------------------------
 with item do return escape
 "
 global __retval__
 
 item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('integer', int(item_val[1]))
+__retval__ = ('boolean', bool(item_val[1]))
 "
 end
 
 ------------------------------------------------------------------
-function toreal
+function tointeger
 ------------------------------------------------------------------
+with (item:%string,base:%integer) do return escape
+"
+global __retval__
+item_val = state.symbol_table.lookup_sym('item')
+base_val = state.symbol_table.lookup_sym('base')
+__retval__ = ('integer', int(item_val[1], base=base_val[1]))
+"
 with item do return escape
 "
 global __retval__
 
 item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('real', float(item_val[1]))
+__retval__ = ('integer', int(item_val[1]))
 "
 end
 
 ------------------------------------------------------------------
-function toboolean
+function toreal
 ------------------------------------------------------------------
 with item do return escape
 "
 global __retval__
 
 item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('boolean', bool(item_val[1]))
+__retval__ = ('real', float(item_val[1]))
 "
 end
 
@@ -166,29 +189,6 @@ with l:%integer do
   return __STRINGFORMAT__(l).
 end
 
-------------------------------------------------------------------
-function tobase
-------------------------------------------------------------------
--- represent the given integer x as a numeral in different bases
-with (x:%integer,base:%integer) do return escape
-"
-global __retval__
-
-x_val = state.symbol_table.lookup_sym('x')
-base_val = state.symbol_table.lookup_sym('base')
-
-if base_val[1] == 2:
-  __retval__ = ('string', format(x_val[1],'b'))
-elif base_val[1] == 8:
-  __retval__ = ('string', format(x_val[1],'o'))
-elif base_val[1] == 16:
-  __retval__ = ('string', format(x_val[1],'X'))
-else:
-  raise ValueError('illegal base value {}'
-          .format(base_val[1]))
-"
-end
-
 ------------------------------------------------------------------
 -- TYPE QUERY FUNCTIONS --
 ------------------------------------------------------------------
@@ -201,29 +201,35 @@ with item do
 end
 
 ------------------------------------------------------------------
-function isscalar
+function isnone
 ------------------------------------------------------------------
-with item do
-  return (item is %integer) or (item is %real).
+with x do
+  return x is %none.
 end
 
 ------------------------------------------------------------------
-function isnone
+function isscalar
 ------------------------------------------------------------------
-with x do
-  return x is %none.
+with item do
+  return (item is %integer) or (item is %real).
 end
 
 ------------------------------------------------------------------
 function gettype
 ------------------------------------------------------------------
-# get the type of 'x' as an Asteroid string
+-- get the type of 'x' as an Asteroid string
 with x do return escape
 "
 global __retval__
 val = state.symbol_table.lookup_sym('x')
 if val[0] == 'object':
   (OBJECT, (STRUCT_ID, (ID, x_type)), OBJECT_MEMORY) = val
+elif val[0] in ['function-val','member-function-val']:
+  # internally we store functions as function values
+  # but to the user these look like functions as the 
+  # type counter part to the %function type pattern
+  # will match both function-val and member-function-val
+  x_type = 'function'
 else:
   x_type = val[0]
 __retval__ = ('string', x_type)
diff --git a/asteroid/modules/util.ast b/asteroid/modules/util.ast
index 5fd74165..7698a8ff 100644
--- a/asteroid/modules/util.ast
+++ b/asteroid/modules/util.ast
@@ -9,26 +9,47 @@
 load system type.
 
 ------------------------------------------------------------------
-structure __UTIL_MODULE__ with
+structure __UTIL_MODULE__ 
+------------------------------------------------------------------
+with
 
 ------------------------------------------------------------------
--- UTILITY FUNCTIONS --
+function achar
 ------------------------------------------------------------------
+-- given a decimal ASCII code return the corresponding character symbol
+with item:%integer do return escape
+"
+global __retval__
+item_val = state.symbol_table.lookup_sym('item')
+__retval__ = ('string', str(chr(item_val[1])))
+"
+end
 
 ------------------------------------------------------------------
-function exit
+function ascii
 ------------------------------------------------------------------
-with none do escape
+-- given a char return the corresponding ASCII code.
+with item:%string do return escape
 "
-import sys
-sys.exit(1)
+global __retval__
+item_val = state.symbol_table.lookup_sym('item')
+__retval__ = ('integer', ord(item_val[1]))
 "
-with msg:%string do escape
+end
+
+------------------------------------------------------------------
+function cls
+------------------------------------------------------------------
+-- clear screen
+with none do escape
 "
-import sys
-msg_val = state.symbol_table.lookup_sym('msg')
-print(msg_val[1])
-sys.exit(1)
+import os
+import platform
+
+if platform.win32_ver()[0]:
+    os.system('cls')
+else:
+    os.system('clear')
 "
 end
 
@@ -46,18 +67,17 @@ __retval__ = copy.deepcopy(obj_val)
 end
 
 ------------------------------------------------------------------
-function cls
+function ctime
 ------------------------------------------------------------------
--- clear screen
-with none do escape
+-- Converts the time as a real value in secs since 1/1/1970 into
+-- string representing local time.
+with t:%real do return escape
 "
-import os
-import platform
+global __retval__
+from time import ctime
+(REAL, t_val) = state.symbol_table.lookup_sym('t')
 
-if platform.win32_ver()[0]:
-    os.system('cls')
-else:
-    os.system('clear')
+__retval__ = ('string', ctime(t_val))
 "
 end
 
@@ -67,33 +87,21 @@ function sleep
 -- program sleep for secs seconds
 with secs if type @isscalar(secs) do escape
 "
-import time
+from time import sleep
 secs_val = state.symbol_table.lookup_sym('secs')
-time.sleep(secs_val[1])
+sleep(secs_val[1])
 "
 end
 
 ------------------------------------------------------------------
-function zip
+function time
 ------------------------------------------------------------------
--- implements Python's zip function
-with (list1:%list,list2:%list) do return escape
+-- Returns the local time as a real value in secs since 1/1/1970
+with none do return escape
 "
 global __retval__
-
-list1_val = state.symbol_table.lookup_sym('list1')
-list2_val = state.symbol_table.lookup_sym('list2')
-
-# zip it with Python's zip
-l = list(zip(list1_val[1], list2_val[1]))
-
-# turn Python tuples into Asteroid tuples and
-# put them onto an output list
-out_list = []
-for (i,t) in l:
-  out_list.append(('tuple',[i,t]))
-
-__retval__ = ('list', out_list)
+from time import time
+__retval__ = ('real', time())
 "
 end
 
@@ -119,26 +127,26 @@ __retval__ = ('tuple', [('list', c1list), ('list',c2list)])
 end
 
 ------------------------------------------------------------------
-function ascii
+function zip
 ------------------------------------------------------------------
--- given a char return the corresponding ASCII code.
-with item:%string do return escape
+-- implements Python's zip function
+with (list1:%list,list2:%list) do return escape
 "
 global __retval__
-item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('integer', ord(item_val[1]))
-"
-end
 
-------------------------------------------------------------------
-function achar
-------------------------------------------------------------------
--- given a decimal ASCII code return the corresponding character symbol
-with item:%integer do return escape
-"
-global __retval__
-item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('string', str(chr(item_val[1])))
+list1_val = state.symbol_table.lookup_sym('list1')
+list2_val = state.symbol_table.lookup_sym('list2')
+
+# zip it with Python's zip
+l = list(zip(list1_val[1], list2_val[1]))
+
+# turn Python tuples into Asteroid tuples and
+# put them onto an output list
+out_list = []
+for (i,t) in l:
+  out_list.append(('tuple',[i,t]))
+
+__retval__ = ('list', out_list)
 "
 end
 
diff --git a/asteroid/modules/vector.ast b/asteroid/modules/vector.ast
index 2f8716cd..4d00802a 100644
--- a/asteroid/modules/vector.ast
+++ b/asteroid/modules/vector.ast
@@ -12,6 +12,28 @@ load system type.
 ------------------------------------------------------------------
 structure __VECTOR_MODULE__ with
 
+------------------------------------------------------------------
+function add
+------------------------------------------------------------------
+with (a,b) do
+  return this @op(lambda with (x,y) do return x+y,a,b).
+end
+
+------------------------------------------------------------------
+function dot
+-- computes the dot product of two lists
+------------------------------------------------------------------
+with (a:%list,b:%list) do
+  return this @mult(a,b) @reduce(lambda with (x,y) do return x+y).
+end
+
+------------------------------------------------------------------
+function mult
+------------------------------------------------------------------
+with (a,b) do
+  return this @op(lambda with (x,y) do return x*y,a,b).
+end
+
 ------------------------------------------------------------------
 function op
 ------------------------------------------------------------------
@@ -35,13 +57,6 @@ with (f:%function,a if type @isscalar(a),b:%list) do
   return v @map(f).
 end
 
-------------------------------------------------------------------
-function add
-------------------------------------------------------------------
-with (a,b) do
-  return this @op(lambda with (x,y) do return x+y,a,b).
-end
-
 ------------------------------------------------------------------
 function sub
 ------------------------------------------------------------------
@@ -49,20 +64,6 @@ with (a,b) do
   return this @op(lambda with (x,y) do return x-y,a,b).
 end
 
-------------------------------------------------------------------
-function mult
-------------------------------------------------------------------
-with (a,b) do
-  return this @op(lambda with (x,y) do return x*y,a,b).
-end
-
-------------------------------------------------------------------
-function dot
--- computes the dot product of two lists
-------------------------------------------------------------------
-with (a:%list,b:%list) do
-  return this @mult(a,b) @reduce(lambda with (x,y) do return x+y).
-end
 
 end -- __VECTOR_MODULE__
 
diff --git a/asteroid/programs/dogs.ast b/asteroid/programs/dogs.ast
index 3b2c4532..0b81cf4b 100644
--- a/asteroid/programs/dogs.ast
+++ b/asteroid/programs/dogs.ast
@@ -2,32 +2,33 @@ load system io.
 load system type.
 
 structure Dog with
-
   data name.
-  data tricks.
-
-  function add_trick
-    with new_trick:%string do
-      this @tricks @append new_trick.
-    end
-
-  function __init__
-    with name:%string do
-      let this @name = name.
-      let this @tricks = [].
-    end
+  data tricks. -- list of trick strings
+end
 
-  end
+let fido = Dog ("Fido",["play dead","fetch"]).
+let buddy = Dog ("Buddy",["sit stay","roll over"]).
 
-let fido = Dog "Fido".
-fido @add_trick "play dead".
-fido @add_trick "fetch".
+-- print out all the dogs that know how to fetch
+-- we do this with first class pattern defines a dog 
+-- that knows how to fetch, we use regular expression 
+-- matching on the trick list
+let fetcher = pattern %[(Dog(name,tricks) 
+                          if type @tostring tricks is ".*fetch.*")]%.
+
+-- one way to do this
+for (Dog(name,tricks) if Dog(name,tricks) is *fetcher) in [fido,buddy] do
+    io @println (name+" knows how to fetch").
+end
 
-let buddy = Dog "Buddy".
-buddy @add_trick "sit stay".
-buddy @add_trick "roll over".
+-- another way to do this
+for ((d:Dog(name,tricks)) if d is *fetcher) in [fido,buddy] do
+    io @println (name+" knows how to fetch").
+end
 
--- print out all the dogs that know how to fetch
-for (Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*") in [fido,buddy] do
+-- yet another way of doing this
+for (*fetcher bind name) in [fido,buddy] do
     io @println (name+" knows how to fetch").
 end
+
+
diff --git a/asteroid/state.py b/asteroid/state.py
index 605cfeac..f32a7157 100644
--- a/asteroid/state.py
+++ b/asteroid/state.py
@@ -15,7 +15,6 @@ def initialize(self,module="<input>"):
         self.modules = [] # loaded modules
         self.AST = None
         self.ignore_pattern = 0 # used to evaluate pattern expressions
-        self.constraint_lvl = 0 # used to evaluate constraint-only patterns
         self.cond_warning = False # used to indicate if conditional subsumption
                                   # warning has been displayed
         self.eval_redundancy = True
@@ -23,6 +22,10 @@ def initialize(self,module="<input>"):
         # stack of 3-tuples for stack trace of function
         # calls: (module,lineno,function name)
         self.trace_stack = [(module,1,"<toplevel>")]
+        # if an exception occurs then error_trace will point to
+        # it.  an exception handler is responsible for clearing
+        # this.
+        self.error_trace = None
 
 state = State()
 
@@ -31,10 +34,15 @@ def warning(str):
     print("Warning: {}: {}: {}".format(module, lineno, str))
 
 def dump_trace():
-    if len(state.trace_stack) == 1:
-        return
+    if state.error_trace:
+        _dump_trace(state.error_trace)
+        return        
     else:
-        print("traceback (most recent call last):")
-        for i in range(0,len(state.trace_stack)):
-            (module,lineno,fname) = state.trace_stack[i]
-            print("{}: {}: calling {}".format(module,lineno,fname))
+        _dump_trace(state.trace_stack)
+        return
+
+def _dump_trace(trace):
+    print("traceback (most recent call last):")
+    for i in range(0,len(trace)):
+        (module,lineno,fname) = trace[i]
+        print("{}: {}: calling {}".format(module,lineno,fname))
diff --git a/asteroid/support.py b/asteroid/support.py
index 31853916..ac3e59e6 100644
--- a/asteroid/support.py
+++ b/asteroid/support.py
@@ -239,13 +239,37 @@ def term2string(term):
         (OBJECT,
          (STRUCT_ID, (ID, struct_id)),
          (OBJECT_MEMORY, (LIST, object_memory))) = term
-        data_memory = data_only(object_memory)
-        term_string = struct_id + '('
-        for ix in range(0, len(data_memory)):
-            term_string += term2string(data_memory[ix])
-            term_string += ',' if ix != len(data_memory)-1 else ''
-        term_string += ')'
-        return term_string
+
+        struct_val = state.symbol_table.lookup_sym(struct_id)
+
+        (STRUCT,
+            (MEMBER_NAMES, (LIST, member_names)),
+            (STRUCT_MEMORY, (LIST, struct_memory))) = struct_val
+
+        # if __str__ function exists for this object use it
+        if '__str__' in member_names:
+            slot_ix = member_names.index('__str__')
+            str_fval = object_memory[slot_ix]
+            # calling a __str__ member function
+            import walk
+            # for some reason we have to reinitialize unify again
+            if walk.debugging:
+                walk.unify = walk.debug_unify
+            else:
+                walk.unify = walk.__unify
+            (STRING, obj_str) = walk.handle_call(term, # object reference
+                                    str_fval,
+                                    ('none', None),
+                                    'member function __str__')
+            return obj_str
+        else:
+            data_memory = data_only(object_memory)
+            term_string = struct_id + '('
+            for ix in range(0, len(data_memory)):
+                term_string += term2string(data_memory[ix])
+                term_string += ',' if ix != len(data_memory)-1 else ''
+            term_string += ')'
+            return term_string
 
     elif TYPE in ['function-val', 'member-function-val']:
         return '(function ...)'
@@ -341,14 +365,18 @@ def term2string(term):
         return term_string
 
     elif TYPE == 'constraint':          # Handle a constraint-only pattern
-        (CONSTRAINT,ptrn) = term
+        (CONSTRAINT,ptrn,bl) = term
+        if bl[0] != 'nil':
+            raise ValueError("term2string: binding term lists not supported")
         term_string = '%['
         term_string += term2string(ptrn)
         term_string += ']%'
         return term_string
 
     elif TYPE == 'deref':               # Handle a first-class pattern
-        (DEREF, d_exp) = term
+        (DEREF, d_exp, binding_list) = term
+        if binding_list[0] != 'nil':
+            raise ValueError("internal error: binding lists in term2string not supported")
         term_string = "*" + term2string(d_exp)
 
         #Get the actual pattern from the symbol table
diff --git a/asteroid/version.py b/asteroid/version.py
index 6626f8c7..9e7dbc25 100644
--- a/asteroid/version.py
+++ b/asteroid/version.py
@@ -5,4 +5,4 @@
 # (c) University of Rhode Island
 ##########################################################################################
 
-VERSION = "1.1.3"
+VERSION = "1.1.4"
diff --git a/asteroid/walk.py b/asteroid/walk.py
index d8995ab5..c91ba8c5 100644
--- a/asteroid/walk.py
+++ b/asteroid/walk.py
@@ -4,7 +4,7 @@
 # (c) University of Rhode Island
 #########################################################################
 
-from copy import deepcopy
+from copy import deepcopy,copy
 from re import match as re_match
 
 from asteroid.globals import *
@@ -120,7 +120,7 @@ def __unify(term, pattern, unifying = True ):
     
     elif ((not unifying) and (term[0] == 'named-pattern')):
 
-        # Unpack a term-side name-pattern if evaluating redundant clauses
+        # Unpack a term-side named-pattern if evaluating redundant clauses
         message_explicit("Evaluating named pattern", notify=True)
         return unify(term[2],pattern,unifying)
 
@@ -161,15 +161,17 @@ def __unify(term, pattern, unifying = True ):
         message_explicit("Objects matched", decrease=True)
         return unifiers
 
-    elif pattern[0] == 'string' and term[0] != 'string':
+    # no implicit type conversions during pattern matching
+    # removing this code, see the discussion in issue 95
+    # elif pattern[0] == 'string' and term[0] != 'string':
         # regular expression applied to a non-string structure
         # this is possible because all data types are subtypes of string
-        message_explicit("Matching string {} and non-string {}",
-            [gen_t2s(pattern), gen_t2s(term)],
-            notify=True
-        )
-
-        return unify(term2string(term), pattern[1])
+    #    message_explicit("Matching string {} and non-string {}",
+    #        [gen_t2s(pattern), gen_t2s(term)],
+    #        notify=True
+    #    )
+    #
+    #    return unify(term2string(term), pattern[1])
 
     elif pattern[0] == 'if-exp':
 
@@ -201,17 +203,11 @@ def __unify(term, pattern, unifying = True ):
 
         unifiers = unify(term, pexp, unifying)
 
-        if state.constraint_lvl:
-            state.symbol_table.push_scope({})
-
         # evaluate the conditional expression in the
         # context of the unifiers.
         declare_unifiers(unifiers)
         bool_val = map2boolean(walk(cond_exp))
 
-        if state.constraint_lvl:
-            state.symbol_table.pop_scope()
-
         if bool_val[1]:
             message_explicit("Condition met, {}",
                 [gen_t2s(cond_exp)], decrease=True
@@ -349,7 +345,12 @@ def __unify(term, pattern, unifying = True ):
             [gen_t2s(term), gen_t2s(p), gen_t2s(name_exp)],
             notify=True, increase=True
         )
-        # name_exp can be an id or an index expression.
+        # name_exp has to be an id or an index expression.
+        if name_exp[0] not in ['id','index']:
+            raise ValueError(
+                "expected a variable, list element, or data member in named pattern\
+                 instead of {}".format(term2string(name_exp)))
+
         unifiers = unify(term, p, unifying) + [(name_exp, term)]
         
         message_explicit("Matched ({} and {})", 
@@ -518,7 +519,7 @@ def __unify(term, pattern, unifying = True ):
                 message_explicit("Success!", level="secondary")
                 return unifier
 
-    elif pattern[0] == 'deref':  # ('deref', v)
+    elif pattern[0] == 'deref':  # ('deref', v, bl)
         # v can be an AST representing any computation
         # that produces a pattern.
 
@@ -526,6 +527,18 @@ def __unify(term, pattern, unifying = True ):
 
         p = walk(pattern[1])
 
+        if pattern[2][0] != 'nil': # we have a binding term list
+            if p[1][0] != 'constraint':
+                raise ValueError(
+                    "binding term lists only supported for constraint patterns")
+            else: 
+                # construct a new constraint pattern with the binding term list in place
+                p = ('pattern',
+                        ('constraint',
+                            p[1][1],
+                            pattern[2]))
+
+
         message_explicit("{} -> {}", [gen_t2s(pattern), gen_t2s(p)], 
             level="secondary")
 
@@ -558,12 +571,31 @@ def __unify(term, pattern, unifying = True ):
             notify=True, increase=True
         )
 
-        state.constraint_lvl += 1
-        unifier = unify(term,pattern[1])
-        state.constraint_lvl -= 1
+        p = pattern[1]
+        bl = pattern[2] # binding term list
+
+        # constraint patterns are evaluated in their own scope
+        state.symbol_table.push_scope({})
+        unifier = unify(term,p)
+        state.symbol_table.pop_scope()
 
         message_explicit("[End] constraint pattern", decrease=True)
-        return [] #Return an empty unifier
+
+        # process binding list
+        if bl[0] == 'nil':
+            return [] #Return an empty unifier
+        else:
+            # binding list is non-empty, map variables
+            # that appear in the binding list into
+            # the returned unifier
+            new_unifier = []
+            for u in unifier:
+                ((ID,x),exp) = u
+                for bt in bl[1]:
+                    (BINDING_TERM, (ID,y), new_id) = bt
+                    if x == y:
+                        new_unifier += [(new_id,exp)]
+            return new_unifier
 
     elif term[0] != pattern[0]:  # nodes are not the same
         message_explicit("Fail: {} and {} are not the same",
@@ -941,6 +973,15 @@ def handle_builtins(node):
         else:
             raise ValueError("unknown builtin unary operation '{}'".format(opname))
 
+#########################################################################
+def pop_stackframe(error_trace=False): 
+    # pop frame off the stack
+    state.symbol_table.pop_scope()
+    state.symbol_table.set_config(state.symbol_table.saved_configs.pop())
+    if error_trace:
+        state.error_trace = copy(state.trace_stack)
+    state.trace_stack.pop()
+
 #########################################################################
 def handle_call(obj_ref, fval, actual_val_args, fname):
     # Needed for later
@@ -1050,19 +1091,11 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
     # Reset settings
     except RedundantPatternFound as r:
         debugging = old_debugging
-
-        # coming back from a function call - restore caller's env
+        # restore caller's env
         state.lineinfo = old_lineinfo
-
         # Keep debugger up to date
-        if debugging:
-            debugger.set_lineinfo(state.lineinfo)
-
-        state.symbol_table.pop_scope()
-        state.symbol_table.set_config(state.symbol_table.saved_configs.pop())
-
-        state.trace_stack.pop()
-
+        if debugging: debugger.set_lineinfo(state.lineinfo)
+        pop_stackframe()
         raise r
 
     # execute the function
@@ -1089,17 +1122,20 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
         function_return_value.pop()
         return_value = val.value
 
-    # coming back from a function call - restore caller's env
+    except Exception as e:
+        # we got some other kind of exception within the function call
+        # clean up our runtime stack and rethrow
+        # Note: do not reset lineinfo, this way the state points at the source 
+        # of the exception
+        pop_stackframe(error_trace=True)
+        raise e
+
+    # all done with function call -- clean up and exit
+    # restore caller's env
     state.lineinfo = old_lineinfo
-
     # Keep debugger up to date
     if debugging: debugger.set_lineinfo(state.lineinfo)
-
-    state.symbol_table.pop_scope()
-    state.symbol_table.set_config(state.symbol_table.saved_configs.pop())
-
-    state.trace_stack.pop()
-
+    pop_stackframe()
     message_explicit("Return: {} from {}",
             [("None" if (not return_value[1]) else gen_t2s(return_value)), 
             fname],
@@ -1331,6 +1367,8 @@ def try_stmt(node):
         except PatternMatchFailed:
             pass
         else:
+            # handler found - null out error_trace
+            state.error_trace = None
             declare_unifiers(unifiers)
             walk_stmt_list(catch_stmts, step_state=stepping)
             return
@@ -1406,10 +1444,9 @@ def for_stmt(node):
 
     # expand the list_term
     (LIST_TYPE, list_val) = walk(list_term)
-    if LIST_TYPE not in ['list','string']:
-        raise ValueError("only iteration over strings and lists is supported")
+    if LIST_TYPE not in ['list','string','tuple']:
+        raise ValueError("iteration not supported for type '{}'".format(LIST_TYPE))
 
-    # we allow iteration over two types of structures: (1) lists (2) strings
     # if it is a string turn the list_val into a list of Asteroid characters.
     if LIST_TYPE == 'string':
         new_list = []
@@ -1535,26 +1572,35 @@ def eval_exp(node):
 
     (EVAL, exp) = node
     assert_match(EVAL, 'eval')
-    # lhh
-    #print("in eval with {}".format(node))
-
+ 
     # Note: eval is essentially a macro call - that is a function
     # call without pushing a symbol table record.  That means
     # we have to first evaluate the argument to 'eval' before
     # walking the term.  This is safe because if the arg is already
     # the actual term it will be quoted and nothing happens if it is
     # a variable it will be expanded to the actual term.
-    #lhh
-    #print("before expand: {}".format(exp))
+
+    state.trace_stack.append((state.lineinfo[0],
+                              state.lineinfo[1],
+                              "eval"))
+
+
+    # evaluate actual parameter
     exp_val_expand = walk(exp)
-    #lhh
-    #print("after expand: {}".format(exp_val_expand))
+
     # now walk the actual term
-    state.ignore_pattern += 1
-    exp_val = walk(exp_val_expand)
-    #lhh
-    #print("after walk: {}".format(exp_val))
-    state.ignore_pattern -= 1
+    if exp_val_expand[0] == 'string':
+        import frontend
+        parser = frontend.Parser(filename="<eval>")
+        eval_ast = parser.parse(exp_val_expand[1])
+        walk(eval_ast)
+        exp_val = function_return_value[-1]
+    else:
+        state.ignore_pattern += 1
+        exp_val = walk(exp_val_expand)
+        state.ignore_pattern -= 1
+
+    state.trace_stack.pop()
     return exp_val
 
 #########################################################################
@@ -1867,14 +1913,9 @@ def process_lineinfo(node):
 #########################################################################
 def deref_exp(node):
 
-    (DEREF, id_exp) = node
-    assert_match(DEREF, 'deref')
-
     # deref operators are only meaningful during pattern matching
-    # ignore during a value walk.
-    # NOTE: the second walk is necessary to interpret what we retrieved
-    # through the indirection
-    return walk(walk(id_exp))
+    # it is an error to have the deref operator appear in an expression
+    raise ValueError("dereferencing patterns is not valid in expressions.")
 
 #########################################################################
 def constraint_exp(node):
@@ -1882,11 +1923,9 @@ def constraint_exp(node):
     # Constraint-only pattern matches should not exist where only an
     # expression is expected. If we get here, we have come across this
     # situation.
-    # A constraint-only pattern match AST cannot be walked and therefor
+    # A constraint-only pattern match AST cannot be walked and therefore
     # we raise an error.
-    raise ValueError(
-        "constraint pattern: '{}' cannot be used as a constructor."
-        .format(term2string(node)))
+    raise ValueError("a constraint pattern cannot be used as an expression.")
 
 #########################################################################
 def set_ret_val(node):
@@ -2017,6 +2056,8 @@ def debug_walk(node, dbg):
 
 # a dictionary to associate tree nodes with node functions
 dispatch_dict = {
+    # Note: statement lists are now handled by separate functions outside
+    #       the walk function
     # statements - statements do not produce return values
     'lineinfo'      : process_lineinfo,
     'set-ret-val'   : set_ret_val,
diff --git a/docs/ADB.rst b/docs/ADB.rst
index 50abc4d2..0fc35f7a 100644
--- a/docs/ADB.rst
+++ b/docs/ADB.rst
@@ -1,21 +1,18 @@
+..
+    /******************************************************************
+    This is the source file from which the action doc is generated.
+    We use cpp to insert live code snippets into the document.
+    In order to generate the action doc run the following command
+    on a Unix-like system:
 
+    cpp -w -P "ADB.txt" > "ADB.rst"
 
-
-
-
-
-
-
-
-
-
-
-
+    ******************************************************************/
+..
+   /* header for generated .rst files */
 
 ..
    *** DO NOT EDIT; MACHINE GENERATED ***
-
-
 ===================
 ADB Reference Guide
 ===================
diff --git a/docs/ADB.txt b/docs/ADB.txt
index 5318b9e4..2153a9e7 100644
--- a/docs/ADB.txt
+++ b/docs/ADB.txt
@@ -1,12 +1,14 @@
-/******************************************************************
-  This is the source file from which the action doc is generated.
-  We use cpp to insert live code snippets into the document.
-  In order to generate the action doc run the following command
-  on a Unix-like system:
+..
+    /******************************************************************
+    This is the source file from which the action doc is generated.
+    We use cpp to insert live code snippets into the document.
+    In order to generate the action doc run the following command
+    on a Unix-like system:
 
-  cpp -w -P "ADB.txt" > "ADB.rst"
+    cpp -w -P "ADB.txt" > "ADB.rst"
+
+    ******************************************************************/
 
- ******************************************************************/
 #include "header.txt"
 
 ===================
diff --git a/docs/Asteroid in Action.rst b/docs/Asteroid in Action.rst
index 915c28ed..24152c0e 100644
--- a/docs/Asteroid in Action.rst
+++ b/docs/Asteroid in Action.rst
@@ -1,21 +1,18 @@
+..
+    /******************************************************************
+    This is the source file from which the action doc is generated.
+    We use cpp to insert live code snippets into the document.
+    In order to generate the action doc run the following command
+    on a Unix-like system:
 
+    cpp -w -P "Asteroid in Action.txt" > "Asteroid in Action.rst"
 
-
-
-
-
-
-
-
-
-
-
-
+    ******************************************************************/
+..
+   /* header for generated .rst files */
 
 ..
    *** DO NOT EDIT; MACHINE GENERATED ***
-
-
 .. highlight:: none
 
 Asteroid in Action
@@ -36,7 +33,6 @@ The canonical ``Hello, World!`` program.  The easiest way to write this in Aster
   load system io.
 
   io @println "Hello, World!".
-
 Output::
 
     Hello, World!
@@ -55,21 +51,17 @@ Here is our first solution using a separate function for each of the steps,
   io @print ("Enter your name: ").
   let name = io @input().
   io @print ("Hello, "+name+"!").
-
-
 Letting the function ``input`` do the prompting,
 ::
   load system io.
 
   let name = io @input("Enter your name: ").
   io @println ("Hello, "+name+"!").
-
 Doing everything in one step,
 ::
   load system io.
 
   io @println ("Hello, "+io @input("Enter your name: ")+"!").
-
 Challenge: String length
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -81,7 +73,6 @@ In order to print the length of a string we can use the function ``len`` availab
 
   load "util".
   io @println (len("Hello!")).
-
 Output::
 
     6
@@ -92,7 +83,6 @@ We can also use the string member function ``length`` in order to compute the le
   load system io.
 
   io @println ("Hello!" @length()).
-
 Output::
 
     6
@@ -121,7 +111,6 @@ Finally we use the ``reduce`` function to map a list with repeated digits to a l
                         @reduce(unique,[]).
   io @println digits.
   assert(digits == ["1","2","3"]).
-
 Output::
 
     [1,2,3]
@@ -146,7 +135,6 @@ We use the ``explode`` function to turn a string into a list of characters. Then
                             @join("").
   io @println str.
   assert(str == "!dlroW ,olleH").
-
 Output::
 
     !dlroW ,olleH
@@ -162,7 +150,6 @@ Challenge: Removing blanks from a string
                                           @replace("  ","").
   io @println str.
   assert(str == "Hello, World!").
-
 Output::
 
     Hello, World!
@@ -198,7 +185,6 @@ with a capital letter.
                       @join("").
   io @println camel_str.
   assert(camel_str == "OnceUponATime").
-
 Output::
 
     OnceUponATime
@@ -217,7 +203,6 @@ Challenge: Incrementing filenames
   for i in 1 to 5 do
       io @println (root+i+ext).
   end
-
 Output::
 
     file1.txt
@@ -251,12 +236,10 @@ In our solution we take advantage of Asteroid's ``Pick`` object.  The ``Pick`` o
   let pick_list = int_list+lc_list+uc_list+sp_list.
 
   -- generate the password and print it.
-  let pwd = pick @pick pick_list @pick(15)
-                           @join("").
+  let pwd = pick @pick pick_list @pickitems 15 @join("").
   io @println pwd.
 
   assert (pwd == "e3zvshdbS43brt#")
-
 Output::
 
     e3zvshdbS43brt#
@@ -303,7 +286,6 @@ We will solve this programming problem using Asteroid's first-class patterns. We
   io @println rna_seq.
 
   assert(rna_seq == "UGGUAGUCAG").
-
 Output::
 
     UGGUAGUCAG
@@ -361,7 +343,6 @@ w to z.
   io @println decoded_msg.
 
   assert (decoded_msg == "hello, world!")
-
 Output::
 
     dahhk, sknhz!
@@ -387,7 +368,6 @@ If there is only one file, then the phrase should be ``1 file found`` instead.
   for n in 0 to 5 do
       io @println (n+" file"+("s " if n>1 or n==0 else " ")+"found").
   end
-
 Output::
 
     0 files found
@@ -405,7 +385,6 @@ Challenge: The most frequent word
 
 In our solution we use a hash table to count the number of word occurences.
 ::
-
   load system io.
   load system util.
   load system hash.
@@ -463,7 +442,6 @@ In our solution we use a hash table to count the number of word occurences.
   io @println most_frequent_word.
 
   assert (most_frequent_word == "sed").
-
 Output::
 
     sed
@@ -502,7 +480,6 @@ second string (``strb``).
   end
 
   assert (common == " fox ").
-
 Output::
 
     The longest common substring is ' fox '.
@@ -533,7 +510,6 @@ An anagram is a word, phrase, or name formed by rearranging the letters of anoth
   end
 
   assert (normalize(str1) == normalize(str2)).
-
 Output::
 
     Anagrams
@@ -567,7 +543,6 @@ to left.
   end
 
   assert (clean_str == clean_str @flip()).
-
 Output::
 
     Palindromic
@@ -618,7 +593,6 @@ part of the original string.
   end
 
   io @println longest_palindrome.
-
 Output::
 
     o, Wo
@@ -747,7 +721,6 @@ We do this by finding and hashing N-grams after the appropriate preprocessing.
   for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
       io @println (n_gram+": "+cnt).
   end
-
 Output::
 
     lorem ipsum dolor: 2
@@ -777,7 +750,6 @@ Challenge: Pi
   load system math. -- definition of pi
 
   io @println (math @pi).
-
 Output::
 
     3.141592653589793
@@ -787,11 +759,10 @@ Other constants are also available.
   load system io.
   load system math.
 
-  io @println (math @e).
-  io @println (math @tau). -- tau=2*pi
-
-  assert (math @tau == 2 * math @pi)
+  let tau = 2 * math @pi.
 
+  io @println (math @e).
+  io @println tau.
 Output::
 
     2.718281828459045
@@ -811,7 +782,6 @@ By definition, the factorial of a positive integer number N is a product of all
   let fact = [1 to n] @reduce(lambda with (a,b) do return a*b).
   io @println fact.
   assert (fact == 6).
-
 Output::
 
     6
@@ -844,7 +814,6 @@ the predicate applied to the input is true.  The last case is of some interest b
 
   io @println ("The factorial of 3 is: " + fact (3)).
   assert (fact(3) == 6).
-
 Output::
 
     The factorial of 3 is: 6
@@ -875,7 +844,6 @@ Here we give an iterative solutions.  It is clear that there exists a trivial re
 
   io @println f_1.
   assert (f_1 == 55)
-
 Output::
 
     55
@@ -895,7 +863,6 @@ Of course this is straightforward, with a ``for-loop`` over a list.  Here we sho
   io @println sq.
 
   assert (sq == [1,4,9,16,25,36,49,64,81,100])
-
 Output::
 
     [1,4,9,16,25,36,49,64,81,100]
@@ -916,7 +883,6 @@ Just as in the previous challenge, we skip the naive loop solution and give a so
   io @println p2.
 
   assert (p2 == [1,2,4,8,16,32,64,128,256,512])
-
 Output::
 
     [1,2,4,8,16,32,64,128,256,512]
@@ -939,7 +905,6 @@ We start with printing the first ten odd numbers,
 
   io @println odd.
   assert(odd == [1,3,5,7,9])
-
 Output::
 
     [1,3,5,7,9]
@@ -957,7 +922,6 @@ Now the even numbers,
 
   io @println even.
   assert(even == [2,4,6,8,10])
-
 Output:
 ::
 
@@ -979,8 +943,6 @@ Comparing non-integer numbers (which are represented as floating-point numbers)
 
   -- equal under the user defined tolerance of 0.0001
   assert (math @isclose(2.0,2.00001,0.0001)).
-
-
 Challenge: Prime numbers
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -1009,7 +971,6 @@ Prime numbers are those that can be divided only by 1, and by themselves.
 
   assert (isprime(17)).
   assert (not isprime(15)).
-
 Output:
 ::
 
@@ -1046,7 +1007,6 @@ Challenge: List of prime numbers
           break.
       end
   end
-
 Output:
 ::
 
@@ -1110,7 +1070,6 @@ Prime factors are the prime numbers that divide the given integer number exactly
   io @println factors.
 
   assert (factors == [3,5,11])
-
 Output:
 ::
 
@@ -1140,7 +1099,6 @@ Challenge: Reducing a fraction
 
   -- show that original and reduced fraction are the same value
   assert (a/b == numerator/denominator).
-
 Output:
 ::
 
@@ -1163,7 +1121,6 @@ Asteroid is an eager language, that is, expressions are evaluated as early as po
       io @println m.
   end
   io @println "We are still alive...".
-
 Output:
 ::
 
@@ -1198,7 +1155,6 @@ Asteroid has two random number generation functions: ``random()`` generates a ra
   let n = 10.
   io @println (randint(0.0,type @toreal(n))).
   io @println (randint(0,n)).
-
 Output:
 ::
 
@@ -1241,7 +1197,6 @@ To illustrate it with an example, let’s take the number 1234 as the seed. On s
   io @println rval.
 
   assert (rval == 5227)
-
 Output:
 ::
 
@@ -1268,7 +1223,6 @@ In our solution, we generate 10 random integers between 0 and 9. We then count h
   end
 
   io @println hist.
-
 Output:
 ::
 
@@ -1295,7 +1249,6 @@ A straightforward solution would be to use the Pythagorean theorem:
   io @println d.
 
   assert (d == 2.23606797749979)
-
 Output:
 ::
 
@@ -1321,7 +1274,6 @@ where ``.`` represents the dot product. In our case ``a`` would be the distance
   io @println d.
 
   assert (d == 2.23606797749979)
-
 Output:
 ::
 
@@ -1356,7 +1308,6 @@ where :math:`n` is the number of elements in the array :math:`x`; :math:`\bar{x}
   io @println sigma.
 
   assert (sigma == 420.96248961952256)
-
 Output:
 ::
 
@@ -1408,7 +1359,6 @@ These expressions can be implemented as-is in the code:
   -- show that the recovered coordinates are the same
   -- we started with
   assert (math @isclose(1,x,0.0001) and math @isclose(2,y,0.0001)).
-
 Output:
 ::
 
@@ -1466,7 +1416,6 @@ All these variants can be implemented by using ``with`` clauses and conditional
   -- show that the recovered coordinates are the same
   -- we started with
   assert (math @isclose(-3,x,0.0001) and math @isclose(5,y,0.0001)).
-
 Output:
 ::
 
@@ -1504,7 +1453,6 @@ To calculate the area of a circle with a radius of 1, pairs of random numbers be
   io @println area.
 
   assert (area == 3.1392).
-
 Output:
 ::
 
@@ -1537,7 +1485,6 @@ ask for the initial guess and enter the loop, which compares the guess with the
       let guess = type @tointeger(io @input("Try again: ")).
   end
   io @println "Yes, this is it!".
-
 Challenge: Binary to integer
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -1553,7 +1500,6 @@ In Asteroid this is straightforward using the built-in ``tointeger`` function, p
   io @println int.
 
   assert (int == 45).
-
 Output:
 ::
 
@@ -1583,7 +1529,6 @@ In Asteroid this is easily done with the ``tobase`` function.
   assert (tointeger(tobase(val,2),2) == val).
   assert (tointeger(tobase(val,8),8) == val).
   assert (tointeger(tobase(val,16),16) == val).
-
 Output:
 ::
 
@@ -1611,7 +1556,6 @@ Pretty straightforward using string and list manipulation.
   io @println s.
 
   assert (s == 49).
-
 Output:
 ::
 
@@ -1632,7 +1576,6 @@ If we remove all the zeros from a binary number, then we are left with only ``1`
   io @println bits.
 
   assert (bits == 4).
-
 Output:
 ::
 
@@ -1653,7 +1596,6 @@ The easiest way to achieve that is to treat the numbers as strings, sort them al
   io @println a.
 
   assert (a == 8675451).
-
 Output:
 ::
 
@@ -1697,7 +1639,6 @@ In the program below, there are four such sequences: for thousands, hundreds, te
   io @println roman.
 
   assert (roman == "MMXVIII")
-
 Output:
 ::
 
@@ -1757,7 +1698,6 @@ The zero name appears only in the case when the given number is zero.
   io @println (spell_number 75).
   io @println (spell_number 987654).
   io @println (spell_number 1001).
-
 Output:
 ::
 
@@ -1789,7 +1729,6 @@ Consider the complete program:
   io @println ("a = "+a,"b = "+b).
 
   assert ((a,b) is (20,10)).
-
 Output:
 ::
 
@@ -1810,7 +1749,6 @@ This approach also works with elements of an array:
   io @println a.
 
   assert (a is [3,5,4,7]).
-
 Output:
 ::
 
@@ -1828,7 +1766,6 @@ Challenge: Reverse a list
   io @println (a @reverse()).
 
   assert(a == [50,40,30,20,10]).
-
 Output:
 ::
 
@@ -1860,7 +1797,6 @@ Asteroid does not have a built-in ``rotate`` function. However, such a function
   io @println c.
 
   assert(b == [7,9,11,13,15,1,3,5] and c == [11,13,15,1,3,5,7,9]).
-
 Output:
 ::
 
@@ -1884,7 +1820,6 @@ This is easily accomplished with the built-in ``shuffle``.
   io @println b.
 
   assert(b == [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]).
-
 Output:
 ::
 
@@ -1906,7 +1841,6 @@ For this we use Asteroid's ``vector`` module, which can handle incrementing a ve
   io @println b.
 
   assert(b == [2,3,4,5,6,7,8,9,10,11]).
-
 Output:
 ::
 
@@ -1929,7 +1863,6 @@ Again, here we take advantage of Asteroid's ``vector`` module.  Note that the tw
   io @println c.
 
   assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
-
 Output:
 ::
 
@@ -1947,7 +1880,6 @@ The vector module defines a function called ``op`` that allows you to combine tw
   io @println c.
 
   assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
-
 Output:
 ::
 
@@ -1968,7 +1900,6 @@ As we said above, any arbitrary binary function. Consider the relational operato
   io @println c.
 
   assert(c == [false,true,false,false,false,true,false,false,true,true]).
-
 Output:
 ::
 
@@ -1992,7 +1923,6 @@ Here we use Asteroid's ``set`` module.
   io @println c.
 
   assert(c @sort() == [1,2,3,4]).
-
 Output:
 ::
 
@@ -2014,7 +1944,6 @@ Challenge: Sum of the elements of an array
   io @println s.
 
   assert (s == 125).
-
 Output:
 ::
 
@@ -2031,7 +1960,6 @@ If summing up elements that are greater than 10,
   io @println s.
 
   assert (s == 92).
-
 Output:
 ::
 
@@ -2050,7 +1978,6 @@ Challenge: Average of an array
   io @println avg.
 
   assert (avg == 60).
-
 Output:
 ::
 
@@ -2067,7 +1994,6 @@ Challenge: Is an element in a list?
   let array = [10, 14, 0, 15, 17, 20, 30, 35].
   let x = 17.
   io @println ((x+" is in the list") if array @member(x) else (x+" is not in the list")).
-
 Output:
 ::
 
@@ -2086,7 +2012,6 @@ We can also use a reduction function to solve this,
   else
       io @println (x+" is not in the list").
   end
-
 Output:
 ::
 
@@ -2110,7 +2035,6 @@ The easiest way to do this is with a reduction,
   let array = [2, 4, 18, 9, 16, 7, 10].
   let odd = array @reduce(lambda with (acc,i) do return i if type @isnone(acc) and mod(i,2) else acc,none).
   io @println odd.
-
 Output:
 ::
 
@@ -2129,7 +2053,6 @@ Challenge: Take every second element
   io @println array.
 
   assert (array == [21,23,25,27,29]).
-
 Output:
 ::
 
@@ -2146,7 +2069,6 @@ We can use an index vector to accomplish  the same thing,
   io @println array.
 
   assert (array == [21,23,25,27,29]).
-
 Output:
 ::
 
@@ -2171,12 +2093,11 @@ Challenge: Number of occurrences in an array
             "grape",
             "pineapple",
             "avocado"].
-            
+
   let cnt = dt @count("grape").
   io @println cnt.
 
   assert (cnt == 2).
-
 Output:
 ::
 
@@ -2202,7 +2123,6 @@ Converting a list to a set will remove all duplicate elements in the list.
   io @println a.
 
   assert (a == [2,3,4,5,6,7,10])
-
 Output:
 ::
 
@@ -2225,7 +2145,7 @@ Challenge: Minimum and maximum
   end
 
   let v = [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
-  
+
   let a = max v.
   let b = min v.
 
@@ -2233,7 +2153,6 @@ Challenge: Minimum and maximum
   io @println b.
 
   assert (a == 15 and b == 2).
-
 Output:
 ::
 
@@ -2255,7 +2174,6 @@ Challenge: Increasing sequences
   io @println b.
 
   assert (b).
-
 Output:
 ::
 
@@ -2355,7 +2273,6 @@ The procedure:
   io @println ("").
 
   assert(mt == [[1,3,5],[2,4,6]]).
-
 Output:
 ::
 
@@ -2419,7 +2336,6 @@ This task is commonly performed to sort items where the sortable parameter is on
   io @println (sort @sort(pairs,lst)).
 
   assert (sort @sort(pairs,lst) == [("Pete",20),("Joe",23),("Billie",40),("Brandi",43)])
-
 Output:
 ::
 
@@ -2466,7 +2382,6 @@ For example, a hash is a collection mapping a car’s license plate to the colou
   end
 
   io @println (sort @sort(pairs,color_lst)).
-
 Output:
 ::
 
@@ -2492,7 +2407,6 @@ We will do this with an outer loop  and a ``map`` function.
   for i in 1 to 10 do
       io @println ([1 to 10] @map(lambda with x do return format(i*x)) @join(" ")).
   end
-
 Output:
 ::
 
@@ -2575,7 +2489,6 @@ The only thing that is left to do is to iterate appropiately and format the outp
   for r in triangle do
       io @println (r @map(lambda with v do return type @tostring v) @join(" ")).
   end
-
 Output:
 ::
 
diff --git a/docs/Asteroid in Action.txt b/docs/Asteroid in Action.txt
index 10f419db..266082e9 100644
--- a/docs/Asteroid in Action.txt
+++ b/docs/Asteroid in Action.txt
@@ -1,12 +1,13 @@
-/******************************************************************
-  This is the source file from which the action doc is generated.
-  We use cpp to insert live code snippets into the document.
-  In order to generate the action doc run the following command
-  on a Unix-like system:
+..
+    /******************************************************************
+    This is the source file from which the action doc is generated.
+    We use cpp to insert live code snippets into the document.
+    In order to generate the action doc run the following command
+    on a Unix-like system:
 
-  cpp -w -P "Asteroid in Action.txt" > "Asteroid in Action.rst"
+    cpp -w -P "Asteroid in Action.txt" > "Asteroid in Action.rst"
 
- ******************************************************************/
+    ******************************************************************/
 #include "header.txt"
 
 .. highlight:: none
diff --git a/docs/Quickstart Tutorial.rst b/docs/Quickstart Tutorial.rst
index 7018840a..b0e17dbe 100644
--- a/docs/Quickstart Tutorial.rst
+++ b/docs/Quickstart Tutorial.rst
@@ -1,21 +1,19 @@
+..
+   /******************************************************************
+   This is the source file from which the reference guide is
+   generated.  We use cpp to insert live code snippets into the
+   document. In order to generate the reference guide run the
+   following command on a Unix-like system in the directory of
+   this doc:
 
+   bash generate_docs
 
-
-
-
-
-
-
-
-
-
-
-
+   ******************************************************************/
+..
+   /* header for generated .rst files */
 
 ..
    *** DO NOT EDIT; MACHINE GENERATED ***
-
-
 .. highlight:: none
 
 .. role:: raw-html(raw)
diff --git a/docs/Quickstart Tutorial.txt b/docs/Quickstart Tutorial.txt
index 1f689d41..7a653250 100644
--- a/docs/Quickstart Tutorial.txt
+++ b/docs/Quickstart Tutorial.txt
@@ -1,13 +1,15 @@
-/******************************************************************
-  This is the source file from which the reference guide is
-  generated.  We use cpp to insert live code snippets into the
-  document. In order to generate the reference guide run the
-  following command on a Unix-like system in the directory of
-  this doc:
+..
+   /******************************************************************
+   This is the source file from which the reference guide is
+   generated.  We use cpp to insert live code snippets into the
+   document. In order to generate the reference guide run the
+   following command on a Unix-like system in the directory of
+   this doc:
 
-  bash generate_docs
+   bash generate_docs
+
+   ******************************************************************/
 
- ******************************************************************/
 #include "header.txt"
 
 .. highlight:: none
diff --git a/docs/Reference Guide.rst b/docs/Reference Guide.rst
index 74a7f735..7640596c 100644
--- a/docs/Reference Guide.rst
+++ b/docs/Reference Guide.rst
@@ -1,21 +1,19 @@
+..
+      /******************************************************************
+      This is the source file from which the reference guide is
+      generated.  We use cpp to insert live code snippets into the
+      document. In order to generate the reference guide run the
+      following command on a Unix-like system in the directory of
+      this doc:
 
+      bash generate_docs
 
-
-
-
-
-
-
-
-
-
-
-
+      ******************************************************************/
+..
+   /* header for generated .rst files */
 
 ..
    *** DO NOT EDIT; MACHINE GENERATED ***
-
-
 .. highlight:: none
 
 Asteroid Reference Guide
@@ -99,8 +97,8 @@ For-Loop
 
 Syntax: ``FOR pattern IN exp DO stmt_list END``
 
-In a for-loop the expression must evaluate to a list.  The pattern is then matched to
-each element of the list sequentially starting with the first element of the list.
+In a for-loop the expression must evaluate to either a list or a tuple.  The pattern is then matched to
+each component of the expression value sequentially starting with the first component.
 The loop body is executed for each successful match.
 
 In the following program the body of the loop is executed exactly once when
@@ -299,13 +297,24 @@ can be copied into an object,
              let this @name = name.
              let this @age = age.
           end
+          function __str__ with none do
+            return this@name+" is "+this@age+" years old".
+          end
       end
 
       let betty = Person("Betty",21).  -- call constructor
       assert( betty @name == "Betty" ).
       assert( betty @age == 21 ).
 
-Also note that object identity is expressed using the ``this`` keyword.
+      load system type.
+      assert(type @tostring betty is "Betty is 21 years old").
+
+Note that object identity is expressed using the ``this`` keyword.
+Here we also supplied an instantiation of the ``__str__`` function that allows
+us to customize the stringification of the object.  See the last line
+where we cast the object ``betty`` to a string.  Without the ``__str__`` function
+Asteroid uses a default representation of the object as a string.
+The ``__str__`` function does not accept any arguments and has to return a string.
 
 Try-Catch
 %%%%%%%%%
@@ -428,7 +437,7 @@ we are dealing with a list,
 ::
       let [h | t] = [1,2,3].
 
-The ``is`` Predicate
+The Is Predicate
 %%%%%%%%%%%%%%%%%%%%
 
 Syntax: ``exp IS pattern``
@@ -443,13 +452,15 @@ Example,
 ::
       if v is (x,y) do
          io @println "success".
-         assert(isdefined x).
-         assert(isdefined y).
+         assert(isdefined "x").
+         assert(isdefined "y").
       else
          io @println "not matched".
+         assert(not isdefined "x").
+         assert(not isdefined "y").
       end
 
-The ``in`` Predicate
+The In Predicate
 %%%%%%%%%%%%%%%%%%%%
 
 Syntax: ``exp IN list_exp``
@@ -462,6 +473,27 @@ Example,
 ::
       let true = 1 in [1,2,3].
 
+The Eval Function
+%%%%%%%%%%%%%%%%%
+
+The ``eval`` function allows you to evaluate Asteroid expressions.  If the expression
+is a string then the contents of the string is treated like Asteroid code and is
+interpreted accordingly in the current interpreter environment.  If that code produces a value then the ``eval`` function
+will return that value, e.g.,
+::
+      let a = eval "1+1".
+      assert(a == 2).
+
+If the expression to be evaluated is a simple, structural pattern then the pattern is
+evaluated as a constructor where variables are instantiated from the current environment.
+For example,
+::
+      let p = pattern (x,y)
+      let x = 1.
+      let y = 2.
+      let o = eval p.
+      assert(o is (1,2)).
+
 List Comprehensions
 %%%%%%%%%%%%%%%%%%%
 
@@ -521,7 +553,7 @@ First-Class Patterns
 %%%%%%%%%%%%%%%%%%%%
 
 | Syntax: ``PATTERN exp``
-| Syntax: ``* exp``
+| Syntax: ``'*' exp (BIND '[' ID (AS ID)? (',' ID (AS ID)?)*']')?``
 
 This construction allows the user to construct a pattern as a value using
 the ``pattern`` keyword.  The advantage of patterns as values is that they
@@ -540,6 +572,21 @@ variables, e.g.
 Here the pair ``(1,2)`` is matched against the pattern stored in the variable ``p``
 such that ``x`` is bound to the value ``2``.
 
+The optional ``bind`` term together with an appropriate list of variable names
+allows the user to selectively project variable bindings from a constraint pattern
+into the current scope.  The ``as`` keyword allows you to rename those bindings.
+Consider the following program,
+::
+      let Pair = pattern %[(x,y)]%.
+
+      -- bindings of the variables x and y are now visible as a and y respetively
+      let *Pair bind [x as a, y] = (1,2).
+      assert( a == 1).
+      assert(y == 2).
+
+At the second  ``let`` statement we bind the ``x`` as ``a`` and ``y`` from the hidden scope
+of the constraint pattern into our current scope.
+
 Type Patterns
 %%%%%%%%%%%%%
 
@@ -559,8 +606,8 @@ Named Patterns
 Syntax: ``name_exp ':' pattern``
 
 Named patterns allow you to bind the term matched by the pattern to a variable.
-Here the name expression has to evaluate to something that looks like a variable,
-object member variable, or array location.
+Here the name expression has to evaluate to either a variable,
+object member variable, or list location.
 
 Example,
 ::
@@ -569,6 +616,15 @@ Example,
 The variable ``x`` will be bound to the value of ``val`` if that value matches the
 type pattern ``%integer``.
 
+Named patterns are a syntactic short hand for the equivalent conditional pattern,
+::
+      name_exp if name_exp is pattern
+
+That means the following two ``let`` statements are equivalent,
+::
+      let x:(q,p) = (1,2).
+      let x if x is (q,p) = (1,2).
+
 Conditional Patterns
 %%%%%%%%%%%%%%%%%%%%
 
@@ -587,7 +643,7 @@ Here ``k`` only matches the value of ``val`` if that value is an even number.
 Pure Constraint Patterns
 %%%%%%%%%%%%%%%%%%%%%%%%
 
-Syntax: ``%[ pattern ]%``
+Syntax: ``%[ pattern ]% (BIND '[' ID (AS ID)? (',' ID (AS ID)?)*']')?``
 
 A pure constraint pattern is a pattern that does not create any bindings
 in the current scope.  Any pattern can be turned into a pure constraint pattern
@@ -617,7 +673,6 @@ where ``<syntactic unit>*`` means zero or more occurrences of the syntactic unit
 ``<syntactic unit>?`` means that the syntactic unit is optional.  Simple terminals
 are written in quotes.
 ::
-
   ////////////////////////////////////////////////////////////////////////////////////////
   // statements
 
@@ -674,7 +729,7 @@ are written in quotes.
 
   pattern
     : PATTERN WITH? exp
-    | '%[' exp ']%'
+    | '%[' exp ']%' binding_list?
     | head_tail
 
   head_tail
@@ -724,7 +779,7 @@ are written in quotes.
     | FALSE
     | NONE
     | ID
-    | '*' call_or_index
+    | '*' call_or_index  binding_list?
     | NOT call_or_index
     | MINUS call_or_index
     | PLUS call_or_index
@@ -735,6 +790,18 @@ are written in quotes.
     | function_const
     | TYPEMATCH           // TYPEMATCH == '%'<typename>
 
+
+
+  binding_list
+    : BIND binding_list_suffix
+
+  binding_list_suffix
+     : binding_term
+     | '[' binding_term (',' binding_term)* ']'
+
+  binding_term
+    : ID (AS ID)?
+
   tuple_stuff
     : exp (',' exp?)*
     | empty
@@ -745,35 +812,54 @@ are written in quotes.
 
   function_const
     : LAMBDA body_defs
+Notes on Function Argument Notation
+-----------------------------------
 
+Functions in Asteroid are multi-dispatch functions and therefore can be called with a variety
+of input configurations.  This is reflected in the documentation of built-in functions and
+functions belonging to modules: when a function can be called with different input argument
+configurations then the documentation reflects this by providing different argument configuration
+separated by a '``|``' symbol.  E.g.,
+
+      list @pop () | ix:%integer
+
+indicating that the list member function ``pop`` can be called either with the empty argument ``()`` or with a
+single integer value.
 
 Builtin Functions
 -----------------
 
-* Function ``len``, when given an input value, returns the length of that input. The
-  function can only be applied to lists, strings, tuples, or structures.
+**getid** x
+      Returns a unique id of any Asteroid object as an integer.
+
+**hd** x:%list
+      Returns the first element of a list. It is an error to apply this
+      function to an empty list.
 
-* Function ``hd``, when given a list as input returns the first element of that list.
-  It is an error to apply this function to an empty list.
+**isdefined** x:%string
+      Returns true if a variable or type name is defined in the
+      current environment otherwise it returns false. The variable or type name must be given as a string.
+**len** x
+      Returns the length of x. The
+      function can only be applied to lists, strings, tuples, or structures.
 
-* Function ``tl``, when given a list as input returns the rest of the list without the first element.
-  It is an error to apply this function to an empty list.
+**range**  stop:%integer | (start:%integer, stop:%integer) | (start:%integer, stop:%integer, inc:%integer)
+      Compute a list of values depending on the input values:
 
-* Function ``range`` will compute a list of values depending on the input values:
+      1. If only the stop value is given then the list [0 to stop-1] is returned.
+      2. If the start and stop values are given then the list [start to stop-1] is returned.
+      3. If in addition to the start and stop values the inc values is given then the list [start to stop-1 step inc] is returned.
 
-  1. ``(start:%integer,stop:%integer)`` returns list ``[start to stop-1]``.
-  2. ``(start:%integer,stop:%integer,inc:%integer)`` returns list ``[start to stop-1 step inc]``.
-  3. ``(stop:%integer)`` returns list ``[0 to stop-1]``.
+**tl** x:%list
+      Returns the rest of the list without the first element.  It is an
+      error to apply this function to an empty list.
 
-* Function ``getid`` returns the id (physical memory address) of any Asteroid object as an Asteroid integer.
 
-* Function ``isdefined`` returns true if a variable or type name is defined in the
-  current environment otherwise it returns false. The variable or type name must be given as a string.
 
 List and String Objects
 -----------------------
 
-In Asteroid, both ``lists`` and ``strings,`` are treated like objects. Due to this, they have member functions that can manipulate the contents of those objects.
+In Asteroid, both ``lists`` and ``strings,`` are treated like objects in the OO sense. Due to this, they have member functions that can manipulate the contents of those objects.
 
 Lists
 ^^^^^
@@ -782,85 +868,155 @@ A **list** is a structured data type that consists of square brackets enclosing
 comma-separated values.
 Member functions on lists can be called on the data structure directly, e.g.::
 
-   [1,2,3] @length()
+   [1,2,3] @length ()
+
+Member Functions
+%%%%%%%%%%%%%%%%
+
+list **@append** item
+      Adds the item to the end of the list.
 
-* Function ``length`` returns the number of elements within that list.
-* Function ``append``, given ``(item)``, adds that item to the end of a list.
-* Function ``extend``, given ``(item)``, will extend the list by adding all the items from the item where ``item`` is either a list, a string or a tuple.
-* Function ``insert``, given ``(ix:%integer,item)``, will insert an item at a given position. The first argument is the index of the element before which to insert, so ``a@insert(0, x)`` inserts at the front of the list, and ``a@insert(a@length(), x)`` is equivalent to ``a@append(x)``.
-* Function ``remove``, given ``(item)``, removes the first element from the list whose value is equal to ``(item)``. It raises a ValueError if there is no such item.
-* Function ``pop``, given ``(ix:%integer)``, removes the item at the given position in the list and returns it. If no index is specified,``a@pop()`` removes and returns the last item in the list.
-* Function ``clear``, given ``(none)``, removes all items from the list.
-* Function ``index`` returns a zero-based index in the list of the first element whose value is equal to ``(item)``. It raises a ValueError exception if there is no such item. The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the ``(startix)`` argument.   This function can be called with several input configurations:
+list **@clear** ()
+      Removes all items from the list.
 
-  1. ``(item,loc(startix:%integer,endix:%integer))``
-  2. ``(item,loc(startix:%integer))``
-  3. ``item``
+list **@copy** ()
+      Returns a shallow copy of the list.
 
-* Function ``count``, given ``(item)``, returns the number of times ``(item)`` appears in the list.
-* Function ``sort`` sorts the items of the list in place. It can be called with several different inputs:
+list **@count** item
+      Returns the number of times item appears in the list.
 
-  1. ``(reverse:%boolean)`` if the boolean is set to true then the sorted list is reversed.
-  2. ``none`` returns the reverse list.
+list **@extend** item
+      Extend the list by adding all the elements from the item to the list where the item is either a list or a tuple.
 
-* Function ``reverse``, reverses the elements of the list in place.
-* Function ``copy``, makes a shallow copy of the list.
-* Function ``shuffle``, returns a random permutation of a given list - in place!
-* Function ``map``, given ``(f:%function)``, applies ``f`` to each element of the list in place. The modified list is returned.
-* Function ``reduce`` reduces the value of elements in a list. This
-  function can be called with several different inputs:
+list **@filter** f:%function
+      Returns a list constructed from those elements for which function f returns true.
 
-  1. Input ``(f:%function)`` returns ``value``, such that ``value = f(value,this@i)``.
-  2. Input ``(f:%function,init)`` returns the same format but uses ``init`` as an initial value.
+list **@index** item | (item, loc(startix:%integer) | (item, loc(startix:%integer, endix:%integer))
+      Returns a zero-based index of the first element whose value is equal to item.
+      It throws an exception if there is no such item. The argument loc allows you to specify
+      startix and endix and are used to limit the search to a particular subsequence of the list.
+      The returned index is computed relative to the beginning of the list rather than the startix argument.
 
-  The first argument to ``f`` is the accumulator.
+list **@insert** (ix:%integer, item)
+      Insert the item into the list at the position i.
+      This means that ``a@insert(0, x)`` inserts x at the front of the list, and ``a@insert(a@length(), x)`` is equivalent to ``a@append(x)``.
 
-* Function ``filter``, given ``(f:%function)``, constructs an output list from those elements of the list for which ``f`` returns true. If ``f`` is none, the identity function is assumed, that is, all elements of the input list that are false are removed.
-* Function ``member``, given ``(item)``, returns true only if ``item`` exists on the list.
-* Function ``join``, given ``(join:%string)``, turns the list into a string using ``join`` between the elements.  The string is returned
-  as the return value from this function.
+list **@join** join_str:%string
+      Turns the list into a string using join_str between the elements.  The string is returned
+      as the return value from this function.
 
+list **@length** ()
+      Returns the number of elements within the list.
 
-See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_ for more on all the functions above.
+list **@map** f:%function
+      Applies the function f to each element of the list in place. The modified list is returned.
+
+list **@member** item
+      Returns true only if item exists on the list.
+
+list **@pop** () | ix:%integer
+      Removes the item at the given position in the list and returns it. If no index is specified
+      removes and returns the last item in the list.
+
+list **@reduce** f:%function | (f:%function, init)
+      Reduce the list to a value by applying the function f to all the members of the list. The function f has to be
+      a function with two arguments where the first argument is the accumulator.  If no initial
+      value is given then the first element of the list is assumed to be the first accumulator value.
+      In order to illustrate, we have::
+
+            let value = [1,2] @reduce (lambda with (x,y) do x+y, 0).
+            assert(value == 3).
+
+      is equivalent to ::
+
+            let l = [1,2].
+            let value = 0.
+            for i in range(l@length()) do
+                  let value = (lambda with (x,y) do x+y) (value,l@i).
+            end
+            assert(value == 3).
+
+list **@remove** item
+      Removes the first element from the list whose value is equal to item.
+      It throws an exception if there is no such item.
+
+list **@reverse** ()
+      Reverses the elements of the list in place and returns the reversed list.
+
+list **@shuffle** ()
+      Creates a random permutation of the list in place and returns the randomized list.
+
+list **@sort** () | reverse:%boolean
+      Sorts the items of the list in place and returns the sorted list.
+      If the boolean reverse is set to true then the sorted list is reversed.
 
 
 Strings
 ^^^^^^^
 
-A string is a sequence of characters that can be used as a variable or a literal constant.
+A string is a sequence of characters surrounded by double quotes.
+In Asteroid, single characters are represented as single character strings.
 Similar to lists the member functions of strings can be called directly on the
 data structure itself, e.g.::
 
-   "Hello there" @length()
+   "Hello there" @length ()
+
+Member Functions
+%%%%%%%%%%%%%%%%
 
-* Function ``length`` returns the number of characters within that string.
-* Function ``explode``, turns a string into a list of characters.
-* Function ``trim``, given the input ``(what:%string)``, returns a copy of the string with the leading and trailing characters removed. The ``what`` argument is a string specifying the set of characters to be removed. If omitted or none, the ``what`` argument defaults to removing whitespace. The ``what`` argument is not a prefix or suffix; rather, all combinations of its values are stripped.
-* Function ``replace`` will return a copy of the string with all occurrences of regular expression pattern ``old`` replaced by the string ``new``. If the optional argument count is given, only the first count occurrences are replaced. It can be called with several different inputs:
+string **@explode** ()
+      Returns the string as a list of characters.
 
-  * ``(old:%string,new:%string,count:%integer)``
-  * ``(old:%string,new:%string)``
+string **@flip** ()
+      Returns a copy of the string with its characters in the reverse order.
 
-* Function ``split`` will return a list of the words in a given string, using ``sep`` as the delimiter string. If ``maxsplit`` is given: at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).
-  If ``sep`` is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, ``"1,,2"@split(",")`` returns ``["1", "", "2"]``). The ``sep`` argument may consist of multiple characters (for example, ``"1<>2<>3"@split("<>")`` returns ``["1", "2", "3"]``). Splitting an empty string with a specified separator returns ``[""]``.
-  If ``sep`` is not specified or is None, a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string or a string consisting of just whitespace with a None separator returns ``[]``.
-  Function ``split`` can be called with several different inputs:
+string **@index** item:%string | (item:%string, loc(startix:%integer)) | (item:%string, loc(startix:%integer, endix:%integer))
+      Returns an integer index of the item in the string or none if item was not found.
+      The  argument loc allows you to specify startix and endix and are used to limit the search
+      to a particular substring of the string. The returned index is computed relative to the beginning
+      of the full string rather than the startix.
 
-  1. Input ``(sep:%string,count:%integer)``
-  2. Input ``(sep:%string)``
-  3. Input ``(none)``
+string **@length** ()
+      Returns the number of characters within the string.
 
-* Function ``toupper``, converts all the lowercase letters in a string to uppercase.
-* Function ``tolower``, converts all the uppercase letters in a string to lowercase.
-* Function ``index`` allows the user to search for a given ``item`` in a list. It returns an integer index into the string or ``none`` if ``item`` was not found.  The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular substring of the string. The returned index is computed relative to the beginning of the full string rather than the ``(startix)`` argument.The function can be called with several different inputs:
+string **@replace** (old:%string, new:%string) | (old:%string, new:%string, count:%integer)
+      Return a copy of the string with all occurrences of regular expression old replaced by the
+      string new. If the argument count is given, only the first count occurrences are replaced.
 
-  1. Input ``(item:%string,loc(startix:%integer,endix:%integer))``
-  2. Input ``(item:%string,loc(startix:%integer))``
-  3. Input ``(item:%string)``
+string **@split** () | sep:%string | (sep:%string, count:%integer)
+      Return a list of the words in the string, using sep as the delimiter. If count is given then
+      at most count splits are done (thus, the list will have at most count+1 elements). If count is
+      not specified or -1, then there is no limit on the number of splits (all possible splits are made).
+      Consecutive delimiters are not grouped together and are deemed to delimit empty strings.
+      For example::
 
-* Function ``flip`` reverses a string.
+            let s = "1,,2" @split ",".
+            assert (s == ["1", "", "2"]).
+
+      The sep argument may consist of multiple characters.
+      For example::
+
+            let s = "1<>2<>3" @split "<>".
+            assert (s == ["1", "2", "3"]).
+
+      Splitting an empty string with a specified separator returns ``[""]``.
+      If sep is not specified or is None, a different splitting algorithm is applied:
+      consecutive whitespace is regarded as a single separator, and the result will contain no empty strings at
+      the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string
+      or a string consisting of just whitespace with a none separator returns ``[]``.
+
+string **@tolower** ()
+      Returns a copy of the string in all lower case letters.
+
+string **@toupper** ()
+      Returns a copy of the string in all upper case letters.
+
+string **@trim** () | what:%string
+      Returns a copy of the string with the leading and trailing characters removed.
+      The what argument specifies the set of characters to be removed.
+      If omitted trim defaults to removing whitespace.
+      The what argument is not a prefix or suffix; rather, all combinations of its characters are stripped.
 
-See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_  for more on all the functions above.
 
 
 Asteroid Modules
@@ -874,226 +1030,509 @@ we have ``println`` as one of the member functions.  To call that function::
    load system io.
    io @println "Hello there!".  -- println is a member function of the io module
 
-Bitwise
+bitwise
 ^^^^^^^
 
-The `bitwise <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/bitwise.ast>`_ module defines Bitwise operations. It supports the following functions,
-
-* Function ``band`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise AND operation.
-* Function ``bor`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise OR operation.
-* Function ``bnot`` can be called with the input ``(x:%integer)``, and performs the Bitwise NOT operation.
-* Function ``bxor`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise XOR operation.
-* Function ``blshift`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise left shift operation.
-* Function ``brshift`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise right shift operation.
-* Function ``blrotate`` can be called with the input ``(x:%integer, i:%integer)``, and performs the Bitwise left rotate operation.
-* Function ``brrotate`` can be called with the input ``(x:%integer, i:%integer)``, and performs the Bitwise right rotate operation.
-* Function ``bsetbit`` can be called with the input ``(x:%integer, i:%integer)``, and sets the ith bit.
-* Function ``bclearbit`` can be called with the input ``(x:%integer, i:%integer)``, and clears the ith bit.
-* Function ``bsize``can be called with the input ``(x:%integer)``, and returns the bit size.
-
-Hash
+This module defines bitwise operations on integers. It supports the following functions,
+
+bitwise **@band** (x:%integer, y:%integer)
+      Performs the bitwise AND operation and returns the result as an integer.
+
+bitwise **@bclearbit** (x:%integer, i:%integer)
+      Clear the ith bit in x and returns the result as an integer.
+
+bitwise **@blrotate** (x:%integer, i:%integer)
+      Performs the bitwise left rotate operation by i bits and returns the result as an integer.
+
+bitwise **@blshift** (x:%integer, y:%integer)
+      Performs the bitwise left shift operation where x is shifted by y bits and returns the result as an integer.
+
+bitwise **@bnot** x:%integer
+      Performs the bitwise NOT operation and returns the result as an integer.
+
+bitwise **@bor** (x:%integer, y:%integer)
+      Performs the bitwise OR operation and returns the result as an integer.
+
+bitwise **@brrotate** (x:%integer, i:%integer)
+      Performs the bitwise right rotate operation by i bits and returns the result as an integer.
+
+bitwise **@brshift** (x:%integer, y:%integer)
+      Performs the bitwise right shift operation where x is shifted by y bits and returns the result as an integer.
+
+bitwise **@bsetbit** (x:%integer, i:%integer)
+      Sets the ith bit in x and returns the result as an integer.
+
+bitwise **@bsize** x:%integer
+      Returns the bit size of x.
+
+bitwise **@bxor** (x:%integer, y:%integer)
+      Performs the bitwise XOR operation and returns the result as an integer.
+
+
+hash
 ^^^^
 
-The `hash <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/hash.ast>`_ module implements a hash for name-values pairs. It supports the following functions,
+This module implements a hash for key-value pairs. It supports the following functions,
+
+hash **@hash** ()
+      Returns a new hash object of type __HASH__.
 
-* Function ``insert``, given the input ``(name,value)``, will insert a given name-value pair into the table.
-* Function ``get``, given ``name``, will return the ``value`` associated with the given ``name`` as long as it can be found otherwise an exception will be thrown.
-* Function ``aslist`` returns the hash as a list of name-value pairs.
+__HASH__ **@aslist** ()
+      Returns the hash as a list of key-value pairs.
 
-IO
+__HASH__ **@get** key
+      Return the value associated with the given key as long as it can be found otherwise an exception will be thrown.
+
+__HASH__ **@insert** (key, value) | pairs:%list
+      Given a pair of the format (key, value) insert it into the table.  Given a list
+      of the format::
+
+            [(key1, val1), (key2, val2), ...]
+
+      insert all the key-value pairs on the list into the hash.
+
+io
 ^^
 
-The `io <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/io.ast>`_ module implements Asteroid's I/O system. The module defines three default streams,
+This module implements Asteroid's I/O system. The module defines three I/O streams,
 
-1. ``__STDIN__`` - the standard input stream.
-2. ``__STDOUT__`` - the standard output stream.
-3. ``__STDERR__`` - the standard error stream.
+1. __STDIN__ - the standard input stream.
+2. __STDOUT__ - the standard output stream.
+3. __STDERR__ - the standard error stream.
 
 Furthermore, the module supports the following functions,
 
-* Function ``println`` can be called with ``item``, and prints a given argument to the terminal (``__STDOUT__``) with an implicit newline character.
-* Function ``print`` can be called with ``item``, and prints a given argument. No implicit newline is appended to the output.
-* Function ``input`` can be called with a string ``prompt``.  If ``prompt`` is given it is printed and then input is read from the terminal (``__STDIN__``) and returned as a string.
-* Function ``open`` opens a file. Given ``(name:%string, mode:%string)``, it returns a file descriptor of type ``FILE``. The ``mode`` string can be ``"r"`` when the file will only be read, ``"w"`` for only writing (an existing file with the same name will be erased), and ``"a"`` opens the file for appending; any data written to the file is automatically added to the end. The ``"r+"`` opens the file for both reading and writing.
-* Function ``close``, given ``file:%FILE``, closes that file.
-* Function ``read``, given ``file:%FILE``, reads a file. If no file is given the ``__STDIN__`` stream is read.
-* Function ``readln``, given ``file:%FILE``, reads a given line of input from the file. If no file is given the ``__STDIN__`` stream is read.
-* Function ``write``, given ``(file:%FILE, what:%string)``, will write ``what`` to the given ``file``.  If ``file`` is not given then it writes to the ``__STDOUT__`` stream.
-* Function ``writeln``, works the same way as ``write`` except that it appends a newline character to the output.
-
-Math
-^^^^
-
-The `math <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/math.ast>`_ module implements mathematical constants and functions. It supports the following functions,
+io **@close** file:%\_\_FILE\_\_
+      Closes the file where file is a file descriptor of type \_\_FILE\_\_.
 
-*Power and logarithmic functions*
+io **@input** () | prompt:%string
+      Ask the user for input from __STDIN__.  The input is returned as a string. If prompt is given it is printed and then input is read from terminal.
 
-* Function ``exp``, given ``x:%integer``, returns e raised to the power ``x``, where e = 2.718281… is the base of natural logarithms.
-* Function ``log`` can be called with two different argument setups,
+io **@open** (name:%string, mode:%string)
+      Returns a file descriptor of type \_\_FILE\_\_.
+      The mode string can be "r" when the file will only be read,
+      "w" for only writing (an existing file with the same name will be erased),
+      and "a" opens the file for appending; any data written to the file is
+      automatically added to the end.
+      Finally,  "r+" opens the file for both reading and writing.
 
-  1. If only one argument, ``(x)``, is input, this returns the natural logarithm of x (to base e).
-  2. If two arguments, ``(x,base)``, are input, this returns the logarithm of x to the given base, calculated as log(x)/log(base).
+io **@print** item
+      Prints item to the terminal (__STDOUT__). No implicit newline is appended to the output.
 
-* Function ``pow``, given ``(b,p:%integer)``, returns "b <sup>p</sup>" as long as b is either ``real`` or ``integer``.
-* Function ``sqrt``, given ``a``, returns its square root as long as ``a`` is either ``real`` or ``integer``.
+io **@println** item
+      Prints item to the terminal (__STDOUT__) with an implicit newline character.
 
-*Number-theoretic and representation functions*
+io **@read** () | file:%\_\_FILE\_\_
+      Read a file and return the contents as a string. If no file is given the __STDIN__ stream is read.
 
-* Function ``abs``, given ``x``, returns its absolute value.
-* Function ``ceil``, given ``x:%real``, returns the ceiling of x: the smallest integer greater than or equal to x.
-* Function ``floor``, given ``x:%real``, returns the floor of x: the largest integer less than or equal to x.
-* Function ``gcd``, given ``(a:%integer,b:%integer)``, returns the greatest common denominator that both integers share.
-* Function ``isclose`` can be called with two different argument setups,
+io **@readln** () | file:%\_\_FILE\_\_
+      Reads a line of input from a file and returns it as a string. If no file is given the __STDIN__ stream is read.
 
-  1. With input values ``(a,b)``, it returns returns ``true`` if the two values are close to each other and ``False`` otherwise. Default tolerance 1e-09.
-  2. With input values ``(a,b,t)``, it compares ``a`` and ``b`` with tolerance ``t``.
+io **@write** what:%string | (file:%\_\_FILE\_\_, what:%string)
+      Write what to a file.  If file is not given then it writes to the __STDOUT__ stream.
 
-* Function ``mod``, given ``(v,d)``, will return the remainder of the operation ``v/d``, as long as ``v`` and ``d`` are either ``real`` or ``integer`` values.
+io **@writeln** what:%string | (file:%\_\_FILE\_\_, what:%string)
+      Write what to a file and append a newline charater.  If file is not given then it writes to  __STDOUT__.
 
-*Trigonometric functions*
 
-* Function ``acos``, given ``x``, returns the arc cosine of x in radians. The result is between 0 and pi.
-* Function ``asin``, given ``x``, returns the arc sine of x in radians. The result is between -pi/2 and pi/2.
-* Function ``atan``, ,given ``x``, returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
-* Function ``cos``, given ``x``, returns the cosine of x radians.
-* Function ``sin``, given ``x``, returns the sine of x radians.
-* Function ``tan``, given ``x``, returns the tangent of x radians.
-* Function ``acosh``, given ``x``, returns the inverse hyperbolic cosine of x.
-* Function ``asinh``, given ``x``, returns the inverse hyperbolic sine of x.
-* Function ``atanh``, given ``x``, returns the inverse hyperbolic tangent of x.
-* Function ``cosh``, given ``x``, returns the hyperbolic cosine of x.
-* Function ``sinh``, given ``x``, returns the hyperbolic sine of x.
-* Function ``tanh``, given ``x``, returns the hyperbolic tangent of x.
-* Function ``degrees``, given ``x``, converts angle ``x`` from radians to degrees.
-* Function ``radians``,  given ``x``, converts angle ``x`` from degrees to radians.
+math
+^^^^
 
-An example,
+The math module implements mathematical constants and functions.
+An example:
 ::
     load system io.
     load system math.
 
     let x = math @sin( math @pi / 2 ).
     io @println("The sine of pi / 2 is " + x + ".").
+Constants
+%%%%%%%%%
+
+math **@pi**
+      The mathematical constant π = 3.141592…, to available precision.
 
-Pick
+math **@e**
+      The mathematical constant e = 2.718281…, to available precision.
+
+
+Power and logarithmic functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+math **@exp** x:%integer
+      Returns e raised to the power x, where e = 2.718281… is the base of the natural logarithm.
+
+math **@log** x | (x, base:%integer)
+      If only argument x is the input, return the natural logarithm of x (to base e).
+      If two arguments, (x, base:%integer), are given as input, return the logarithm
+      of x to the given base, calculated as log(x)/log(base).
+
+math **@pow** (b, p:%integer)
+      Return b raised to the power p.  The return type depends on the type
+      of the base.
+
+math **@sqrt** x
+      Return the square root of x as a real.
+
+
+Number-theoretic and representation functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+math **@abs** x
+      Return that absolute value of x.  The return type depends on the type of x.
+
+math **@ceil** x:%real
+      Returns the ceiling of x: the smallest integer greater than or equal to x.
+
+math **@floor** x:%real
+      Returns the floor of x: the largest integer less than or equal to x.
+
+math **@gcd** (a:%integer, b:%integer)
+      Returns the greatest common denominator that both integers share.
+
+math **@isclose** (a:%real, b:%real) | (a:%real, b:%real, t:%real)
+      Return true if the values a and b are close to each other and false otherwise.
+      Default tolerance is 1e-09.  An alternative tolerance can be specified with
+      the t argument.
+
+math **@mod** (v,d)
+      Implements the modulus operation. Returns the remainder of the quotient v/d.
+
+
+Trigonometric functions
+%%%%%%%%%%%%%%%%%%%%%%%
+
+math **@acos** x
+      Returns the arc cosine of x in radians. The result is between 0 and pi.
+
+math **@asin** x
+      Returns the arc sine of x in radians. The result is between -pi/2 and pi/2.
+
+math **@atan** x
+      Returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
+
+math **@cos** x
+      Returns the cosine of x radians.
+
+math **@sin** x
+      Returns the sine of x radians.
+
+math **@tan** x
+      Returns the tangent of x radians.
+
+Hyperbolic functions
+%%%%%%%%%%%%%%%%%%%%
+
+math **@acosh** x
+      Returns the inverse hyperbolic cosine of x.
+
+math **@asinh** x
+      Returns the inverse hyperbolic sine of x.
+
+math **@atanh** x
+      Returns the inverse hyperbolic tangent of x.
+
+math **@cosh** x
+      Returns the hyperbolic cosine of x.
+
+math **@sinh** x
+      Returns the hyperbolic sine of x.
+
+math **@tanh** x
+      Returns the hyperbolic tangent of x.
+
+Angular conversion
+%%%%%%%%%%%%%%%%%%
+
+math **@degrees** x
+      Converts angle x from radians to degrees.
+
+math **@radians** x
+      Converts angle x from degrees to radians.
+
+
+os
+^^
+
+This module provides a portable way of using operating system dependent functionality.
+
+Process Parameters
+%%%%%%%%%%%%%%%%%%
+
+os **@argv**
+      The list of command line arguments passed to an Asteroid script.
+      argv[0] is the name of the Asteroid script (it is operating
+      system dependent whether this is a full pathname or not).
+      In interactive mode argv[0] will be the empty string.
+
+os **@env**
+      A hash table where keys and values are strings that represent
+      the process environment. For example,
+            os @env @get "HOME"
+      is the pathname of your home directory (on some platforms),
+      and is equivalent to getenv("HOME") in C.
+
+os **@platform**
+      This string contains a platform identifier.
+
+
+Functions
+%%%%%%%%%
+
+os **@basename** path:%string
+      Return the base name of pathname path. This is the second element of the pair
+      returned by passing path to the function split. Note that the result of this
+      function is different from the Unix basename program; where basename for '/foo/bar/'
+      returns 'bar', the basename function returns an empty string ("").
+
+os **@chdir** path:%string
+      Change the current working directory to path.
+
+os **@dirname** path:%string
+      Return the directory name of pathname path. This is the first element of the
+      pair returned by passing path to the function split.
+
+os **@exists** path:%string
+      Return true if path refers to an existing path or an open file descriptor.
+      Returns false for broken symbolic links. On some platforms, this function
+      may return False if permission is not granted to execute stat on
+      the requested file, even if the path physically exists.
+
+os **@exit** () | v:%integer | msg:%string
+      Signaling an intention to exit the interpreter.
+      When an argument value other than none is provided
+      it is considered a status value. If it is
+      an integer, zero is considered “successful termination” and any
+      nonzero value is considered “abnormal termination” by shells and
+      the like. Most systems require it to be in the range 0–127, and
+      produce undefined results otherwise. Some systems have a
+      convention for assigning specific meanings to specific exit codes,
+      but these are generally underdeveloped; Unix programs generally
+      use 2 for command line syntax errors and 1 for all other kind
+      of errors. If none is given as an argument value then is it
+      is considered to be a successful exit equivalent to passing a zero.
+      If a string is passed then it is printed printed to
+      __STDERR__ and results in an exit code of 1. In particular,
+      sys.exit("some error message") is a quick way to exit a program
+      when an error occurs.
+
+os **@getdir** ()
+      Return a string representing the current working directory.
+
+os **@getpathtime** path:%string | (path:%string,flag:%boolean)
+      Returns a triple with (creation, access, modification) times.
+      By default the return value is a triple of real numbers
+      giving the number of seconds since 1/1/1970.  If the flag is set
+      to true then a triple of strings is returned where each string
+      represents the respective local time. Throws an exception if the file
+      does not exist or is inaccessible.
+
+os **@getsize** path:%string
+      Return the size, in bytes, of path. Throws exception if the file
+      does not exist or is inaccessible.
+
+os **@isfile** path:%string
+      Return true if path is an existing regular file. This follows
+      symbolic links.
+
+os **@isdir** path:%string
+      Return true if path is an existing directory. This follows
+      symbolic links.
+
+os **@join** (path1:%string,path2:%string)
+      Join path1 and path2 components intelligently. The return value
+      is the concatenation of path and any members of *paths with
+      exactly one directory separator following each non-empty part
+      except the last, meaning that the result will only end in a
+      separator if the last part is empty. If the second component is an
+      absolute path, the first component is thrown away.
+
+      On Windows, the drive letter is not reset when an absolute
+      path component (e.g., r'\foo') is encountered. If a component
+      contains a drive letter, all previous components are thrown away
+      and the drive letter is reset. Note that since there is a current
+      directory for each drive, os.path.join("c:", "foo") represents a
+      path relative to the current directory on drive C: (c:foo), not c:\foo.
+
+os **@split** path:%string
+      Split the pathname path into a pair, (head, tail) where tail is
+      the last pathname component and head is everything leading up to
+      that. The tail part will never contain a slash; if path ends in
+      a slash, tail will be empty. If there is no slash in path, head
+      will be empty. If path is empty, both head and tail are empty.
+      Trailing slashes are stripped from head unless it is the root
+      (one or more slashes only). Also see the functions dirname and
+      basename.
+
+os **@splitdrive** path:%string
+      Split the pathname path into a pair (drive, tail) where drive is
+      either a mount point or the empty string. On systems which do not
+      use drive specifications, drive will always be the empty string.
+      In all cases, drive + tail will be the same as path.
+
+      On Windows, splits a pathname into drive/UNC sharepoint and
+      relative path.
+
+      If the path contains a drive letter, drive will contain everything
+      up to and including the colon.
+
+os **@splitext** path:%string
+      Split the pathname path into a pair (root, ext) such that
+      root + ext == path, and the extension, ext, is empty or begins
+      with a period and contains at most one period. If the path contains
+      no extension, ext will be the empty string.
+
+os **@syscmd** cmd:%string
+      Execute a command in a subshell. This is implemented
+      by calling the Standard C function system, and has the same
+      limitations. If command generates any output, it will be
+      sent to the interpreter standard output stream.
+      The C standard does not specify the meaning of the return value of
+      the C function, so the return value of this function is
+      system-dependent.
+
+
+
+
+pick
 ^^^^
 
-The `pick <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/pick.ast>`_ module implements
-pick objects that allow a user to randomly pick items from a list using the ``pick`` function.
-The ``pick`` function can be called with ``n:%integer`` and returns a list of ``n`` randomly picked objects from the object list.
-Here is a simple use case
+The pick module implements
+pick objects that allow a user to randomly pick items from a list of items using the pickitems function.
+An example:
 ::
    load system io.
    load system pick.
 
    let po = pick @pick([1 to 10]).
-   let objects = po @pick(3).
+   let objects = po @pickitems 3.
    io @println objects.
+pick **@pick** l:%list
+      Construct a pick object of type __PICK__.
 
+__PICK__ **@pickitems** () | n:%integer
+      Return items randomly picked from the list l.  If no input is provided
+      then pickitems will return a single, randomly picked item from the list.
+      If an integer value n is given then a list of n randomly picked items from
+      the list l is returned.  The picked item list is constructed by sampling the
+      list l with replacement.
 
 
-Random
+random
 ^^^^^^
 
-The `random <https://github.com/lutzhamel/asteroid/blob/master/asteroid/modules/random.ast>`_ module implements the ``random`` numbers. Using the functions included in this module will return a random value within a given range or interval. It supports the following functions,
+The random module implements random number generation.
 
-* Function ``random``, given the input ``none``, returns a random floating point number in the range ``[0.0, 1.0)``.
-* Function ``randint`` returns a random value N in the interval lo <= N <= hi. The exact random value output depends on the types of the values specifying the interval. It can be called with two different number interval inputs:
+random **@randint** (lo:%integer,hi:%integer) | (lo:%real,hi:%real)
+      Return a random value N in the interval lo <= N <= hi.
+      The type of the random value depends on the types of the
+      values specifying the interval.  If the interval is specified
+      with integers then a random integer value is returned.
+      If the interval is specified with real numbers then a real value is
+      is returned, and for everything else an exception is thrown.
 
-  1. ``(lo:%integer,hi:%integer)``
-  2. ``(lo:%real,hi:%real)``
-  3. Note: any other interval specification will instead output an error message for "unsupported interval specification in randint."
+random **@random** ()
+      Return a random real number in the range [0.0, 1.0).
 
-* Function ``seed``, given ``(sd:%integer)``, provides a seed value for the random number generator.
+random **@seed** x:%integer
+      Provide the seed value x for the random number generator.
 
-Set
+set
 ^^^
 
-The `set <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/set.ast>`_ module implements Asteroid sets as lists. Unlike lists, sets do not have repeated members. It supports the following functions,
+The set module implements Asteroid sets as lists.
+Unlike lists, sets do not have repeated elements.
+Use the set member function toset to turn any list
+into a list that represents a set (remove repeated items).
+
+set **@diff** (a:%list,b:%list)
+      Return the difference set between sets a and b.
+
+set **@intersection** (a:%list,b:%list)
+      Return the intersection of sets a and b.
+
+set **@toset** l:%list
+      Return list l as a set by removing repeated elements.
+
+set **@union** (a:%list,b:%list)
+      Return the union of sets a and b.
+
+set **@xunion** (a:%list,b:%list)
+      Return the elements in a or b but not both.
 
-* Function ``toset``, given ``(lst:%list)``, converts the input list into a set.
-* Function ``diff``, given ``(a:%list,b:%list)``, computes the difference set between the two set ``a`` and ``b``.
-* Function ``intersection``, given ``(a:%list,b:%list)``, finds the intersection between  sets ``a`` and ``b``.
-* Function ``union``, given ``(a:%list,b:%list)``, computes the union of sets ``a`` and ``b``.
-* Function ``xunion``, given ``(a:%list,b:%list)``, returns all elements in ``a`` or ``b``, but not in both.
 
-Sort
+sort
 ^^^^
 
-The `sort <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/sort.ast>`_ module
-defines a parameterized ``sort`` function over a list.
-The ``sort`` function makes use of a user-defined order predicate on the list's elements to
-perform the sort. The ``Quicksort`` is the underlying sort algorithm.
-The following is a simple example,
+The sort  module
+defines a parameterized sort function over a list.
+The sort function makes use of a user-defined order predicate on the list's elements to
+perform the sort. The QuickSort is the underlying sort algorithm.
+The following is a simple example:
 ::
    load system io.
    load system sort.
-   let sl = sort @sort((lambda with (x,y) do return true if x<y else false),
+   let sl = sort @sort((lambda with (x,y) do true if x<y else false),
                        [10,5,110,50]).
-    io @println sl.
-
+   io @println sl.
 prints the sorted list::
 
   [5,10,50,110]
 
-Stream
-^^^^^^
+sort **@sort** (p:%function,l:%list)
+      Returns the sorted list l using the predicate p.
 
-The `stream <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/stream.ast>`_ module implements streams that allow
-the developer to turn any list into a stream supporting interface functions like ``peeking`` ahead or ``rewinding`` the stream.
-The following stream interface functions are available,
 
-* Function ``eof`` returns ``true`` if the stream does not contain any further elements for processing. Otherwise it returns ``false``.
-* Function ``peek`` returns the current element available on the stream otherwise it returns ``none``.
-* Function ``get`` returns the current element and moves the stream pointer one ahead.
-* Function ``rewind`` resets the stream pointer to the first element of the stream.
-* Function ``map`` applies a given function to each element in the stream.
-* Function ``append``, given ``item``, adds item to the end of the stream.
-* Function ``__string__`` maps a the stream to a string representation.
+stream
+^^^^^^
 
-A simple use case.
+The stream module implements streams that allow
+the developer to turn any list into a stream supporting interface functions like peeking ahead or rewinding
+the stream.
+A simple use case:
 ::
    load system io.
    load system stream.
 
-   let s = stream @stream([1 to 10]).
-   while not s @ eof() do
-      io @ print (s @get()+" ").
+   let s = stream @stream [1 to 10].
+   while not s @eof() do
+      io @print (s @get() + " ").
    end
-   io @println ("").
-
-
+   io @println "".
 which outputs::
 
    1 2 3 4 5 6 7 8 9 10
 
 
-Type
-^^^^
+stream **@stream** l:%list
+      Returns a stream object of type __STREAM__.
 
-The `type <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/type.ast>`_ module defines type related functions and structures.
+__STREAM__ **@append** x
+      Adds x to the end of the stream.
 
-*Type Conversion*
+__STREAM__ **@eof** ()
+      Returns true if the stream does not contain any further elements for processing.
+      Otherwise it returns false.
 
-* Function ``tointeger`` converts a given input to an integer. It can be called with two different arguments,
+__STREAM__ **@get** ()
+      Returns the current element and moves
+      the stream pointer one ahead.  Returns none if no elements left in stream.
 
-  1. ``(item:%string,base:%integer)`` where ``base`` is a valid base for integer conversion
-  2. ``item`` where ``item`` is converted to a base 10 integer.
+__STREAM__ **@map** f:%function
+      Applies function f to each element in the stream.
 
+__STREAM__ **@peek** ()
+      Returns the current element available on the stream otherwise it returns none.
 
-* Function ``toreal``, given ``item``, returns the input as a real number data type.
-* Function ``toboolean``, given ``item``, returns the input as a Boolean value of either true or false.
-* Function ``tostring`` converts an Asteroid object to a string. If format values are given, it applies the formatting to the object. It can be called with several different inputs where ``*TP`` indicates a``boolean``, ``integer``, or ``string`` type and ``w`` is the width specification, ``p`` is the precision specification and ``s`` is the scientific notation flag.  When no formatting information is provided a default string conversion occurs,
+__STREAM__ **@rewind** ()
+      Resets the stream pointer to the first element of the stream.
 
-  1. ``(v:*TP,type @stringformat(w:%integer))``
-  2. ``(v:%real,type @stringformat(w:%integer))``
-  3. ``(v:%real,type @stringformat(w:%integer,p:%integer))``
-  4. ``(v:%real,type @stringformat(w:%integer,p:%integer,s:%boolean))``
-  5. ``item`` - default conversion
 
-* Function ``tobase`` represents the given integer ``x`` (*specifically* within the given input ``(x:%integer,base:%integer)``) as a string in the given base.
+type
+^^^^
 
-Here is a program that exercises some of the string formatting options,
+The type module defines type related functions and structures.
+Here is a program that exercises some of the string formatting options:
 ::
     load system io.
     load system type.
@@ -1115,7 +1554,6 @@ Here is a program that exercises some of the string formatting options,
     -- if precision is missing then value is left justified and zero padded on right.
     let r = type @tostring(math @pi,type @stringformat(6,3)).
     io @println r.
-
 The output of the program is,
 ::
 
@@ -1126,13 +1564,42 @@ The output of the program is,
 
 Notice the right justification of the various values within the given string length.
 
+Type Conversion
+%%%%%%%%%%%%%%%
+
+type **@tobase** (x:%integer,base:%integer)
+      Represents the given integer x as a numeral string in different bases.
+
+type **@toboolean** x
+      Interpret x as a Boolean value.
 
-*Type Query Functions*
+type **@tointeger** (x:%string,base:%integer) | x
+      Converts a given input to an integer. If a base value is specified then
+      the resulting integer is in the corresponding base.
 
-* Function ``islist`` returns ``true`` if given ``item`` is a list otherwise it will return ``false``.
-* Function ``isscalar`` returns ``true`` if given ``item`` is either an integer or a real value.
-* Function ``isnone`` returns ``true`` if given ``item`` is equal to the value ``none``.
-* Function ``gettype`` returns the type of a given ``item`` as an Asteroid string.
+type **@toreal** x
+      Returns the input as a real number.
+
+type  **@tostring** x | (x,type @stringformat(width:%integer,precision:%integer,scientific:%boolean))
+      Converts an Asteroid object to a string. If format values are given,
+      it applies the formatting to the string object.
+
+
+
+Type Query Functions
+%%%%%%%%%%%%%%%%%%%%
+
+type **@islist** x
+      Returns true if x is a list otherwise it will return false.
+
+type **@isnone** x
+      Returns true if x is equal to the value none.
+
+type **@isscalar** x
+      Returns true if x is either an integer or a real value.
+
+type **@gettype** x
+      Returns the type of x as a string.
 
 A simple example program using the ``gettype`` function,
 ::
@@ -1140,42 +1607,48 @@ A simple example program using the ``gettype`` function,
 
    let i = 1.
    assert(type @gettype(i) == "integer").
+util
+^^^^
 
+The util module defines utility functions and structures that don't really
+fit into any other modules.
 
-Util
-^^^^
+util **@achar** x
+      Given a decimal ASCII code x, return the corresponding character symbol.
 
-The `util <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/util.ast>`_ module defines utility functions and structures that don't really fit into any omodules. It supports the following functions,
+util **@ascii** x:%string
+      Given a character x, return the corresponding ASCII code of the first character of the input.
 
-* Function ``exit`` exits the program. It can be called with two inputs,
+util **@cls** ()
+      Clears the terminal screen.
 
-  1. ``none``
-  2. ``msg:%string``
+util **@copy** x
+      Given the object x, make a deep copy of it.
 
-* Function ``copy``, given Asteroid object ``obj``, makes a deep copy of it.
-* Function ``cls`` clears the terminal screen.
-* Function ``sleep``,  programs sleep for ``secs`` seconds where the argument ``secs`` is either an integer or real value.
-* Function ``zip``, given ``(list1:%list,list2:%list)``, will return a list where element ``i`` of the list is the tuple ``(list1@i,list2@i)``.
-* Function ``unzip``, given a list of pairs will return a pair of lists where the first component of the pair is the list of all the first components of the pairs of the input list and the second component of the return list is a list of all the second components of the input list.
-* Function ``ascii``, given a character ``item:%string``, returns the corresponding ASCII code of the first character of the input string.
-* Function ``achar``, given a decimal ASCII code ``item:%integer``, returns the corresponding character symbol.
+util **@ctime** x:%real
+      Given a real value representing seconds since 1/1/1970 this function
+      converts it to a suitable string representation of the date.
 
-Vector
-^^^^^^
+type **@sleep** x
+      Sleep for x seconds where the x is either an integer or real value.
 
-The `vector <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/vector.ast>`_ defines functions useful for vector arithmetic. It supports the following functions.  Here ``a`` and ``b`` are vectors implemented as lists,
+type **@time** ()
+      Returns the local time as a real value in secs since 1/1/1970.
 
-* Function ``add``, given the input ``(a,b)``, returns a vector that contains the element by element sum of the input vectors.
-* Function ``sub``, given the input ``(a,b)``, returns the element by element difference vector.
-* Function ``mult``, given the input ``(a,b)``, returns the element by element vector multiplication.
-* Function ``dot``, given ``(a,b)``, computes the dot product of the two vectors.
-* Function ``op``  allows the developer to vectorize any function. It can be called with three different inputs:
+type **@unzip** x:%list
+      Given a list of pairs x this function will return a pair of lists
+      where the first component of the pair is the list of all the first
+      components of the pairs of the input list and the second component
+      of the return list is a list of all the second components of the input list.
 
-  1. ``(f:%function,a:%list,b:%list)``
-  2. ``(f:%function,a:%list,b if type @isscalar(b))``
-  3. ``(f:%function,a if type @isscalar(a),b:%list)``
+type **@zip** (list1:%list,list2:%list)
+      Returns a list where element i of the list is the tuple (list1@i,list2@i).
 
-Here is a simple example program for the ``vector`` module,
+vector
+^^^^^^
+
+The vector defines functions useful for vector arithmetic. Vectors are implemented as lists.
+Here is a simple example program for the ``vector`` module:
 ::
    load system io.
    load system vector.
@@ -1184,9 +1657,24 @@ Here is a simple example program for the ``vector`` module,
    let b = [0,1].
 
    io @println (vector @dot (a,b)).
+which prints the value ``0``.
 
+vector **@add** (a:%list,b:%list)
+      Returns a vector that contains the element by element sum of the input vectors a and b.
+
+vector **@dot** (a:%list,b:%list)
+      Computes the dot product of the two vectors a and b.
+
+vector **@mult** (a:%list,b:%list)
+      Returns the element by element vector multiplication of vectors a and b.
+
+vector **@op** (f:%function,a:%list,b:%list) | (f:%function,a:%list,b if type @isscalar(b)) | (f:%function,a if type @isscalar(a),b:%list)
+      Allows the developer to vectorize any function f. Applying scalar values
+      to vectors is also supported by this function.
+
+vector **@sub** (a:%list,b:%list)
+      Returns the element by element difference vector.
 
-which prints the value ``0``.
 
 Interfacing Asteroid with Python
 --------------------------------
@@ -1236,7 +1724,7 @@ as an argument.  Let's test drive this in the Python interactive shell,
 ::
     ubuntu$ python3
     Python 3.8.10 (default, Nov 26 2021, 20:14:08)
-    [GCC 9.3.0] on 1
+    [GCC 9.3.0] on linux
     Type "help", "copyright", "credits" or "license" for more information.
     >>> from asteroid.interp import interp
     >>> interp('load system io. io @println "Hello, World!".')
diff --git a/docs/Reference Guide.txt b/docs/Reference Guide.txt
index 8851b7cc..05994053 100644
--- a/docs/Reference Guide.txt
+++ b/docs/Reference Guide.txt
@@ -1,13 +1,14 @@
-/******************************************************************
-  This is the source file from which the reference guide is
-  generated.  We use cpp to insert live code snippets into the
-  document. In order to generate the reference guide run the
-  following command on a Unix-like system in the directory of
-  this doc:
+..
+      /******************************************************************
+      This is the source file from which the reference guide is
+      generated.  We use cpp to insert live code snippets into the
+      document. In order to generate the reference guide run the
+      following command on a Unix-like system in the directory of
+      this doc:
 
-  bash generate_docs
+      bash generate_docs
 
- ******************************************************************/
+      ******************************************************************/
 #include "header.txt"
 
 .. highlight:: none
@@ -93,8 +94,8 @@ For-Loop
 
 Syntax: ``FOR pattern IN exp DO stmt_list END``
 
-In a for-loop the expression must evaluate to a list.  The pattern is then matched to
-each element of the list sequentially starting with the first element of the list.
+In a for-loop the expression must evaluate to either a list or a tuple.  The pattern is then matched to
+each component of the expression value sequentially starting with the first component.
 The loop body is executed for each successful match.
 
 In the following program the body of the loop is executed exactly once when
@@ -293,13 +294,24 @@ can be copied into an object,
              let this @name = name.
              let this @age = age.
           end
+          function __str__ with none do
+            return this@name+" is "+this@age+" years old".
+          end
       end
 
       let betty = Person("Betty",21).  -- call constructor
       assert( betty @name == "Betty" ).
       assert( betty @age == 21 ).
 
-Also note that object identity is expressed using the ``this`` keyword.
+      load system type.
+      assert(type @tostring betty is "Betty is 21 years old").
+
+Note that object identity is expressed using the ``this`` keyword.
+Here we also supplied an instantiation of the ``__str__`` function that allows
+us to customize the stringification of the object.  See the last line
+where we cast the object ``betty`` to a string.  Without the ``__str__`` function
+Asteroid uses a default representation of the object as a string.
+The ``__str__`` function does not accept any arguments and has to return a string.
 
 Try-Catch
 %%%%%%%%%
@@ -422,7 +434,7 @@ we are dealing with a list,
 ::
       let [h | t] = [1,2,3].
 
-The ``is`` Predicate
+The Is Predicate
 %%%%%%%%%%%%%%%%%%%%
 
 Syntax: ``exp IS pattern``
@@ -437,13 +449,15 @@ Example,
 ::
       if v is (x,y) do
          io @println "success".
-         assert(isdefined x).
-         assert(isdefined y).
+         assert(isdefined "x").
+         assert(isdefined "y").
       else
          io @println "not matched".
+         assert(not isdefined "x").
+         assert(not isdefined "y").
       end
 
-The ``in`` Predicate
+The In Predicate
 %%%%%%%%%%%%%%%%%%%%
 
 Syntax: ``exp IN list_exp``
@@ -456,6 +470,27 @@ Example,
 ::
       let true = 1 in [1,2,3].
 
+The Eval Function
+%%%%%%%%%%%%%%%%%
+
+The ``eval`` function allows you to evaluate Asteroid expressions.  If the expression
+is a string then the contents of the string is treated like Asteroid code and is
+interpreted accordingly in the current interpreter environment.  If that code produces a value then the ``eval`` function
+will return that value, e.g.,
+::
+      let a = eval "1+1".
+      assert(a == 2).
+
+If the expression to be evaluated is a simple, structural pattern then the pattern is 
+evaluated as a constructor where variables are instantiated from the current environment.
+For example,
+::
+      let p = pattern (x,y)
+      let x = 1.
+      let y = 2.
+      let o = eval p.
+      assert(o is (1,2)).
+
 List Comprehensions
 %%%%%%%%%%%%%%%%%%%
 
@@ -515,7 +550,7 @@ First-Class Patterns
 %%%%%%%%%%%%%%%%%%%%
 
 | Syntax: ``PATTERN exp``
-| Syntax: ``* exp``
+| Syntax: ``'*' exp (BIND '[' ID (AS ID)? (',' ID (AS ID)?)*']')?``
 
 This construction allows the user to construct a pattern as a value using
 the ``pattern`` keyword.  The advantage of patterns as values is that they
@@ -534,6 +569,21 @@ variables, e.g.
 Here the pair ``(1,2)`` is matched against the pattern stored in the variable ``p``
 such that ``x`` is bound to the value ``2``.
 
+The optional ``bind`` term together with an appropriate list of variable names 
+allows the user to selectively project variable bindings from a constraint pattern 
+into the current scope.  The ``as`` keyword allows you to rename those bindings.
+Consider the following program,
+::
+      let Pair = pattern %[(x,y)]%.
+
+      -- bindings of the variables x and y are now visible as a and y respetively
+      let *Pair bind [x as a, y] = (1,2).  
+      assert( a == 1).
+      assert(y == 2).
+
+At the second  ``let`` statement we bind the ``x`` as ``a`` and ``y`` from the hidden scope 
+of the constraint pattern into our current scope.
+
 Type Patterns
 %%%%%%%%%%%%%
 
@@ -553,8 +603,8 @@ Named Patterns
 Syntax: ``name_exp ':' pattern``
 
 Named patterns allow you to bind the term matched by the pattern to a variable.
-Here the name expression has to evaluate to something that looks like a variable,
-object member variable, or array location.
+Here the name expression has to evaluate to either a variable,
+object member variable, or list location.
 
 Example,
 ::
@@ -563,6 +613,15 @@ Example,
 The variable ``x`` will be bound to the value of ``val`` if that value matches the
 type pattern ``%integer``.
 
+Named patterns are a syntactic short hand for the equivalent conditional pattern,
+::
+      name_exp if name_exp is pattern
+
+That means the following two ``let`` statements are equivalent,
+::
+      let x:(q,p) = (1,2).
+      let x if x is (q,p) = (1,2).
+
 Conditional Patterns
 %%%%%%%%%%%%%%%%%%%%
 
@@ -581,7 +640,7 @@ Here ``k`` only matches the value of ``val`` if that value is an even number.
 Pure Constraint Patterns
 %%%%%%%%%%%%%%%%%%%%%%%%
 
-Syntax: ``%[ pattern ]%``
+Syntax: ``%[ pattern ]% (BIND '[' ID (AS ID)? (',' ID (AS ID)?)*']')?``
 
 A pure constraint pattern is a pattern that does not create any bindings
 in the current scope.  Any pattern can be turned into a pure constraint pattern
@@ -613,34 +672,54 @@ are written in quotes.
 ::
 #include "/tmp/grammar.tmp"
 
+Notes on Function Argument Notation
+-----------------------------------
+
+Functions in Asteroid are multi-dispatch functions and therefore can be called with a variety 
+of input configurations.  This is reflected in the documentation of built-in functions and 
+functions belonging to modules: when a function can be called with different input argument 
+configurations then the documentation reflects this by providing different argument configuration 
+separated by a '``|``' symbol.  E.g.,
+
+      list @pop () | ix:%integer
+
+indicating that the list member function ``pop`` can be called either with the empty argument ``()`` or with a 
+single integer value.
 
 Builtin Functions
 -----------------
 
-* Function ``len``, when given an input value, returns the length of that input. The
-  function can only be applied to lists, strings, tuples, or structures.
+**getid** x
+      Returns a unique id of any Asteroid object as an integer.
+
+**hd** x:%list
+      Returns the first element of a list. It is an error to apply this 
+      function to an empty list.
 
-* Function ``hd``, when given a list as input returns the first element of that list.
-  It is an error to apply this function to an empty list.
+**isdefined** x:%string
+      Returns true if a variable or type name is defined in the
+      current environment otherwise it returns false. The variable or type name must be given as a string.
+**len** x
+      Returns the length of x. The
+      function can only be applied to lists, strings, tuples, or structures.
 
-* Function ``tl``, when given a list as input returns the rest of the list without the first element.
-  It is an error to apply this function to an empty list.
+**range**  stop:%integer | (start:%integer, stop:%integer) | (start:%integer, stop:%integer, inc:%integer)
+      Compute a list of values depending on the input values:
 
-* Function ``range`` will compute a list of values depending on the input values:
+      1. If only the stop value is given then the list [0 to stop-1] is returned.
+      2. If the start and stop values are given then the list [start to stop-1] is returned.
+      3. If in addition to the start and stop values the inc values is given then the list [start to stop-1 step inc] is returned.
 
-  1. ``(start:%integer,stop:%integer)`` returns list ``[start to stop-1]``.
-  2. ``(start:%integer,stop:%integer,inc:%integer)`` returns list ``[start to stop-1 step inc]``.
-  3. ``(stop:%integer)`` returns list ``[0 to stop-1]``.
+**tl** x:%list
+      Returns the rest of the list without the first element.  It is an 
+      error to apply this function to an empty list.
 
-* Function ``getid`` returns the id (physical memory address) of any Asteroid object as an Asteroid integer.
 
-* Function ``isdefined`` returns true if a variable or type name is defined in the
-  current environment otherwise it returns false. The variable or type name must be given as a string.
 
 List and String Objects
 -----------------------
 
-In Asteroid, both ``lists`` and ``strings,`` are treated like objects. Due to this, they have member functions that can manipulate the contents of those objects.
+In Asteroid, both ``lists`` and ``strings,`` are treated like objects in the OO sense. Due to this, they have member functions that can manipulate the contents of those objects.
 
 Lists
 ^^^^^
@@ -649,85 +728,155 @@ A **list** is a structured data type that consists of square brackets enclosing
 comma-separated values.
 Member functions on lists can be called on the data structure directly, e.g.::
 
-   [1,2,3] @length()
+   [1,2,3] @length ()
 
-* Function ``length`` returns the number of elements within that list.
-* Function ``append``, given ``(item)``, adds that item to the end of a list.
-* Function ``extend``, given ``(item)``, will extend the list by adding all the items from the item where ``item`` is either a list, a string or a tuple.
-* Function ``insert``, given ``(ix:%integer,item)``, will insert an item at a given position. The first argument is the index of the element before which to insert, so ``a@insert(0, x)`` inserts at the front of the list, and ``a@insert(a@length(), x)`` is equivalent to ``a@append(x)``.
-* Function ``remove``, given ``(item)``, removes the first element from the list whose value is equal to ``(item)``. It raises a ValueError if there is no such item.
-* Function ``pop``, given ``(ix:%integer)``, removes the item at the given position in the list and returns it. If no index is specified,``a@pop()`` removes and returns the last item in the list.
-* Function ``clear``, given ``(none)``, removes all items from the list.
-* Function ``index`` returns a zero-based index in the list of the first element whose value is equal to ``(item)``. It raises a ValueError exception if there is no such item. The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the ``(startix)`` argument.   This function can be called with several input configurations:
+Member Functions
+%%%%%%%%%%%%%%%%
 
-  1. ``(item,loc(startix:%integer,endix:%integer))``
-  2. ``(item,loc(startix:%integer))``
-  3. ``item``
+list **@append** item
+      Adds the item to the end of the list.
 
-* Function ``count``, given ``(item)``, returns the number of times ``(item)`` appears in the list.
-* Function ``sort`` sorts the items of the list in place. It can be called with several different inputs:
+list **@clear** ()
+      Removes all items from the list.
 
-  1. ``(reverse:%boolean)`` if the boolean is set to true then the sorted list is reversed.
-  2. ``none`` returns the reverse list.
+list **@copy** ()
+      Returns a shallow copy of the list.
 
-* Function ``reverse``, reverses the elements of the list in place.
-* Function ``copy``, makes a shallow copy of the list.
-* Function ``shuffle``, returns a random permutation of a given list - in place!
-* Function ``map``, given ``(f:%function)``, applies ``f`` to each element of the list in place. The modified list is returned.
-* Function ``reduce`` reduces the value of elements in a list. This
-  function can be called with several different inputs:
+list **@count** item
+      Returns the number of times item appears in the list.
 
-  1. Input ``(f:%function)`` returns ``value``, such that ``value = f(value,this@i)``.
-  2. Input ``(f:%function,init)`` returns the same format but uses ``init`` as an initial value.
+list **@extend** item
+      Extend the list by adding all the elements from the item to the list where the item is either a list or a tuple.
 
-  The first argument to ``f`` is the accumulator.
+list **@filter** f:%function
+      Returns a list constructed from those elements for which function f returns true. 
 
-* Function ``filter``, given ``(f:%function)``, constructs an output list from those elements of the list for which ``f`` returns true. If ``f`` is none, the identity function is assumed, that is, all elements of the input list that are false are removed.
-* Function ``member``, given ``(item)``, returns true only if ``item`` exists on the list.
-* Function ``join``, given ``(join:%string)``, turns the list into a string using ``join`` between the elements.  The string is returned
-  as the return value from this function.
+list **@index** item | (item, loc(startix:%integer) | (item, loc(startix:%integer, endix:%integer))
+      Returns a zero-based index of the first element whose value is equal to item. 
+      It throws an exception if there is no such item. The argument loc allows you to specify 
+      startix and endix and are used to limit the search to a particular subsequence of the list. 
+      The returned index is computed relative to the beginning of the list rather than the startix argument.   
 
+list **@insert** (ix:%integer, item)
+      Insert the item into the list at the position i.
+      This means that ``a@insert(0, x)`` inserts x at the front of the list, and ``a@insert(a@length(), x)`` is equivalent to ``a@append(x)``.
 
-See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_ for more on all the functions above.
+list **@join** join_str:%string
+      Turns the list into a string using join_str between the elements.  The string is returned
+      as the return value from this function.
 
+list **@length** ()
+      Returns the number of elements within the list.
 
-Strings
-^^^^^^^
+list **@map** f:%function
+      Applies the function f to each element of the list in place. The modified list is returned.
 
-A string is a sequence of characters that can be used as a variable or a literal constant.
-Similar to lists the member functions of strings can be called directly on the
-data structure itself, e.g.::
+list **@member** item
+      Returns true only if item exists on the list.
+
+list **@pop** () | ix:%integer
+      Removes the item at the given position in the list and returns it. If no index is specified
+      removes and returns the last item in the list.
 
-   "Hello there" @length()
+list **@reduce** f:%function | (f:%function, init)
+      Reduce the list to a value by applying the function f to all the members of the list. The function f has to be
+      a function with two arguments where the first argument is the accumulator.  If no initial
+      value is given then the first element of the list is assumed to be the first accumulator value.
+      In order to illustrate, we have::
 
-* Function ``length`` returns the number of characters within that string.
-* Function ``explode``, turns a string into a list of characters.
-* Function ``trim``, given the input ``(what:%string)``, returns a copy of the string with the leading and trailing characters removed. The ``what`` argument is a string specifying the set of characters to be removed. If omitted or none, the ``what`` argument defaults to removing whitespace. The ``what`` argument is not a prefix or suffix; rather, all combinations of its values are stripped.
-* Function ``replace`` will return a copy of the string with all occurrences of regular expression pattern ``old`` replaced by the string ``new``. If the optional argument count is given, only the first count occurrences are replaced. It can be called with several different inputs:
+            let value = [1,2] @reduce (lambda with (x,y) do x+y, 0).
+            assert(value == 3).
 
-  * ``(old:%string,new:%string,count:%integer)``
-  * ``(old:%string,new:%string)``
+      is equivalent to ::
 
-* Function ``split`` will return a list of the words in a given string, using ``sep`` as the delimiter string. If ``maxsplit`` is given: at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).
-  If ``sep`` is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, ``"1,,2"@split(",")`` returns ``["1", "", "2"]``). The ``sep`` argument may consist of multiple characters (for example, ``"1<>2<>3"@split("<>")`` returns ``["1", "2", "3"]``). Splitting an empty string with a specified separator returns ``[""]``.
-  If ``sep`` is not specified or is None, a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string or a string consisting of just whitespace with a None separator returns ``[]``.
-  Function ``split`` can be called with several different inputs:
+            let l = [1,2].
+            let value = 0.
+            for i in range(l@length()) do
+                  let value = (lambda with (x,y) do x+y) (value,l@i).
+            end
+            assert(value == 3).
 
-  1. Input ``(sep:%string,count:%integer)``
-  2. Input ``(sep:%string)``
-  3. Input ``(none)``
+list **@remove** item
+      Removes the first element from the list whose value is equal to item. 
+      It throws an exception if there is no such item.
 
-* Function ``toupper``, converts all the lowercase letters in a string to uppercase.
-* Function ``tolower``, converts all the uppercase letters in a string to lowercase.
-* Function ``index`` allows the user to search for a given ``item`` in a list. It returns an integer index into the string or ``none`` if ``item`` was not found.  The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular substring of the string. The returned index is computed relative to the beginning of the full string rather than the ``(startix)`` argument.The function can be called with several different inputs:
+list **@reverse** ()
+      Reverses the elements of the list in place and returns the reversed list.
 
-  1. Input ``(item:%string,loc(startix:%integer,endix:%integer))``
-  2. Input ``(item:%string,loc(startix:%integer))``
-  3. Input ``(item:%string)``
+list **@shuffle** ()
+      Creates a random permutation of the list in place and returns the randomized list.
 
-* Function ``flip`` reverses a string.
+list **@sort** () | reverse:%boolean
+      Sorts the items of the list in place and returns the sorted list. 
+      If the boolean reverse is set to true then the sorted list is reversed.
+
+
+Strings
+^^^^^^^
+
+A string is a sequence of characters surrounded by double quotes.
+In Asteroid, single characters are represented as single character strings.
+Similar to lists the member functions of strings can be called directly on the
+data structure itself, e.g.::
+
+   "Hello there" @length ()
+
+Member Functions
+%%%%%%%%%%%%%%%%
+
+string **@explode** ()
+      Returns the string as a list of characters.
+
+string **@flip** ()
+      Returns a copy of the string with its characters in the reverse order.
+
+string **@index** item:%string | (item:%string, loc(startix:%integer)) | (item:%string, loc(startix:%integer, endix:%integer))
+      Returns an integer index of the item in the string or none if item was not found.  
+      The  argument loc allows you to specify startix and endix and are used to limit the search 
+      to a particular substring of the string. The returned index is computed relative to the beginning 
+      of the full string rather than the startix.  
+
+string **@length** ()
+      Returns the number of characters within the string.
+
+string **@replace** (old:%string, new:%string) | (old:%string, new:%string, count:%integer)
+      Return a copy of the string with all occurrences of regular expression old replaced by the 
+      string new. If the argument count is given, only the first count occurrences are replaced. 
+
+string **@split** () | sep:%string | (sep:%string, count:%integer)
+      Return a list of the words in the string, using sep as the delimiter. If count is given then
+      at most count splits are done (thus, the list will have at most count+1 elements). If count is 
+      not specified or -1, then there is no limit on the number of splits (all possible splits are made).
+      Consecutive delimiters are not grouped together and are deemed to delimit empty strings. 
+      For example::
+      
+            let s = "1,,2" @split ",".
+            assert (s == ["1", "", "2"]). 
+            
+      The sep argument may consist of multiple characters. 
+      For example:: 
+      
+            let s = "1<>2<>3" @split "<>". 
+            assert (s == ["1", "2", "3"]).
+            
+      Splitting an empty string with a specified separator returns ``[""]``.
+      If sep is not specified or is None, a different splitting algorithm is applied: 
+      consecutive whitespace is regarded as a single separator, and the result will contain no empty strings at 
+      the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string 
+      or a string consisting of just whitespace with a none separator returns ``[]``.
+ 
+string **@tolower** ()
+      Returns a copy of the string in all lower case letters.
+
+string **@toupper** ()
+      Returns a copy of the string in all upper case letters.
+
+string **@trim** () | what:%string
+      Returns a copy of the string with the leading and trailing characters removed. 
+      The what argument specifies the set of characters to be removed. 
+      If omitted trim defaults to removing whitespace. 
+      The what argument is not a prefix or suffix; rather, all combinations of its characters are stripped.
 
-See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_  for more on all the functions above.
 
 
 Asteroid Modules
@@ -741,147 +890,439 @@ we have ``println`` as one of the member functions.  To call that function::
    load system io.
    io @println "Hello there!".  -- println is a member function of the io module
 
-Bitwise
+bitwise
 ^^^^^^^
 
-The `bitwise <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/bitwise.ast>`_ module defines Bitwise operations. It supports the following functions,
-
-* Function ``band`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise AND operation.
-* Function ``bor`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise OR operation.
-* Function ``bnot`` can be called with the input ``(x:%integer)``, and performs the Bitwise NOT operation.
-* Function ``bxor`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise XOR operation.
-* Function ``blshift`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise left shift operation.
-* Function ``brshift`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise right shift operation.
-* Function ``blrotate`` can be called with the input ``(x:%integer, i:%integer)``, and performs the Bitwise left rotate operation.
-* Function ``brrotate`` can be called with the input ``(x:%integer, i:%integer)``, and performs the Bitwise right rotate operation.
-* Function ``bsetbit`` can be called with the input ``(x:%integer, i:%integer)``, and sets the ith bit.
-* Function ``bclearbit`` can be called with the input ``(x:%integer, i:%integer)``, and clears the ith bit.
-* Function ``bsize``can be called with the input ``(x:%integer)``, and returns the bit size.
-
-Hash
+This module defines bitwise operations on integers. It supports the following functions,
+
+bitwise **@band** (x:%integer, y:%integer)
+      Performs the bitwise AND operation and returns the result as an integer.
+
+bitwise **@bclearbit** (x:%integer, i:%integer)
+      Clear the ith bit in x and returns the result as an integer.
+
+bitwise **@blrotate** (x:%integer, i:%integer)
+      Performs the bitwise left rotate operation by i bits and returns the result as an integer.
+
+bitwise **@blshift** (x:%integer, y:%integer)
+      Performs the bitwise left shift operation where x is shifted by y bits and returns the result as an integer.
+
+bitwise **@bnot** x:%integer
+      Performs the bitwise NOT operation and returns the result as an integer.
+
+bitwise **@bor** (x:%integer, y:%integer)
+      Performs the bitwise OR operation and returns the result as an integer.
+
+bitwise **@brrotate** (x:%integer, i:%integer)
+      Performs the bitwise right rotate operation by i bits and returns the result as an integer.
+
+bitwise **@brshift** (x:%integer, y:%integer)
+      Performs the bitwise right shift operation where x is shifted by y bits and returns the result as an integer.
+
+bitwise **@bsetbit** (x:%integer, i:%integer)
+      Sets the ith bit in x and returns the result as an integer.
+
+bitwise **@bsize** x:%integer
+      Returns the bit size of x.
+
+bitwise **@bxor** (x:%integer, y:%integer)
+      Performs the bitwise XOR operation and returns the result as an integer.
+
+
+hash
 ^^^^
 
-The `hash <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/hash.ast>`_ module implements a hash for name-values pairs. It supports the following functions,
+This module implements a hash for key-value pairs. It supports the following functions,
+
+hash **@hash** ()
+      Returns a new hash object of type __HASH__.
+
+__HASH__ **@aslist** ()
+      Returns the hash as a list of key-value pairs.
 
-* Function ``insert``, given the input ``(name,value)``, will insert a given name-value pair into the table.
-* Function ``get``, given ``name``, will return the ``value`` associated with the given ``name`` as long as it can be found otherwise an exception will be thrown.
-* Function ``aslist`` returns the hash as a list of name-value pairs.
+__HASH__ **@get** key
+      Return the value associated with the given key as long as it can be found otherwise an exception will be thrown.
 
-IO
+__HASH__ **@insert** (key, value) | pairs:%list
+      Given a pair of the format (key, value) insert it into the table.  Given a list
+      of the format::
+
+            [(key1, val1), (key2, val2), ...]
+
+      insert all the key-value pairs on the list into the hash.
+
+io
 ^^
 
-The `io <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/io.ast>`_ module implements Asteroid's I/O system. The module defines three default streams,
+This module implements Asteroid's I/O system. The module defines three I/O streams,
 
-1. ``__STDIN__`` - the standard input stream.
-2. ``__STDOUT__`` - the standard output stream.
-3. ``__STDERR__`` - the standard error stream.
+1. __STDIN__ - the standard input stream.
+2. __STDOUT__ - the standard output stream.
+3. __STDERR__ - the standard error stream.
 
 Furthermore, the module supports the following functions,
 
-* Function ``println`` can be called with ``item``, and prints a given argument to the terminal (``__STDOUT__``) with an implicit newline character.
-* Function ``print`` can be called with ``item``, and prints a given argument. No implicit newline is appended to the output.
-* Function ``input`` can be called with a string ``prompt``.  If ``prompt`` is given it is printed and then input is read from the terminal (``__STDIN__``) and returned as a string.
-* Function ``open`` opens a file. Given ``(name:%string, mode:%string)``, it returns a file descriptor of type ``FILE``. The ``mode`` string can be ``"r"`` when the file will only be read, ``"w"`` for only writing (an existing file with the same name will be erased), and ``"a"`` opens the file for appending; any data written to the file is automatically added to the end. The ``"r+"`` opens the file for both reading and writing.
-* Function ``close``, given ``file:%FILE``, closes that file.
-* Function ``read``, given ``file:%FILE``, reads a file. If no file is given the ``__STDIN__`` stream is read.
-* Function ``readln``, given ``file:%FILE``, reads a given line of input from the file. If no file is given the ``__STDIN__`` stream is read.
-* Function ``write``, given ``(file:%FILE, what:%string)``, will write ``what`` to the given ``file``.  If ``file`` is not given then it writes to the ``__STDOUT__`` stream.
-* Function ``writeln``, works the same way as ``write`` except that it appends a newline character to the output.
-
-Math
-^^^^
-
-The `math <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/math.ast>`_ module implements mathematical constants and functions. It supports the following functions,
+io **@close** file:%\_\_FILE\_\_
+      Closes the file where file is a file descriptor of type \_\_FILE\_\_.
 
-*Power and logarithmic functions*
+io **@input** () | prompt:%string
+      Ask the user for input from __STDIN__.  The input is returned as a string. If prompt is given it is printed and then input is read from terminal.
 
-* Function ``exp``, given ``x:%integer``, returns e raised to the power ``x``, where e = 2.718281… is the base of natural logarithms.
-* Function ``log`` can be called with two different argument setups,
+io **@open** (name:%string, mode:%string)
+      Returns a file descriptor of type \_\_FILE\_\_. 
+      The mode string can be "r" when the file will only be read, 
+      "w" for only writing (an existing file with the same name will be erased), 
+      and "a" opens the file for appending; any data written to the file is 
+      automatically added to the end. 
+      Finally,  "r+" opens the file for both reading and writing.
 
-  1. If only one argument, ``(x)``, is input, this returns the natural logarithm of x (to base e).
-  2. If two arguments, ``(x,base)``, are input, this returns the logarithm of x to the given base, calculated as log(x)/log(base).
+io **@print** item
+      Prints item to the terminal (__STDOUT__). No implicit newline is appended to the output.
 
-* Function ``pow``, given ``(b,p:%integer)``, returns "b <sup>p</sup>" as long as b is either ``real`` or ``integer``.
-* Function ``sqrt``, given ``a``, returns its square root as long as ``a`` is either ``real`` or ``integer``.
+io **@println** item
+      Prints item to the terminal (__STDOUT__) with an implicit newline character.
 
-*Number-theoretic and representation functions*
+io **@read** () | file:%\_\_FILE\_\_
+      Read a file and return the contents as a string. If no file is given the __STDIN__ stream is read.
 
-* Function ``abs``, given ``x``, returns its absolute value.
-* Function ``ceil``, given ``x:%real``, returns the ceiling of x: the smallest integer greater than or equal to x.
-* Function ``floor``, given ``x:%real``, returns the floor of x: the largest integer less than or equal to x.
-* Function ``gcd``, given ``(a:%integer,b:%integer)``, returns the greatest common denominator that both integers share.
-* Function ``isclose`` can be called with two different argument setups,
+io **@readln** () | file:%\_\_FILE\_\_
+      Reads a line of input from a file and returns it as a string. If no file is given the __STDIN__ stream is read.
 
-  1. With input values ``(a,b)``, it returns returns ``true`` if the two values are close to each other and ``False`` otherwise. Default tolerance 1e-09.
-  2. With input values ``(a,b,t)``, it compares ``a`` and ``b`` with tolerance ``t``.
+io **@write** what:%string | (file:%\_\_FILE\_\_, what:%string)
+      Write what to a file.  If file is not given then it writes to the __STDOUT__ stream.
 
-* Function ``mod``, given ``(v,d)``, will return the remainder of the operation ``v/d``, as long as ``v`` and ``d`` are either ``real`` or ``integer`` values.
+io **@writeln** what:%string | (file:%\_\_FILE\_\_, what:%string)
+      Write what to a file and append a newline charater.  If file is not given then it writes to  __STDOUT__.
 
-*Trigonometric functions*
 
-* Function ``acos``, given ``x``, returns the arc cosine of x in radians. The result is between 0 and pi.
-* Function ``asin``, given ``x``, returns the arc sine of x in radians. The result is between -pi/2 and pi/2.
-* Function ``atan``, ,given ``x``, returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
-* Function ``cos``, given ``x``, returns the cosine of x radians.
-* Function ``sin``, given ``x``, returns the sine of x radians.
-* Function ``tan``, given ``x``, returns the tangent of x radians.
-* Function ``acosh``, given ``x``, returns the inverse hyperbolic cosine of x.
-* Function ``asinh``, given ``x``, returns the inverse hyperbolic sine of x.
-* Function ``atanh``, given ``x``, returns the inverse hyperbolic tangent of x.
-* Function ``cosh``, given ``x``, returns the hyperbolic cosine of x.
-* Function ``sinh``, given ``x``, returns the hyperbolic sine of x.
-* Function ``tanh``, given ``x``, returns the hyperbolic tangent of x.
-* Function ``degrees``, given ``x``, converts angle ``x`` from radians to degrees.
-* Function ``radians``,  given ``x``, converts angle ``x`` from degrees to radians.
+math
+^^^^
 
-An example,
+The math module implements mathematical constants and functions.
+An example:
 ::
 #include "../asteroid/test-suites/ref-programs/math.ast"
 
-Pick
+Constants
+%%%%%%%%%
+
+math **@pi**
+      The mathematical constant π = 3.141592…, to available precision.
+
+math **@e**
+      The mathematical constant e = 2.718281…, to available precision.
+
+
+Power and logarithmic functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+math **@exp** x:%integer
+      Returns e raised to the power x, where e = 2.718281… is the base of the natural logarithm.
+
+math **@log** x | (x, base:%integer)
+      If only argument x is the input, return the natural logarithm of x (to base e).
+      If two arguments, (x, base:%integer), are given as input, return the logarithm 
+      of x to the given base, calculated as log(x)/log(base).
+
+math **@pow** (b, p:%integer)
+      Return b raised to the power p.  The return type depends on the type
+      of the base.
+
+math **@sqrt** x 
+      Return the square root of x as a real.
+
+
+Number-theoretic and representation functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+math **@abs** x
+      Return that absolute value of x.  The return type depends on the type of x.
+
+math **@ceil** x:%real
+      Returns the ceiling of x: the smallest integer greater than or equal to x.
+
+math **@floor** x:%real
+      Returns the floor of x: the largest integer less than or equal to x.
+
+math **@gcd** (a:%integer, b:%integer)
+      Returns the greatest common denominator that both integers share.
+
+math **@isclose** (a:%real, b:%real) | (a:%real, b:%real, t:%real)
+      Return true if the values a and b are close to each other and false otherwise.
+      Default tolerance is 1e-09.  An alternative tolerance can be specified with 
+      the t argument.
+
+math **@mod** (v,d)
+      Implements the modulus operation. Returns the remainder of the quotient v/d.
+
+
+Trigonometric functions
+%%%%%%%%%%%%%%%%%%%%%%%
+
+math **@acos** x
+      Returns the arc cosine of x in radians. The result is between 0 and pi.
+
+math **@asin** x
+      Returns the arc sine of x in radians. The result is between -pi/2 and pi/2.
+
+math **@atan** x
+      Returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
+
+math **@cos** x
+      Returns the cosine of x radians.
+
+math **@sin** x
+      Returns the sine of x radians.
+
+math **@tan** x
+      Returns the tangent of x radians.
+
+Hyperbolic functions
+%%%%%%%%%%%%%%%%%%%%
+
+math **@acosh** x
+      Returns the inverse hyperbolic cosine of x.
+
+math **@asinh** x
+      Returns the inverse hyperbolic sine of x.
+
+math **@atanh** x
+      Returns the inverse hyperbolic tangent of x.
+
+math **@cosh** x
+      Returns the hyperbolic cosine of x.
+
+math **@sinh** x
+      Returns the hyperbolic sine of x.
+
+math **@tanh** x
+      Returns the hyperbolic tangent of x.
+
+Angular conversion
+%%%%%%%%%%%%%%%%%%
+
+math **@degrees** x
+      Converts angle x from radians to degrees.
+
+math **@radians** x
+      Converts angle x from degrees to radians.
+
+
+os
+^^
+
+This module provides a portable way of using operating system dependent functionality. 
+
+Process Parameters
+%%%%%%%%%%%%%%%%%%
+
+os **@argv**
+      The list of command line arguments passed to an Asteroid script. 
+      argv[0] is the name of the Asteroid script (it is operating 
+      system dependent whether this is a full pathname or not).
+      In interactive mode argv[0] will be the empty string.
+
+os **@env**
+      A hash table where keys and values are strings that represent 
+      the process environment. For example, 
+            os @env @get "HOME"
+      is the pathname of your home directory (on some platforms), 
+      and is equivalent to getenv("HOME") in C.
+
+os **@platform**
+      This string contains a platform identifier.
+
+
+Functions
+%%%%%%%%%
+
+os **@basename** path:%string
+      Return the base name of pathname path. This is the second element of the pair
+      returned by passing path to the function split. Note that the result of this
+      function is different from the Unix basename program; where basename for '/foo/bar/'
+      returns 'bar', the basename function returns an empty string ("").
+
+os **@chdir** path:%string
+      Change the current working directory to path.
+
+os **@dirname** path:%string
+      Return the directory name of pathname path. This is the first element of the 
+      pair returned by passing path to the function split.
+
+os **@exists** path:%string
+      Return true if path refers to an existing path or an open file descriptor. 
+      Returns false for broken symbolic links. On some platforms, this function 
+      may return False if permission is not granted to execute stat on 
+      the requested file, even if the path physically exists.
+
+os **@exit** () | v:%integer | msg:%string
+      Signaling an intention to exit the interpreter.
+      When an argument value other than none is provided
+      it is considered a status value. If it is 
+      an integer, zero is considered “successful termination” and any 
+      nonzero value is considered “abnormal termination” by shells and 
+      the like. Most systems require it to be in the range 0–127, and 
+      produce undefined results otherwise. Some systems have a 
+      convention for assigning specific meanings to specific exit codes, 
+      but these are generally underdeveloped; Unix programs generally 
+      use 2 for command line syntax errors and 1 for all other kind 
+      of errors. If none is given as an argument value then is it
+      is considered to be a successful exit equivalent to passing a zero. 
+      If a string is passed then it is printed printed to 
+      __STDERR__ and results in an exit code of 1. In particular, 
+      sys.exit("some error message") is a quick way to exit a program 
+      when an error occurs.
+
+os **@getdir** ()
+      Return a string representing the current working directory.
+
+os **@getpathtime** path:%string | (path:%string,flag:%boolean)
+      Returns a triple with (creation, access, modification) times.
+      By default the return value is a triple of real numbers
+      giving the number of seconds since 1/1/1970.  If the flag is set
+      to true then a triple of strings is returned where each string
+      represents the respective local time. Throws an exception if the file 
+      does not exist or is inaccessible.
+
+os **@getsize** path:%string
+      Return the size, in bytes, of path. Throws exception if the file 
+      does not exist or is inaccessible.
+
+os **@isfile** path:%string
+      Return true if path is an existing regular file. This follows 
+      symbolic links.
+
+os **@isdir** path:%string
+      Return true if path is an existing directory. This follows 
+      symbolic links.
+
+os **@join** (path1:%string,path2:%string)
+      Join path1 and path2 components intelligently. The return value 
+      is the concatenation of path and any members of *paths with 
+      exactly one directory separator following each non-empty part 
+      except the last, meaning that the result will only end in a 
+      separator if the last part is empty. If the second component is an 
+      absolute path, the first component is thrown away. 
+
+      On Windows, the drive letter is not reset when an absolute 
+      path component (e.g., r'\foo') is encountered. If a component 
+      contains a drive letter, all previous components are thrown away 
+      and the drive letter is reset. Note that since there is a current 
+      directory for each drive, os.path.join("c:", "foo") represents a 
+      path relative to the current directory on drive C: (c:foo), not c:\foo.
+
+os **@split** path:%string
+      Split the pathname path into a pair, (head, tail) where tail is 
+      the last pathname component and head is everything leading up to 
+      that. The tail part will never contain a slash; if path ends in 
+      a slash, tail will be empty. If there is no slash in path, head 
+      will be empty. If path is empty, both head and tail are empty. 
+      Trailing slashes are stripped from head unless it is the root 
+      (one or more slashes only). Also see the functions dirname and 
+      basename.
+
+os **@splitdrive** path:%string
+      Split the pathname path into a pair (drive, tail) where drive is 
+      either a mount point or the empty string. On systems which do not 
+      use drive specifications, drive will always be the empty string. 
+      In all cases, drive + tail will be the same as path.
+
+      On Windows, splits a pathname into drive/UNC sharepoint and 
+      relative path.
+
+      If the path contains a drive letter, drive will contain everything 
+      up to and including the colon.
+
+os **@splitext** path:%string
+      Split the pathname path into a pair (root, ext) such that 
+      root + ext == path, and the extension, ext, is empty or begins 
+      with a period and contains at most one period. If the path contains 
+      no extension, ext will be the empty string.
+
+os **@syscmd** cmd:%string
+      Execute a command in a subshell. This is implemented 
+      by calling the Standard C function system, and has the same 
+      limitations. If command generates any output, it will be 
+      sent to the interpreter standard output stream. 
+      The C standard does not specify the meaning of the return value of 
+      the C function, so the return value of this function is 
+      system-dependent.
+
+
+
+
+pick
 ^^^^
 
-The `pick <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/pick.ast>`_ module implements
-pick objects that allow a user to randomly pick items from a list using the ``pick`` function.
-The ``pick`` function can be called with ``n:%integer`` and returns a list of ``n`` randomly picked objects from the object list.
-Here is a simple use case
+The pick module implements
+pick objects that allow a user to randomly pick items from a list of items using the pickitems function.
+An example:
 ::
 #include "../asteroid/test-suites/ref-programs/pick.ast"
 
 
-Random
+pick **@pick** l:%list
+      Construct a pick object of type __PICK__.
+
+__PICK__ **@pickitems** () | n:%integer
+      Return items randomly picked from the list l.  If no input is provided 
+      then pickitems will return a single, randomly picked item from the list.
+      If an integer value n is given then a list of n randomly picked items from 
+      the list l is returned.  The picked item list is constructed by sampling the 
+      list l with replacement.
+
+
+random
 ^^^^^^
 
-The `random <https://github.com/lutzhamel/asteroid/blob/master/asteroid/modules/random.ast>`_ module implements the ``random`` numbers. Using the functions included in this module will return a random value within a given range or interval. It supports the following functions,
+The random module implements random number generation. 
 
-* Function ``random``, given the input ``none``, returns a random floating point number in the range ``[0.0, 1.0)``.
-* Function ``randint`` returns a random value N in the interval lo <= N <= hi. The exact random value output depends on the types of the values specifying the interval. It can be called with two different number interval inputs:
+random **@randint** (lo:%integer,hi:%integer) | (lo:%real,hi:%real)
+      Return a random value N in the interval lo <= N <= hi.
+      The type of the random value depends on the types of the
+      values specifying the interval.  If the interval is specified 
+      with integers then a random integer value is returned. 
+      If the interval is specified with real numbers then a real value is
+      is returned, and for everything else an exception is thrown.
 
-  1. ``(lo:%integer,hi:%integer)``
-  2. ``(lo:%real,hi:%real)``
-  3. Note: any other interval specification will instead output an error message for "unsupported interval specification in randint."
+random **@random** ()
+      Return a random real number in the range [0.0, 1.0).
 
-* Function ``seed``, given ``(sd:%integer)``, provides a seed value for the random number generator.
+random **@seed** x:%integer
+      Provide the seed value x for the random number generator.
 
-Set
+set
 ^^^
 
-The `set <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/set.ast>`_ module implements Asteroid sets as lists. Unlike lists, sets do not have repeated members. It supports the following functions,
+The set module implements Asteroid sets as lists. 
+Unlike lists, sets do not have repeated elements.
+Use the set member function toset to turn any list 
+into a list that represents a set (remove repeated items).
+
+set **@diff** (a:%list,b:%list)
+      Return the difference set between sets a and b.
+
+set **@intersection** (a:%list,b:%list)
+      Return the intersection of sets a and b.
+
+set **@toset** l:%list
+      Return list l as a set by removing repeated elements.
+
+set **@union** (a:%list,b:%list)
+      Return the union of sets a and b.
+
+set **@xunion** (a:%list,b:%list)
+      Return the elements in a or b but not both.
 
-* Function ``toset``, given ``(lst:%list)``, converts the input list into a set.
-* Function ``diff``, given ``(a:%list,b:%list)``, computes the difference set between the two set ``a`` and ``b``.
-* Function ``intersection``, given ``(a:%list,b:%list)``, finds the intersection between  sets ``a`` and ``b``.
-* Function ``union``, given ``(a:%list,b:%list)``, computes the union of sets ``a`` and ``b``.
-* Function ``xunion``, given ``(a:%list,b:%list)``, returns all elements in ``a`` or ``b``, but not in both.
 
-Sort
+sort
 ^^^^
 
-The `sort <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/sort.ast>`_ module
-defines a parameterized ``sort`` function over a list.
-The ``sort`` function makes use of a user-defined order predicate on the list's elements to
-perform the sort. The ``Quicksort`` is the underlying sort algorithm.
-The following is a simple example,
+The sort  module
+defines a parameterized sort function over a list.
+The sort function makes use of a user-defined order predicate on the list's elements to
+perform the sort. The QuickSort is the underlying sort algorithm.
+The following is a simple example:
 ::
 #include "../asteroid/test-suites/ref-programs/sort.ast"
 
@@ -889,22 +1330,17 @@ prints the sorted list::
 
   [5,10,50,110]
 
-Stream
-^^^^^^
+sort **@sort** (p:%function,l:%list)
+      Returns the sorted list l using the predicate p.
 
-The `stream <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/stream.ast>`_ module implements streams that allow
-the developer to turn any list into a stream supporting interface functions like ``peeking`` ahead or ``rewinding`` the stream.
-The following stream interface functions are available,
 
-* Function ``eof`` returns ``true`` if the stream does not contain any further elements for processing. Otherwise it returns ``false``.
-* Function ``peek`` returns the current element available on the stream otherwise it returns ``none``.
-* Function ``get`` returns the current element and moves the stream pointer one ahead.
-* Function ``rewind`` resets the stream pointer to the first element of the stream.
-* Function ``map`` applies a given function to each element in the stream.
-* Function ``append``, given ``item``, adds item to the end of the stream.
-* Function ``__string__`` maps a the stream to a string representation.
+stream
+^^^^^^
 
-A simple use case.
+The stream module implements streams that allow
+the developer to turn any list into a stream supporting interface functions like peeking ahead or rewinding
+the stream.
+A simple use case:
 ::
 #include "../asteroid/test-suites/ref-programs/stream.ast"
 
@@ -913,32 +1349,35 @@ which outputs::
    1 2 3 4 5 6 7 8 9 10
 
 
-Type
-^^^^
+stream **@stream** l:%list
+      Returns a stream object of type __STREAM__.
 
-The `type <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/type.ast>`_ module defines type related functions and structures.
+__STREAM__ **@append** x
+      Adds x to the end of the stream.
 
-*Type Conversion*
+__STREAM__ **@eof** ()
+      Returns true if the stream does not contain any further elements for processing.
+      Otherwise it returns false.
 
-* Function ``tointeger`` converts a given input to an integer. It can be called with two different arguments,
+__STREAM__ **@get** ()
+      Returns the current element and moves 
+      the stream pointer one ahead.  Returns none if no elements left in stream.
 
-  1. ``(item:%string,base:%integer)`` where ``base`` is a valid base for integer conversion
-  2. ``item`` where ``item`` is converted to a base 10 integer.
+__STREAM__ **@map** f:%function
+      Applies function f to each element in the stream.
 
+__STREAM__ **@peek** () 
+      Returns the current element available on the stream otherwise it returns none.
 
-* Function ``toreal``, given ``item``, returns the input as a real number data type.
-* Function ``toboolean``, given ``item``, returns the input as a Boolean value of either true or false.
-* Function ``tostring`` converts an Asteroid object to a string. If format values are given, it applies the formatting to the object. It can be called with several different inputs where ``*TP`` indicates a``boolean``, ``integer``, or ``string`` type and ``w`` is the width specification, ``p`` is the precision specification and ``s`` is the scientific notation flag.  When no formatting information is provided a default string conversion occurs,
+__STREAM__ **@rewind** ()
+      Resets the stream pointer to the first element of the stream.
 
-  1. ``(v:*TP,type @stringformat(w:%integer))``
-  2. ``(v:%real,type @stringformat(w:%integer))``
-  3. ``(v:%real,type @stringformat(w:%integer,p:%integer))``
-  4. ``(v:%real,type @stringformat(w:%integer,p:%integer,s:%boolean))``
-  5. ``item`` - default conversion
 
-* Function ``tobase`` represents the given integer ``x`` (*specifically* within the given input ``(x:%integer,base:%integer)``) as a string in the given base.
+type
+^^^^
 
-Here is a program that exercises some of the string formatting options,
+The type module defines type related functions and structures.
+Here is a program that exercises some of the string formatting options:
 ::
 #include "../asteroid/test-suites/ref-programs/format.ast"
 
@@ -952,57 +1391,111 @@ The output of the program is,
 
 Notice the right justification of the various values within the given string length.
 
+Type Conversion
+%%%%%%%%%%%%%%%
+
+type **@tobase** (x:%integer,base:%integer)
+      Represents the given integer x as a numeral string in different bases.
+
+type **@toboolean** x
+      Interpret x as a Boolean value.
+
+type **@tointeger** (x:%string,base:%integer) | x 
+      Converts a given input to an integer. If a base value is specified then 
+      the resulting integer is in the corresponding base.
+
+type **@toreal** x
+      Returns the input as a real number.
 
-*Type Query Functions*
+type  **@tostring** x | (x,type @stringformat(width:%integer,precision:%integer,scientific:%boolean)) 
+      Converts an Asteroid object to a string. If format values are given, 
+      it applies the formatting to the string object. 
+      
 
-* Function ``islist`` returns ``true`` if given ``item`` is a list otherwise it will return ``false``.
-* Function ``isscalar`` returns ``true`` if given ``item`` is either an integer or a real value.
-* Function ``isnone`` returns ``true`` if given ``item`` is equal to the value ``none``.
-* Function ``gettype`` returns the type of a given ``item`` as an Asteroid string.
+
+Type Query Functions
+%%%%%%%%%%%%%%%%%%%%
+
+type **@islist** x 
+      Returns true if x is a list otherwise it will return false.
+
+type **@isnone** x
+      Returns true if x is equal to the value none.
+
+type **@isscalar** x
+      Returns true if x is either an integer or a real value.
+
+type **@gettype** x
+      Returns the type of x as a string.
 
 A simple example program using the ``gettype`` function,
 ::
 #include "../asteroid/test-suites/ref-programs/type.ast"
 
-Util
+util
 ^^^^
 
-The `util <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/util.ast>`_ module defines utility functions and structures that don't really fit into any omodules. It supports the following functions,
+The util module defines utility functions and structures that don't really 
+fit into any other modules. 
 
-* Function ``exit`` exits the program. It can be called with two inputs,
+util **@achar** x
+      Given a decimal ASCII code x, return the corresponding character symbol.
 
-  1. ``none``
-  2. ``msg:%string``
+util **@ascii** x:%string
+      Given a character x, return the corresponding ASCII code of the first character of the input.
 
-* Function ``copy``, given Asteroid object ``obj``, makes a deep copy of it.
-* Function ``cls`` clears the terminal screen.
-* Function ``sleep``,  programs sleep for ``secs`` seconds where the argument ``secs`` is either an integer or real value.
-* Function ``zip``, given ``(list1:%list,list2:%list)``, will return a list where element ``i`` of the list is the tuple ``(list1@i,list2@i)``.
-* Function ``unzip``, given a list of pairs will return a pair of lists where the first component of the pair is the list of all the first components of the pairs of the input list and the second component of the return list is a list of all the second components of the input list.
-* Function ``ascii``, given a character ``item:%string``, returns the corresponding ASCII code of the first character of the input string.
-* Function ``achar``, given a decimal ASCII code ``item:%integer``, returns the corresponding character symbol.
+util **@cls** ()
+      Clears the terminal screen.
 
-Vector
-^^^^^^
+util **@copy** x
+      Given the object x, make a deep copy of it.
+
+util **@ctime** x:%real
+      Given a real value representing seconds since 1/1/1970 this function 
+      converts it to a suitable string representation of the date.
+
+type **@sleep** x 
+      Sleep for x seconds where the x is either an integer or real value.
 
-The `vector <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/vector.ast>`_ defines functions useful for vector arithmetic. It supports the following functions.  Here ``a`` and ``b`` are vectors implemented as lists,
+type **@time** ()
+      Returns the local time as a real value in secs since 1/1/1970.
 
-* Function ``add``, given the input ``(a,b)``, returns a vector that contains the element by element sum of the input vectors.
-* Function ``sub``, given the input ``(a,b)``, returns the element by element difference vector.
-* Function ``mult``, given the input ``(a,b)``, returns the element by element vector multiplication.
-* Function ``dot``, given ``(a,b)``, computes the dot product of the two vectors.
-* Function ``op``  allows the developer to vectorize any function. It can be called with three different inputs:
+type **@unzip** x:%list
+      Given a list of pairs x this function will return a pair of lists 
+      where the first component of the pair is the list of all the first 
+      components of the pairs of the input list and the second component 
+      of the return list is a list of all the second components of the input list.
 
-  1. ``(f:%function,a:%list,b:%list)``
-  2. ``(f:%function,a:%list,b if type @isscalar(b))``
-  3. ``(f:%function,a if type @isscalar(a),b:%list)``
+type **@zip** (list1:%list,list2:%list)
+      Returns a list where element i of the list is the tuple (list1@i,list2@i).
 
-Here is a simple example program for the ``vector`` module,
+vector
+^^^^^^
+
+The vector defines functions useful for vector arithmetic. Vectors are implemented as lists.
+Here is a simple example program for the ``vector`` module:
 ::
 #include "../asteroid/test-suites/ref-programs/vector.ast"
 
 which prints the value ``0``.
 
+vector **@add** (a:%list,b:%list) 
+      Returns a vector that contains the element by element sum of the input vectors a and b.
+
+vector **@dot** (a:%list,b:%list) 
+      Computes the dot product of the two vectors a and b.
+
+vector **@mult** (a:%list,b:%list)
+      Returns the element by element vector multiplication of vectors a and b.
+
+vector **@op** (f:%function,a:%list,b:%list) | (f:%function,a:%list,b if type @isscalar(b)) | (f:%function,a if type @isscalar(a),b:%list)
+      Allows the developer to vectorize any function f. Applying scalar values 
+      to vectors is also supported by this function.
+
+vector **@sub** (a:%list,b:%list)
+      Returns the element by element difference vector.
+
+
 Interfacing Asteroid with Python
 --------------------------------
 
diff --git a/docs/User Guide.rst b/docs/User Guide.rst
index 6c82f3d8..8921f5aa 100644
--- a/docs/User Guide.rst
+++ b/docs/User Guide.rst
@@ -1,21 +1,18 @@
+..
+    /******************************************************************
+    This is the source file from which the user guide is generated.
+    We use cpp to insert live code snippets into the document.
+    In order to generate the user guide run the following command
+    on a Unix-like system in the directory of this doc:
 
+    bash generate_docs
 
-
-
-
-
-
-
-
-
-
-
-
+    ******************************************************************/
+..
+   /* header for generated .rst files */
 
 ..
    *** DO NOT EDIT; MACHINE GENERATED ***
-
-
 .. highlight:: none
 
 Asteroid User Guide
@@ -24,21 +21,20 @@ Asteroid User Guide
 Introduction
 ------------
 
-Asteroid is a multi-paradigm programming language supporting first-class patterns.
-The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_, and makes pattern matching one of its core computational mechanisms.  We often refer to this as pattern-matching oriented programming. When we talk about pattern matching we mean structural pattern matching
+Asteroid is a modern, application-oriented, multi-paradigm programming language supporting first-class patterns.
+The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_.  Furthermore, Asteroid is
+dynamically typed and makes pattern matching one of its core computational mechanisms.  When we talk about pattern matching we mean both structural pattern matching
 as well as regular expression matching.
 
 In this document we describe the major features of Asteroid and give plenty of examples.  If you have used a programming language like Python or JavaScript before, then Asteroid should appear very familiar.  However, there are some features which differ drastically from other programming languages due to the core pattern-matching programming
-paradigm.  Here are just two examples:
+paradigm with first-class patterns.  Here are just two examples:
 
 **Example:** All statements that look like assignments are actually pattern-match statements.  For example if we state,
 ::
     let [x,2,y] = [1,2,3].
-
 that means the subject term ``[1,2,3]`` is matched to the pattern ``[x,2,y]`` and ``x`` and ``y`` are bound to the values 1 and 3, respectively.  By the way, there is nothing wrong with the following statement,
 ::
     let [1,2,3] = [1,2,3].
-
 which is just another pattern match without any variable instantiations.
 
 **Example:** Patterns in Asteroid are first-class citizens of the language.
@@ -59,7 +55,6 @@ in order to ensure that the domain of the function is not violated,
         with n:*NEG_INT do            -- use second pattern
             throw Error("undefined for "+n).
         end
-
 As you can see, the program first creates patterns and stores them in the variables
 ``POS_INT`` and ``NEG_INT`` and it uses those patterns later in the code by
 dereferencing those variables with the ``*`` operator.  First-class patterns have
@@ -74,14 +69,14 @@ with programming in Asteroid.
 The Basics
 ----------
 
-As with most languages we are familiar with, Asteroid has **variables** (alpha-numeric symbols starting with an alpha character) and **constants**.  Constants are available for all the **primitive data types**,
+As with most programming languages we are familiar with, Asteroid has variables (alpha-numeric symbols starting with an alpha character) and constants.  Constants are available for all the primitive data types,
 
 * ``integer``, e.g. ``1024``
 * ``real``, e.g. ``1.75``
 * ``string``, e.g. ``"Hello, World!"``
 * ``boolean``, e.g. ``true``
 
-Asteroid arranges these data types in a **type hierarchy**,
+Asteroid arranges these primitive data types in a type hierarchy,
 
 ``boolean`` < ``integer`` < ``real`` < ``string``
 
@@ -89,25 +84,22 @@ Type hierarchies facilitate automatic type promotion.  Here is an example
 where automatic type promotion is used to put together a string from different data types,
 ::
     let x:%string = "value: " + 1.
-
 Here we associate the string ``"value: 1"`` with the variable ``x`` by first promoting the integer value ``1`` to the string ``"1"`` using the fact that ``integer`` < ``string``  according to our type hierarchy  and then interpreting the ``+`` operator as a string concatenation operator.
 
-Asteroid supports two more data types:
+Asteroid also supports the built-in data types:
 
 * ``list``
 * ``tuple``
 
-These are **structured data types** in that they can contain entities that belong to other data types. Both of these data types have constructors which are possibly empty sequences of comma separated values enclosed by square brackets for lists, e.g. ``[1,2,3]``, and enclosed by parentheses for tuples, e.g. ``(x,y)``. For tuples we have the caveat that the 1-tuple is represented by a value followed by a comma to distinguish it from parenthesized expressions, e.g. ``(3,)``.
+These are structured data types in that they can contain entities that belong to other data types. Both of these data types have constructors which are possibly empty sequences of comma separated values enclosed by square brackets for lists, e.g. ``[1,2,3]``, and enclosed by parentheses for tuples, e.g. ``(x,y)``. For tuples we have the caveat that the 1-tuple is represented by a value followed by a comma to distinguish it from parenthesized expressions, e.g. ``(3,)`` the 1-tuple versus ``(3)`` the parenthesized expression.
 Here are some examples,
 ::
     let l = [1,2,3].  -- this is a list
     let t = (1,2,3).  -- this is a tuple
-
 As we said above, in order to distinguish it from a parenthesized value the single element in a 1-tuple has to be followed by a comma, like so,
 ::
     let one_tuple = (1,).  -- this is a 1-tuple
-
-Lists and tuples themselves are also embedded in type hierarchies, although very simple ones:
+Lists are mutable objects whereas tuples are immutable.  Lists and tuples themselves are also embedded in type hierarchies, although very simple ones:
 
 * ``list`` < ``string``
 * ``tuple`` < ``string``
@@ -116,9 +108,9 @@ That is, any list or tuple can be viewed as a string.  This is very convenient f
 ::
     load system io.
     io @println ("this is my list: " + [1,2,3]).
+Here the ``+`` operator acts like a string concantenation operator with the list ``[1,2,3]`` promoted to a string according to the above type hierarchy.
 
-
-Finally, Asteroid supports one more type, namely the ``none`` type.  The ``none`` type has
+Asteroid supports the ``none`` type.  The ``none`` type has
 only one member: A constant named ``none``.  However, it turns out that the null-tuple, a tuple with no components
 indicated by ``()``, also belongs to this type rather than the tuple type discussed earlier. But the ``none``
 data type only has one constant, this implies that ``()`` and ``none`` mean the same thing and can be used
@@ -126,11 +118,25 @@ interchangeably.  That is, the following ``let`` statements will succeed,
 ::
     let none = ().
     let () = none.
-
 showing that ``()`` and ``none`` are equivalent and pattern-match each other.
 The ``none`` data type itself does not belong to any type hierarchy.
 
-By now you probably figured out that statements are terminated with a period and that comments start with a ``--`` symbol and continue till the end of the line.  You probably also figured out that the ``let`` statement is Asteroid's version of assignment even though the underlying mechanism is a bit different.
+We should mention here that because functions and patterns are both first-class citizens in Asteroid we
+also have the types ``function`` and ``pattern``,
+::
+   load system type.
+
+   -- define a function
+   function inc with x do
+      return x+1.
+   end
+
+   -- show that 'inc' is of type 'function'
+   assert (type @gettype(inc) == "function").
+Just like the ``none`` type, neither of these types are
+part of a type hierarchy but we can use them in type patterns (see below).
+
+By now you probably figured out that statements are terminated with a period and that comments start with a ``--`` symbol and continue till the end of the line.  You probably also figured out that the ``let`` statement is Asteroid's version of assignment even though the underlying mechanism is a bit different as we will see when we discuss pattern matching in more detail.
 
 Data Structures
 ---------------
@@ -141,42 +147,40 @@ Lists
 In Asteroid the ``list`` is a fundamental, built-in data structure.  A trait it shares with programming languages such as Lisp, Python, ML, and Prolog.  Below is a list reversal example program.  Notice that lists are zero-indexed and
 elements of a list are accessed via the ``@`` operator,
 ::
-    load system io.    -- load the io module so we can print
+    load system io.
 
-    let a = [1,2,3].             -- construct list a
-    let b = [a @2, a @1, a @0].  -- reverse list a
+    let a = [1,2,3].          -- construct list a
+    let b = [a@2, a@1, a@0].  -- reverse list a
     io @println b.
-
 The output is: ``[3,2,1]``.
 
 We can achieve the same effect by giving a list of index values (a slice) to the ``@`` operator,
 ::
-    load system io.    -- load the io module so we can print
+    load system io.
 
     let a = [1,2,3].     -- construct list a
-    let b = a @[2,1,0].  -- reverse list a using slice [2,1,0]
+    let b = a@[2,1,0].   -- reverse list a using slice [2,1,0]
     io @println b.
-
 In Asteroid lists are considered objects with member functions that can manipulate list
 objects. We could rewrite the above example as,
 ::
     load system io.
 
     let a = [1,2,3].
-    let b = a @reverse(). -- reverse list using member function 'reverse'
+    let b = a @reverse (). -- reverse list using member function 'reverse'
     io @println b.
-
-The ``@`` operator allows you to access either individual elements, slices, or member functions of a list.
-Actually, the ``@`` operator is more general than that, it is Asteroid's substructure access operator.
+The ``@`` operator is Asteroid's general access operator.
+It allows you to access either individual elements, slices, or member functions of a list.
+It also allows for access to members and functions of tuples and objects.
 Notice that in order to access the ``println`` function of the ``io`` module we also use the ``@`` operator.
-This is because in Asteroid, **system modules are objects**, so you must use the ``@`` to access the functions
+This is because in Asteroid, system modules are objects, so you must use ``@`` to access the functions
 of the module.
 
-For a comprehensive treatment of available member functions for Asteroid lists please see the reference guide.
+For a comprehensive treatment of available member functions for lists and tuples please see the reference guide.  We look at objects later on in this guide.
 
-Besides using the default constructor for lists which consists of the
-square brackets enclosing a list of elements we can use **list comprehensions** to construct lists.  In Asteroid a list comprehension consist of a range specifier together with
-a step specifier allowing you to generate integer values within that range,
+Besides using the constructor for lists which consists of the
+square brackets enclosing comma separated elements we can use list comprehensions to construct lists.  In Asteroid a list comprehension consist of a range specifier together with
+an optional step specifier allowing you to generate integer values within that range,
 ::
     load system io.
 
@@ -186,9 +190,8 @@ a step specifier allowing you to generate integer values within that range,
 
     -- reverse the list using a slice computed as comprehension
     let slice = [4 to 0 step -1]. -- list comprehension
-    let b = a @slice.
+    let b = a@slice.
     io @println ("reversed list: " + b).
-
 The output is,
 ::
 
@@ -202,46 +205,26 @@ a list of alternating 1 and -1,
     load system io.
     load system math.
 
-    let a = [1 to 10] @map(lambda with x do return math @mod(x,2))
-                      @map(lambda with x do return 1 if x else -1).
+    let a = [1 to 10] @map (lambda with x do math @mod (x,2))
+                      @map (lambda with x do 1 if x else -1).
 
     io @println a.
-
 where the output is,
 ::
 
     [1,-1,1,-1,1,-1,1,-1,1,-1]
 
-Higher dimensional arrays can easily be simulated with lists of lists,
-::
-    load system io.
-
-    -- build a 2-D array
-    let b = [[1,2,3],
-             [4,5,6],
-             [7,8,9]].
-
-    -- modify an element in the array
-    let b @1 @1 = 0.
-    io @println ("["+b@0+"\n "+b@1+"\n "+b@2+"]").
-
-The output is,
-::
-    [[1,2,3]
-     [4,0,6]
-     [7,8,9]]
 
 
 Tuples
 ^^^^^^
 
-As we saw earlier, the ``tuple`` is another fundamental, built-in data structure that can be found in Asteroid.
+As we saw earlier, the tuple is another fundamental, built-in data structure that can be found in Asteroid.
 Below is an example of a tuple declaration and access.
 ::
     let a = (1,2,3).    -- construct tuple a
-    let b = a @1.       -- access the second element in tuple a
-    assert(b == 2).     -- assert that the value of the second element is correct
-
+    let b = a@1.        -- access the second element in tuple a, tuples are 0-indexed
+    assert (b == 2).    -- assert that the value of the second element is correct
 Lists and tuples may be nested,
 ::
     -- build a list of tuples
@@ -249,20 +232,18 @@ Lists and tuples may be nested,
              ("d","e","f"),
              ("g","h","i")].
     -- Access an element in the nested structure.
-    assert(b @1 @1 == "e").
-
-Unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared.  The following code block demonstrates this,
+    assert (b@0@1 == "b").
+As we have mentioned earlier, unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared.  The following program demonstrates this,
 ::
     load system io.
 
     let b = ("a","b","c"). -- build a tuple
-    
+
     try
-        let b @1 = "z". -- attempt to modify an element in the tuple
-    catch Exception(kind,message) do
+        let b@1 = "z". -- attempt to modify an element in the tuple
+    catch Exception (kind,message) do
         io @println (kind+": "+message).
     end.
-
 Which will print out the following message:
 ::
 
@@ -274,7 +255,7 @@ Tuples tend to be preferred over lists when representing some sort of structure,
 like abstract syntax trees, where that structure is immutable meaning, for example,
 that the arity of a tree node cannot change.
 
-Custom Data Structures
+Structures and Objects
 ^^^^^^^^^^^^^^^^^^^^^^
 
 You can introduce custom data structures using the ``structure`` keyword.  For example,
@@ -285,10 +266,11 @@ the following statement introduces a structure of type ``A`` with data members `
        data b.
     end
 
-These custom data structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.   Asteroid creates
-a *default constructor* that instantiates an object from a given structure.  A default constructor copies the arguments given to it into the
-data member fields in the order that the data members appear in the
-structure definition and as they appear in the parameter list of the constructor.
+Structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.
+
+For each structure Asteroid creates
+a default constructor that instantiates an object from that structure.  The default constructor copies the arguments given to it into the
+data member fields in the order that the arguments and data members appear in the program text.
 Also, the data fields of an object are accessed via
 their names rather than index values.  Here is a simple example that illustrates
 all this,
@@ -299,10 +281,9 @@ all this,
         data b.
     end
 
-    let obj = A(1,2).       -- call constructor
-    assert( obj @a == 1 ).  -- access first data member
-    assert( obj @b == 2 ).  -- access second data member
-
+    let obj = A(1,2).     -- default constructor, a<-1, b<-2
+    assert (obj@a == 1).  -- access first data member
+    assert (obj@b == 2).  -- access second data member
 The following is a more involved example,
 ::
     load system io.
@@ -315,19 +296,18 @@ The following is a more involved example,
 
     -- make a list of persons
     let people = [
-        -- use default constructors to construct Person instances
+        -- use default constructors to construct Person objects
         Person("George", 32, "man"),
         Person("Sophie", 46, "woman"),
         Person("Oliver", 21, "man")
     ].
 
     -- retrieve the second person on the list and use pattern
-    -- matching to extract member values
-    let Person(name,age,gender) = people @1.
+    -- matching on Person objects to extract member values
+    let Person(name,age,gender) = people@1.
 
     -- print out the member values
     io @println (name + " is " + age + " years old and is a " +  gender + ".").
-
 The output is,
 ::
 
@@ -340,65 +320,103 @@ information from a ``Person`` object.
 In addition to the default constructor, structures in Asteroid also support user specified
 constructors and member functions.  We'll talk about those later when we talk about OO programming in Asteroid.
 
-The ``let`` Statement
----------------------
+The Let Statement
+-----------------
+
+The ``let`` statement is a pattern matching statement of the form,
+::
+    let <pattern> = <value>.
+
+where the pattern on the left side of the equal sign is matched against the value of the right side of the equal sign.  When the pattern consist of just a single variable then the let statement can be viewed as Asteroid's version of the assignment statement, e.g.,
+::
+    let x = 1.
 
-The ``let`` statement is a pattern matching statement and can be viewed as Asteroid's version of the assignment statement even though statements like,
+However, statements like,
 ::
 
     let 1 = 1.
 
-where we take the term on the right side and match it to the pattern on the left side of
-the ``=`` operator are completely legal and highlight the fact that ``let`` statement is not equivalent to an assignment statement.  Simple patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, and user defined structures.
-Here is an example where we do some computations on the right side of a ``let`` statement and then match the result against a pattern on the left,
+where we pattern match the pattern 1 on the left side to the value 1 on the right side are completely legal and highlight the fact that the let statement is not equivalent to an assignment statement.
+
+Simple patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, as well as user defined structures.
+The advantage of pattern matching is that it provides direct access to substructures of a particular value.
+Consider that we want to access the constituent values of the pair ``(1,2)``.  In a non-pattern-matching approach we would have to access each of these constituent values one-by-one,
 ::
-    load system io.
+    let p = (1,2).
+    let x = p@0.
+    let y = p@1.
+    assert (x==1 and y==2).
+
+But in a pattern-matching approach we can write a ``let`` statement with a pattern that looks like a pair with
+the variables ``x`` and ``y`` where we expect our values to be,
+::
+    let p = (1,2).
+    let (x,y) = p.
+    assert (x==1 and y==2).
+
+Matching the pattern against the value ``(1,2)`` stored in ``p`` first matches the pair structure against the pair value and the matches the variables to the appropriate substructures.  Once the variables have been matched to value the ``let`` statement declares the variables in the current scope and they become available for computation.
+
+The following is an example involving structures and objects,
+::
+    structure Person with
+        data name.
+        data age.
+        data profession.
+    end
 
-    let [x,2,y] = [1+0,1+1,1+2].
-    io @println (x,y).
+    let joe = Person("Joe", 32, "Cook").  -- construct an object
+    let Person(n,a,p) = joe.              -- pattern match object
 
-The output is: ``(1,3)``
+    assert (n=="Joe" and a==32 and p=="Cook").
+We first construct an object ``joe`` with the first ``let`` statement and the use pattern matching to desctructure it with the second ``let`` statement binding its substructures to the variables ``n``, ``a``, and ``p``.
 
-Asteroid supports special patterns called **type patterns** that match any value
+Asteroid supports special patterns called type patterns that match any value
 of a given type.  For instance, the ``%integer`` pattern matches any integer value.  Here is a simple example,
 ::
     let %integer = 1.
-
-This ``let`` statement succeeds because ``1`` is an integer value can be pattern-matched against
+This let statement succeeds because ``1`` is an integer value can be pattern-matched against
 the type pattern ``%integer``.
 
 Asteroid also
-supports something called a **named pattern** were a (sub)pattern on the left side
-of a ``let`` statement (or any pattern as it appears in Asteroid) can be given a name
+supports something called a named pattern were a (sub)pattern can be given a name
 and that name will be instantiated with a term during pattern matching.  For example,
 ::
     load system io.
 
-    let t:(1,2) = (1,2).  -- using a named pattern on lhs
+    let t:(x,y) = (1,2).  -- using a named pattern on lhs
     io @println t.
-
-Here, the construct ``t:(1,2)`` is called a named pattern and the variable ``t`` will be unified with the term ``(1,2)``, or more generally, the variable will be unified with term
+Here, the construct ``t:(x,y)`` is called a named pattern and the variable ``t`` will be unified with the term ``(1,2)``, or more generally, the variable will be unified with term
 that matches the pattern on the right of the colon.  The program will print,
 ::
-
     (1,2)
 
+Named patterns are a shorthand notation for conditional patterns; in this case,
+::
+    let t if t is (x,y) = (1,2).
+
 We can combine type patterns and named patterns to give us something that looks
 like a variable declaration in other languages. In Asteroid, though, it is still just all
 about pattern matching.  Consider,
 ::
     load system io.
     load system math.
-    load system type.
 
     let x:%real = math @pi.
-    io @println (type @tostring (x,type @stringformat (4,2))).
-
+    io @println x.
 The left side of the ``let`` statement is a named type pattern that matches any real value, and
 if that match is successful then the value is bound to the variable ``x``.  Note
 that even though this looks like a declaration, it is in fact a pattern matching
-operation.  The program will print the value ``3.14`` according to the format of
-4 characters with 2 characters after the decimal point.
+operation.  The program will print the value ``3.141592653589793``.
+
+Beware of the fact that even though the ``let`` statement above looks like a
+declaration of a real variable it is not; it is a pattern match statement enforcing that the
+value assigned to ``x`` matches the pattern ``%real``.  Since this is a pattern match statement, this
+also means that standard type promotions such as promoting integers to reals during assignments in other
+programming languages do not apply here.  For example, in Asteroid the following let statement fails,
+::
+    let x:%real = 1.
+
+because ``1`` is an integer value and does not match the pattern ``%real``.
 
 Flow of Control
 ---------------
@@ -412,7 +430,6 @@ As we said, in terms of flow of control statements there are really not a lot of
     for i in 0 to 10 step 2 do
         io @println i.
     end
-
 The output is,
 ::
 
@@ -428,10 +445,12 @@ Here is another example that iterates over lists,
     load system io.
     load system util
 
-    for (ix,bird) in util @zip (["first","second","third"],["turkey","duck","chicken"]) do
+    let indexes = ["first","second","third"].
+    let birds = ["turkey","duck","chicken"].
+
+    for (ix,bird) in util @zip (indexes,birds) do
         io @println ("the "+ix+" bird is a "+bird).
     end
-
 The output is,
 ::
 
@@ -439,7 +458,7 @@ The output is,
     the second bird is a duck
     the third bird is a chicken
 
-Here we first create a list of pairs using the ``zip`` function, over which we then
+In the loop we first create a list of pairs using the ``zip`` function, over which we then
 iterate pattern matching on each of the pairs on the list with the pattern ``(ix,bird)``.
 
 The following is a short program that demonstrates an ``if`` statement,
@@ -459,39 +478,34 @@ The following is a short program that demonstrates an ``if`` statement,
     else do
         io @println "Something else".
     end
-
 Even though Asteroid's flow of control statements look so familiar, they support pattern matching to a degree not found in other programming languages and which we will take a look at below.
 
 Functions
 ---------
 
 Functions in Asteroid resemble function definitions in functional programming languages such as Haskell and ML.
-Here functions have a single formal argument and function calls are expressed via juxtaposition
-of the function name and the actual argument.  Here is a simple example,
+Here functions definitions have a single formal argument and function calls are expressed via juxtaposition
+of the function name and the single actual argument.  Here is a simple example,
 ::
-    function double
-        with i do -- pattern match the actual arg with i
-            return 2*i.
-        end
-
-    let d = double 2.  -- function call via juxtaposition
-    assert( d == 4 ).
+    function double with i do -- pattern match the actual arg with i
+        return 2*i.
+    end
 
-In the ``with`` statement we pattern match the actual argument that is
+    let d = double 2.  -- function call via juxtaposition, no parentheses necessary
+    assert (d == 4).
+In the ``with`` expression we pattern match the actual argument that is
 being passed in against the variable ``i``.  Also note that the function call is expressed via juxtaposition,
 no parentheses necessary.
 
 If we wanted to pass more than a single value to a function we have to create
 a tuple and then pass that tuple to the function like in this example,
 ::
-    function reduce
-        with (a,b) do -- pattern match the actual argument
-            return a*b.
-        end
+    function reduce with (a,b) do -- pattern match the actual argument
+        return a*b.
+    end
 
     let r = reduce (2,4).  -- function call via juxtaposition
-    assert( r == 8 ).
-
+    assert (r == 8).
 Even though the function call looks like a traditional function call like in
 Python it is not.  The underlying mechanism is quite different: on the call site
 we construct a tuple that holds all our values which is then passed to the function as the only parameter.
@@ -500,7 +514,7 @@ instantiated during this pattern match can be used within the function body.
 
 In Asteroid functions are multi-dispatch, that is,
 a single function can have multiple bodies each attached to a different pattern
-matching the formal argument.
+matching the actual argument.
 The following is the quick sort implemented in
 Asteroid where each ``with`` clause introduces a new function body with its
 corresponding pattern,
@@ -518,9 +532,9 @@ corresponding pattern,
 
             for e in rest do
                 if e < pivot do
-                    let less = less + [e].
+                    less @append e.
                 else
-                    let more = more + [e].
+                    more @append e.
                 end
             end
 
@@ -529,7 +543,6 @@ corresponding pattern,
 
     -- print the sorted list
     io @println (qsort [3,2,1,0])
-
 The output is as expected,
 ::
 
@@ -548,22 +561,22 @@ name.  Here is an example using a ``lambda`` function,
 ::
     load system io.
 
-    io @println ((lambda with n do return n+1) 1).
-
-The output is ``2``.  Here, the lambda function is a function that takes a value
+    io @println ((lambda with n do n+1) 1).
+The output is ``2``.  Here, the ``lambda`` function is a function that takes a value
 and increments it by one.  We then apply the value ``1`` to the function and the
 print function prints out the value ``2``.
 
 Pattern Matching
 ----------------
 
-Pattern matching lies at the heart of Asteroid.  We saw some of Asteroid's pattern matching ability when we discussed the ``let`` statement.  We can also have pattern matching
-in expressions using the ``is`` predicate.
+Pattern matching lies at the heart of Asteroid.  We saw some of Asteroid's pattern matching ability when we discussed the ``let`` statement.  Here is a more general discussion of pattern matching.
 
-Pattern Matching in Expressions: The ``is`` Predicate
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Pattern Matching in Expressions: The Is Predicate
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Consider the following example of this predicate among some patterns,
+We can also have pattern matching
+in expressions using the ``is`` predicate.
+Consider the following example,
 ::
     load system io.
 
@@ -576,7 +589,6 @@ Consider the following example of this predicate among some patterns,
     else do
         io @println "it's something else".
     end
-
 Here we use patterns to determine if ``p`` is a triple, a pair, or something else. Pattern matching is embedded in the expressions of the ``if`` statement using the ``is`` predicate. The
 output of this program is,
 ::
@@ -584,7 +596,7 @@ output of this program is,
     it's a pair with: 1,2
 
 Pattern matching with the ``is`` predicate can happen anywhere expressions can
-be used.  That means we can use the predicate also in ``let`` statements,
+be used.  That means we can use the predicate also on the right side of ``let`` statements,
 ::
 
     let true = (1,2) is (1,2).
@@ -593,7 +605,7 @@ This is kind of strange looking but it succeeds.  Here the
 left operand of the ``is`` predicate is a term and
 the right operand is a pattern.  Obviously this pattern match will succeed because the
 term and the pattern look identical.  The return value of the ``is`` predicate is then
-pattern matched against the ``true`` value on the left of the ``=`` symbol.
+pattern matched against the ``true`` pattern on the left of the ``=`` symbol.
 
 We can also employ pattern matching in loops.
 In the following program we use the ``is`` predicate to test whether a list is empty or not
@@ -608,7 +620,6 @@ while looping,
         io @println head.
         let list = tail.
     until list is []. -- pattern match with is predicate
-
 The output is,
 ::
 
@@ -616,53 +627,39 @@ The output is,
     2
     3
 
-In addition, the example employs pattern matching using the head-tail operator  in order to iterate over the list elements and print print them.  The
+The example employs pattern matching using the head-tail operator in order to iterate over the list elements and print them.  The
 termination condition of the loop is computed with the ``is`` predicate.
 
 Pattern Matching in Function Arguments
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 As we have seen earlier, Asteroid supports pattern matching on function arguments in the style of ML and many other functional programming languages.
-Here is an example that uses pattern matching on function arguments using custom data structures.  The program below implements `Peano addition <https://en.wikipedia.org/wiki/Peano_axioms#Addition>`_ on terms using the two Peano axioms,
-::
-
-    x + 0 = x
-    x + s(y) = s(x+y)
-
-Here ``x`` and ``y`` are variables, ``0`` represents the natural number with value zero, and ``s`` is the successor function.  In Peano arithmetic any natural number can be represented by the appropriate number of applications of the successor function to the natural number ``0``. Here is the program that implements
-the Peano arithmetic based on the two axiom where we replaced the ``+`` operator with the
-``add`` symbol,
+Here is an example that uses pattern matching on function arguments using binary tree data structures,
 ::
-    -- implements Peano addition on terms
-    load system io.
-
-    structure s with
-        data val.
-        end
-
-    structure add with
-        data left.
-        data right.
-        end
-
-    function reduce
-        with add(x,0) do
-            return reduce(x).
-        with add(x,s(y))  do
-            return s(reduce(add(x,y))).
-        with term do
-            return term.
-        end
-
-    -- add 2 3
-    io @println (reduce(add(s(s(0)),s(s(s(0)))))).
+    structure Node with -- internal tree node with a value
+        data value.
+        data left_child.
+        data right_child.
+    end
 
-Our program defines the structure ``s`` to represent the successor function and the structure ``add`` to represent Peano addition. Next, it defines a function that uses pattern matching to identify the left sides of the two axioms.  If either pattern matches the input to the ``reduce`` function, it will activate the corresponding function body and rewrite the term recursively in an appropriate manner.  We have one additional pattern which matches if neither one of the Peano axiom patterns matches and terminates the recursion.  Finally,  on the last line, we use our ``reduce`` function to compute the Peano term for the addition of 2 + 3. As expected, the output of this program is,
-::
+    structure Leaf with -- leaf node with a value
+        data value.
+    end
 
-    s(s(s(s(s(0)))))
+    -- traverse a tree and collect all the values in the tree in a list
+    function traverse
+        with Leaf(v) do
+            return [v].
+        with Node(v,l,r) do
+            return [v] + traverse l + traverse r.
+    end
 
-which represents the value 5.
+    let tree = Node(1,Leaf(2),Leaf(3)).
+    assert (traverse(tree) == [1,2,3]).
+The structures ``Node`` and ``Leaf`` allow us to construct binary trees with embedded values.
+The ``traverse`` function traverses such trees and collects the values embedded in a tree on a list
+and returns that list.  Notice the pattern matching on the tree node constructs in the ``with`` clauses
+of the ``traverse`` funtion.
 
 Conditional Pattern Matching
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -678,21 +675,37 @@ the kind of values that are being passed to a particular function body,
     function factorial
         with 0 do
             return 1
-        with (n:%integer) if n > 0 do
+        with n if (n is %integer) and (n > 0) do
             return n * factorial (n-1).
-        with (n:%integer) if n < 0 do
+        with n if (n is %integer) and (n < 0) do
             throw Error("factorial is not defined for "+n).
-        end
+    end
 
     io @println ("The factorial of 3 is: " + factorial 3).
-
 Here we see that first, we make sure that we are being passed integers and second,
 that the integers are positive using the appropriate conditions on the input values. If
 we are being passed a negative integer, then we throw an error.
 
+The above factorial program can be simplified by rewriting the first condition on ``n`` in the conditional patterns as a named pattern.
+We can also take advantage of the fact that the last expression evaluated in a function body provides an implicit return value.
+This gives us,
+::
+    load system io.
+
+    function factorial
+        with 0 do
+            1
+        with (n:%integer) if n > 0 do
+            n * factorial (n-1).
+        with (n:%integer) if n < 0 do
+            throw Error("factorial is not defined for "+n).
+    end
+
+    io @println ("The factorial of 3 is: " + factorial 3).
+The parentheses as they appear in the conditional pattern expressions are necessary.
 
-Pattern Matching in ``for`` Loops
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Pattern Matching in For Loops
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 We have seen pattern matching in ``for`` loops earlier.  Here we show another
 example. This combines structural matching with regular expression matching
@@ -704,24 +717,23 @@ that selects certain items from a list. Suppose we want to print out the names o
     structure Person with
         data name.
         data age.
-        end
+    end
 
     -- define a list of persons
     let people = [
         Person("George", 32),
         Person("Sophie", 46),
         Person("Oliver", 21)
-        ].
+    ].
 
     -- print names that contain 'p'
-    for Person(name:".*p.*",_) in people do
+    for Person(name if name is ".*p.*",age) in people do
         io @println name.
     end
+Here we pattern match the ``Person`` object in the ``for`` loop and then use a regular expression to see if the name of that person matches our requirement that it contains a lower case 'p'.  The output is ``Sophie``.
 
-Here we pattern match the ``Person`` object in the ``for`` loop and then use a regular expression to see if the name of that person matches our requirement that it contains a lower case 'p'.  We can tag the pattern with a variable name, a named pattern, so that we can print out the name if the regular expression matches. The output is ``Sophie``.
-
-Pattern Matching in ``try-catch`` Statements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Pattern Matching in Try-Catch Statements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Exception handling in Asteroid is very similar to exception handling in many of the other modern programming languages available today.  The example below shows an Asteroid program  that throws one of two exceptions depending on the randomly generated value ``i``,
 ::
@@ -731,33 +743,32 @@ Exception handling in Asteroid is very similar to exception handling in many of
 
     structure Head with
         data val.
-        end
+    end
 
     structure Tail with
         data val.
-        end
+    end
 
     try
-        let i = random @random().
+        let i = random @random ().
         if i >= 0.5 do
-            throw Head(i).
+            throw Head i.
         else do
-            throw Tail(i).
+            throw Tail i.
         end
-    catch Head(v) do
-        io @println("you win with "+type @tostring(v,type @stringformat(4,2))).
-    catch Tail(v) do
-        io @println("you loose with "+type @tostring(v,type @stringformat(4,2))).
+    catch Head v do
+        io @println ("you win with "+type @tostring (v,type @stringformat (4,2))).
+    catch Tail v do
+        io @println ("you loose with "+type @tostring (v,type @stringformat (4,2))).
     end
-
 The ``Head`` and ``Tail`` exceptions are handled by their corresponding ``catch`` statements, respectively.  In both cases the exception object is unpacked using pattern matching and the unpacked value is used in the appropriate message printed to the screen.
 
 It is worth noting that even though Asteroid has builtin exception objects such as ``Error``,
 you can construct any kind of object and throw it as part of an exception.
 
 
-Structures, Object-Based Programming, and Pattern Matching
-----------------------------------------------------------
+Structures, Object-Oriented Programming, and Pattern Matching
+-------------------------------------------------------------
 
 We saw structures such as,
 ::
@@ -765,66 +776,59 @@ We saw structures such as,
     structure Person with
         data name.
         data age.
-        data gender.
-        end
+    end
 
 earlier.  It is Asteroid's way to create custom data structures. These structures
 introduce a new type name into a program. For instance, in the case above, the ``structure``
 statement introduces the type name ``Person``.   Given a structure definition, we can
-create **instances** of that structure.  For example,
+create objects from that structure.  For example,
 ::
 
-    let scarlett = Person("Scarlett",28,"F").
+    let scarlett = Person("Scarlett",28).
 
 The right side of the ``let`` statement invokes the default constructor for the
-structure in order to create an instance stored in the variable ``scarlett``. We
-can access members of the instance,
+structure in order to create an object stored in the variable ``scarlett``. We
+can access members of the object,
 ::
     load system io.
 
     structure Person with
         data name.
         data age.
-        data gender.
-        end
+    end
 
-    let scarlett = Person("Scarlett",28,"F").
+    let scarlett = Person("Scarlett",28).
     -- access the name field of the structure instance
-    io @println (scarlett @name).
-
+    io @println (scarlett@name).
 Asteroid allows you to attach functions to structures.  In member functions
-the object identity of the instance is available through the ``this`` keyword.
+the object identity is available through the ``this`` keyword.
 For example, we can
 extend our ``Person`` structure with the ``hello`` function that uses the ``name`` field
-of the instance,
+of the object,
 ::
     load system io.
 
     structure Person with
         data name.
         data age.
-        data gender.
-        function hello
-            with none do
-                io @println ("Hello, my name is "+this @name).
-            end
+        function hello with none do
+            io @println ("Hello, my name is "+this@name).
         end
+    end
 
-    let scarlett = Person("Scarlett",28,"F").
+    let scarlett = Person("Scarlett",28).
     -- call the member function
-    scarlett @hello().
-
+    scarlett @hello ().
 This program will print out,
 ::
-
     Hello, my name is Scarlett
 
-The expression ``this @name`` accesses the ``name`` field of the instance the
+The expression ``this@name`` accesses the ``name`` field of the object the
 function ``hello`` was called on.
 Even though our structures are starting to look a bit more like object definitions,
 pattern matching continues to work in the same way from when we discussed structures.
-The only thing you need to keep in mind is that you **cannot** pattern match on a
-function field.  From a pattern matching perspective, a structure consists only of
+The only thing you need to keep in mind is that you cannot pattern match on a
+function member field.  From a pattern matching perspective, a structure consists only of
 data fields.  So even if we declare a structure like this,
 ::
     load system io.
@@ -832,91 +836,74 @@ data fields.  So even if we declare a structure like this,
     structure Person with
         data name.
         -- the function is defined in the middle of the data fields
-        function hello
-            with none do
-                io @println ("Hello, my name is "+this @name).
-            end
-        data age.
-        data gender.
+        function hello with none do
+            io @println ("Hello, my name is "+this@name).
         end
+        data age.
+    end
 
     -- pattern matching ignores function definitions
-    let Person(name,age,_) = Person("Scarlett",28,"F").
+    let Person(name,age) = Person("Scarlett",28).
     io @println (name+" is "+age+" years old").
-
 where the function ``hello`` is defined in the middle of the data fields,
 pattern matching simply ignores the function definition and pattern matches
 only on the data fields.  The output of the program is,
 ::
-
     Scarlett is 28 years old
 
-Here is a slightly more involved example based on the
+Here is a slightly more involved example loosely based on the
 dog example from the `Python documentation <https://docs.python.org/3/tutorial/classes.html>`_.
 The idea of the dog example is to have a structure that describes dogs by their
-names and the tricks that they can perform.  Tricks can be added to a particular
-dog instance by calling the ``add_trick`` function.  Rather than using the default
-constructor, we define a constructor for our instances with the ``__init__`` function.
+names and the tricks that they can perform.   Rather than using the default
+constructor, we define a constructor for our instances with the ``__init__`` function
+that performs some basic type checking on its arguments using type patterns and then
+initializes the data members of the object.
 Here is the program listing for the example in Asteroid,
 ::
-    load system io.
-    load system type.
-
-    structure Dog with
-
-       data name.
-       data tricks.
-
-       function add_trick
-          with new_trick:%string do
-             this @tricks @append new_trick.
-          end
-
-       function __init__
-          with name:%string do
-             let this @name = name.
-             let this @tricks = [].
-          end
-
-    end
-
-    let fido = Dog "Fido".
-    fido @add_trick "play dead".
-    fido @add_trick "fetch".
+   load system io.
+   load system type.
+
+   structure Dog with
+      data name.
+      data tricks.
+      function __init__ with (name:%string, tricks:%list) do -- constructor
+         let this@name = name.
+         let this@tricks = tricks.
+      end
+   end
 
-    let buddy = Dog "Buddy".
-    buddy @add_trick "sit stay".
-    buddy @add_trick "roll over".
+   let fido = Dog("Fido",["play dead","fetch"]).
+   let buddy = Dog("Buddy",["sit stay","roll over"]).
+   let bella = Dog("Bella",["roll over","fetch"]).
 
-    -- print out all the dogs that know how to fetch
-    for (Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*") in [fido,buddy] do
-        io @println (name+" knows how to fetch").
-    end
+   let dogs = [fido,buddy,bella].
 
-After declaring the structure we instantiate two dogs, Fido and Buddy, and add
-tricks to their respective trick repertoires.  The last couple of lines
+   -- print out all the dogs that know how to fetch
+   for (Dog(name,tricks) if type @tostring tricks is ".*fetch.*") in dogs do
+      io @println (name+" knows how to fetch").
+   end
+After declaring the structure we instantiate the dogs with their
+respective trick repertoires and put them on a list.  The last couple of lines
 of the program consist of a ``for`` loop over a list of our dogs.
 The ``for`` loop is interesting
 because here we use structural, conditional, and regular expression pattern
 matching in order to only select the dogs that know how to do ``fetch`` from
 the list of dogs.  The pattern is,
 ::
-
-    Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*"
+    Dog(name,tricks) if type @tostring tricks is ".*fetch.*"
 
 The structural part of the pattern is ``Dog(name,tricks)`` which simply matches
 any dog instance on the list.  However, that match is only successful if
 the conditional part of the pattern holds,
 ::
-
-    if type @tostring(tricks) is ".*fetch.*"
+    if type @tostring tricks is ".*fetch.*"
 
 This condition only succeeds if the ``tricks`` list viewed as a string matches
 the regular expression ``".*fetch.*"``. That is, if the list contains the word ``fetch``.
 The output is,
 ::
-
     Fido knows how to fetch
+    Bella knows how to fetch
 
 
 Patterns as First-Class Citizens
@@ -933,16 +920,16 @@ doesn't change what we can and cannot compute with the language. But it does cha
 we can express what we want to compute.  That is, it changes the expressiveness
 of a programming language.
 
-In Asteroid first-class patterns are introduced with the keywords ``pattern with``
+In Asteroid first-class patterns are introduced with the keyword ``pattern``
 and patterns themselves are values that we can store in variables and then reference
 when we want to use them.  Like so,
 ::
 
-    let P = pattern (x,y).
-    let *P = (1,2).
+    let p = pattern (x,y).  -- define a first-class pattern
+    let *p = (1,2).         -- use the first-class pattern
 
-The left side of the second ``let`` statement dereferences the pattern stored in variable ``P``
-and uses the pattern to match against the term ``(1,2)``.
+The left side of the second ``let`` statement dereferences the pattern stored in variable ``p``
+and uses the pattern to match against the value ``(1,2)``.
 
 Here we look at three examples of how first-class patterns can add to a developer's
 programming toolbox.
@@ -954,31 +941,27 @@ Patterns can become very complicated especially when conditional pattern matchin
 is involved.  First-class patterns allow us to control the complexity of patterns
 by breaking patterns up into smaller subpatterns that are more easily managed. Consider
 the following function that takes a pair of values.  The twist is that
-the first component of the pair is restricted to the primitive data types of
+the first component of the pair is restricted to primitive data types of
 Asteroid,
 ::
 
-    function foo
-        with (x if (x is %boolean) or (x is %integer) or (x is %string),y) do
-            io @println (x,y).
-        end
+    function foo with (x if (x is %boolean) or (x is %integer) or (x is %string),y) do
+        io @println (x,y).
+    end
 
-That complicated pattern for the first component completely obliterates the
+That complicated pattern for the first component of the input pair completely obliterates the
 overall structure of the parameter pattern and makes the function definition
 difficult to read.
 
 We can express the same function with a first-class pattern,
 ::
+    let TP = pattern q if (q is %boolean) or
+                          (q is %integer) or
+                          (q is %string).
 
-    let TP = pattern
-        with q if (q is %boolean) or
-                  (q is %integer) or
-                  (q is %string).
-
-    function foo
-        with (x:*TP,y) do
-            io @println (x,y).
-        end
+    function foo with (x:*TP,y) do
+        io @println (x,y).
+    end
 
 It is clear now that the main input structure to the function is a pair and the
 conditional type restriction pattern has been relegated to a subpattern stored in the variable
@@ -999,7 +982,7 @@ spots where the patterns occurs. Consider the following program snippet,
             return n * fact (n-1).
         with (n:%integer) if n < 0 do
             throw Error("fact undefined for negative values").
-        end
+    end
 
     function sign
         with 0 do
@@ -1008,8 +991,7 @@ spots where the patterns occurs. Consider the following program snippet,
             return 1.
         with (n:%integer) if n < 0 do
             return -1.
-        end
-
+    end
 In order to write these two functions we had to repeat the almost identical pattern
 four times.  First-class patterns allow us to write the same two functions in a
 much more elegant way,
@@ -1024,22 +1006,21 @@ much more elegant way,
             return n * fact (n-1).
         with *NEG_INT do
             throw Error("fact undefined for negative values").
-        end
+    end
 
     function sign
         with 0 do
-                return 1
-            with *POS_INT do
-                return 1.
-            with *NEG_INT do
-                return -1.
-            end
-
+            return 1
+        with *POS_INT do
+            return 1.
+        with *NEG_INT do
+            return -1.
+    end
 The relevant patterns are now stored in the variables ``POS_INT`` and ``NEG_INT``
 which are then used in the function definitions.
 
 Constraint Patterns
--------------------
+^^^^^^^^^^^^^^^^^^^
 
 Sometimes we want to use patterns as constraints on other patterns.  Consider
 the following (somewhat artificial) example,
@@ -1051,8 +1032,8 @@ Here we want to use the pattern ``v if (v is %integer) and v > 0`` purely as a c
 on the pattern ``x`` in the sense that we want a match on ``x`` only to succeed
 if ``some_value`` is a positive integer.  The problem is that this constraint pattern
 introduces a spurious binding of the variable ``v`` into the current environment
-which might be undesirable due to variable name clashes.  Our notion of constraint pattern
-addresses this.  We can rewrite the above statement as follows,
+which might be undesirable due to variable name clashes.  Constraint patterns
+address this.  We can rewrite the above statement as follows,
 ::
 
    let x: %[v if (v is %integer) and v > 0]% = some_value.
@@ -1073,7 +1054,6 @@ in functions.  Consider the following program,
    end
 
    io @println (add(1,2)).
-
 Without the ``%[...]%`` operators around the pattern ``v if (v is %integer) and v > 0``
 the argument list pattern for the function
 ``(a:*POS_INT,b:*POS_INT)`` would instantiate two instances of the variable ``v``
@@ -1082,82 +1062,172 @@ With the ``%[...]%`` operators in place we prevent
 the pattern ``v if (v is %integer) and v > 0`` from instantiating the variable ``v`` thus preventing a non-linearity
 to occur in the argument list pattern.
 
-
-More on Multi-Dispatch
-----------------------
-
-With the ``qsort`` function above we saw functional programming style dispatch
-where the ``with`` clauses represent a case analysis over a single type, namely
-the input type to the function.
-However, Asteroid has a much broader view of multi-dispatch where the ``with`` clauses
-represent a case analysis over different types.
-In order to demonstrate this type of multi-dispatch, we show the example program from the
-`multi-dispatch Wikipedia page <https://en.wikipedia.org/wiki/Multiple_dispatch>`_
-written in Asteroid,
+Sometimes we need to use constraint patterns instead of straightforward patterns
+in order to avoid non-linearities but
+we also want controlled access to the variables these constraint patterns declare.
+We achieve this by using the ``bind`` keyword at the pattern-match site.
+Consider the following program,
 ::
-    load system io.
-    load system type.
+   -- declare a pattern that matches scalar values
+   let Scalar = pattern %[p if (p is %integer) or (p is %real)]%.
 
-    let pos_num = pattern %[x if type @isscalar(x) and x > 0]%.
-   
-    structure Asteroid with
-       data size.
-       function __init_
-          with v:*pos_num do
-             let this @size = v.
-          end
-    end
+   -- declare a pattern that matches pairs of scalars
+   let Pair = pattern %[(x:*Scalar,y:*Scalar)]%.
 
-    structure Spaceship with
-        data size.
-       function __init_
-          with v:*pos_num do
-             let this @size = v.
-          end
-    end
+   -- compute the dot product of two pairs of scalars
+   function dot2d
+      with (*Pair bind [x as a1, y as a2], *Pair bind [x as b1, y as b2]) do
+         a1*b1 + a2*b2
+   end
 
-    -- we use first-class pattern SpaceObject to
-    -- express that both asteroids and space ships are space objects.
-    let SpaceObject = pattern %[x if (x is %Asteroid) or (x is %Spaceship)]%.
+   assert(dot2d((1,0),(0,1)) == 0).
+In the function definition of ``dot2d`` we see that the ``Pair`` pattern is used
+twice to make sure that the function is called with a pair of pairs as its argument.
+However, in order to compute the dot product of those two pairs we need access
+to the values each pair matched.  We use the ``bind`` keyword together with an
+appropriate binding term list to extract the matched values.  For the first
+pair we map ``x`` and ``y`` to ``a1`` and ``a2`` and for the second
+pair we map ``x`` and ``y`` to ``b1`` and ``b2``, respectively.
 
-    -- multi-dispatch function
-    function collide_with
-      with (a:%Asteroid, b:%Spaceship) do
-        return "a/s".
-      with (a:%Spaceship, b:%Asteroid) do
-        return "s/a".
-      with (a:%Spaceship, b:%Spaceship) do
-        return "s/s".
-      with (a:%Asteroid, b:%Asteroid) do
-        return "a/a".
-      end
+As a quick aside, the ``as`` construction in the binding term list is only necessary
+when trying to resolve non-linearities otherwise the binding term list can just consist
+of the variable names appearing in the pattern that you want to bind into the current
+scope.
 
-    -- here we use the first-class pattern SpaceObject as a
-    -- constraint on the function parameters.
-    function collide with (x:*SpaceObject, y:*SpaceObject) do
-      return "Big boom!" if (x@size > 100 and y@size > 100) else collide_with(x, y).
-    end
 
-    io @println (collide(Asteroid(101), Spaceship(300))).
-    io @println (collide(Asteroid(10), Spaceship(10))).
-    io @println (collide(Spaceship(101), Spaceship(10))).
+Basic Asteroid I/O
+------------------
 
-Each ``with`` clause in the function ``collide_with`` introduces a new function body with its
-corresponding pattern.
-The function bodies in this case are simple ``return`` statements
-but they could be arbitrary computations.  The output of the program is,
+I/O functions are defined as member functions of the ``io`` module. The ``println`` function prints its argument in a readable form to the terminal.  Recall that the ``+`` operator also implements string concatenation.  This allows us to construct nicely formatted output strings,
 ::
+    load system io.
 
-    Big boom!
-    a/s
-    s/s
+    let a = 1.
+    let b = 2.
+    io @println ("a + b = " + (a + b)).
+The output is
+::
+
+    a + b = 3
+
+We can use the ``tostring`` function defined in the ``type`` module to provide some
+additional formatting. The idea is that the ``tostring`` function takes a value to be turned into a string together with an optional ``stringformat`` formatting specifier object,
+::
+
+    type @tostring(value[,type @stringformat(width spec[,precision spec])])
+
+The width specifier tells the ``tostring`` function how many characters to reserve for the string conversion of the value.  If the value requires more characters than given in the width specifier then the width specifier is ignored.  If the width specifier is larger than than the number of characters required for the value then the value will be right justified.  For real values there is an optional precision specifier.
+
+Here is a program that exercises some of the string formatting options,
+::
+    load system io.
+    load system type.
+    load system math.
+
+    -- if the width specifier is larger than the length of the value
+    -- then the value will be right justified
+    let b = type @tostring(true,type @stringformat(10)).
+    io @println b.
+
+    let i = type @tostring(5,type @stringformat(5)).
+    io @println i.
+
+    -- we can format a string by applying tostring to the string
+    let s = type @tostring("hello there!",type @stringformat(30)).
+    io @println s.
+
+    -- for floating point values: first value is width, second value precision.
+    -- if precision is missing then value is left justified and zero padded on right.
+    let r = type @tostring(math @pi,type @stringformat(6,3)).
+    io @println r.
+The output of the program is,
+::
+
+          true
+        5
+                      hello there!
+     3.142
+
+Notice the right justification of the various values within the given string length.
+
+The ``io`` module also defines a function ``print`` which behaves just like ``println``
+except that it does not terminate print with a newline.
+
+Another useful function defined in the ``io`` module is the ``input`` function that, given an optional prompt string, will prompt the user at the terminal and return the input value as a string.  Here is a small example,
+::
+    load system io.
+
+    let name = io @input("What is your name? ").
+    io @println ("Hello " + name + "!").
+The output is,
+::
+
+    What is your name? Leo
+    Hello Leo!
+
+
+We can use the type casting functions such as ``tointeger`` or ``toreal`` defined in the
+``type`` module to convert the string returned from ``input`` into a numeric value,
+::
+    load system io.
+    load system type.
+
+    let i if i > 0  = type @tointeger(io @input("Please enter a positive integer value: ")).
+
+    for k in 1 to i do
+        io @println k.
+    end
+The output is,
+::
+
+    Please enter a positive integer value: 3
+    1
+    2
+    3
+
+
+Finally, the function ``read`` reads from ``stdin`` and returns the input as a string.  The function ``write`` writes a string to ``stdout``.
+
+The Module System
+-----------------
+
+A module in Asteroid is a file with a set of valid Asteroid statements.
+You can load this file into other Asteroid code with the statement::
+
+   load "example_path/example_filename".
+
+or::
+
+   load example_modulename.
+
+The search strategy for a module to be loaded is as follows,
+
+1. raw module name - could be an absolute path
+2. search in current directory
+3. search in directory where Asteroid is installed
+4. search in subdirectory where Asteroid was started
+
+Modules defined by the Asteroid system should be loaded with the keyword ``system``
+in order to avoid any clashes with locally defined modules.  If the ``system``
+keyword is used then Asteroid only searches in its system folders
+rather than in user directories.
+
+Say that you wanted to load the ``math`` module so you could execute a certain trigonometric function. The following Asteroid program loads the ``math`` module as well as the ``io``  module. Only after loading them would you be able to complete the sine function below,
+::
+    load system io.
+    load system math.
 
+    let x = math @sin( math @pi / 2 ).
+    io @println("The sine of pi / 2 is " + x + ".").
+Both the function ``sin`` and the constant value ``pi`` are defined in the ``math`` module.
+In addition, the ``io`` module is where all input/output functions in Asteroid (such as ``println``) come from.
+If you want the complete list of modules, make sure to check out the reference guide `here <https://asteroid-lang.readthedocs.io/en/latest/Reference%20Guide.html>`_.
 
 
 More on Exceptions
 ------------------
 
-This section will give further information on how to work with **exceptions**, or unexpected conditions that break the regular flow of execution.  Exceptions generated by Asteroid are ``Exception`` objects with the following structure,
+This section will give further information on how to work with exceptions, or unexpected conditions that break the regular flow of execution.  Exceptions generated by Asteroid are ``Exception`` objects with the following structure,
 ::
 
     structure Exception with
@@ -1193,7 +1263,6 @@ example,
     catch Exception("ArithmeticError", s) do
         io @println s.
     end
-
 The output is,
 ::
 
@@ -1209,7 +1278,6 @@ Asteroid also provides a predefined ``Error`` object for user level exceptions,
     catch Error(s) do
         io @println s.
     end
-
 Of course the user can also use the ``Exception`` object for their own exceptions
 by defining a ``kind`` that does not interfere with the predefined ``kind`` strings above,
 ::
@@ -1220,7 +1288,6 @@ by defining a ``kind`` that does not interfere with the predefined ``kind`` stri
     catch Exception("MyException",s) do
         io @println s.
     end
-
 The output here is,
 ::
 
@@ -1236,7 +1303,6 @@ the user is allowed to construct user level exceptions with any kind of object i
     catch ("funny exception", v) do
         io @println v.
     end
-
 The output of this program is ``42``.
 
 Now, if you don't care what kind of exception you catch, you need to use a ``wildcard`` or a variable because exception handlers are activated via pattern matching on the
@@ -1249,7 +1315,6 @@ exception object itself.  Here is an example using a ``wildcard``,
     catch _ do
         io @println "something happened".
     end
-
 Here is an example using a variable,
 ::
     load system io.
@@ -1260,7 +1325,6 @@ Here is an example using a variable,
     catch e do
         io @println ("something happened: "+type @tostring(e)).
     end
-
 In this last example we simply convert the caught exception object into a string
 and print it,
 ::
@@ -1269,135 +1333,70 @@ and print it,
     lists/tuples are not the same length)
 
 
-Basic Asteroid I/O
-------------------
-
-I/O functions are defined as member functions of the ``io`` module. The ``println`` function prints its argument in a readable form to the terminal.  Recall that the ``+`` operator also implements string concatenation.  This allows us to construct nicely formatted output strings,
-::
-    load system io.
-
-    let a = 1.
-    let b = 2.
-    io @println ("a + b = " + (a + b)).
-
-The output is
-::
-
-    a + b = 3
-
-We can use the ``tostring`` function defined in the ``type`` module to provide some
-additional formatting. The idea is that the ``tostring`` function takes a value to be turned into a string together with an optional ``stringformat`` formatting specifier object,
-::
-
-    type @tostring(value[,type @stringformat(width spec[,precision spec])])
-
-The width specifier tells the ``tostring`` function how many characters to reserve for the string conversion of the value.  If the value requires more characters than given in the width specifier then the width specifier is ignored.  If the width specifier is larger than than the number of characters required for the value then the value will be right justified.  For real values there is an optional precision specifier.
-
-Here is a program that exercises some of the string formatting options,
-::
-    load system io.
-    load system type.
-    load system math.
-
-    -- if the width specifier is larger than the length of the value
-    -- then the value will be right justified
-    let b = type @tostring(true,type @stringformat(10)).
-    io @println b.
-
-    let i = type @tostring(5,type @stringformat(5)).
-    io @println i.
-
-    -- we can format a string by applying tostring to the string
-    let s = type @tostring("hello there!",type @stringformat(30)).
-    io @println s.
-
-    -- for floating point values: first value is width, second value precision.
-    -- if precision is missing then value is left justified and zero padded on right.
-    let r = type @tostring(math @pi,type @stringformat(6,3)).
-    io @println r.
-
-The output of the program is,
-::
-
-          true
-        5
-                      hello there!
-     3.142
-
-Notice the right justification of the various values within the given string length.
-
-The ``io`` module also defines a function ``print`` which behaves just like ``println``
-except that it does not terminate print with a newline.
-
-Another useful function defined in the ``io`` module is the ``input`` function that, given an optional prompt string, will prompt the user at the terminal and return the input value as a string.  Here is a small example,
-::
-    load system io.
-
-    let name = io @input("What is your name? ").
-    io @println ("Hello " + name + "!").
-
-The output is,
-::
-
-    What is your name? Leo
-    Hello Leo!
-
+More on Multi-Dispatch
+----------------------
 
-We can use the type casting functions such as ``tointeger`` or ``toreal`` defined in the
-``type`` module to convert the string returned from ``input`` into a numeric value,
+With the ``qsort`` function above we saw functional programming style dispatch
+where the ``with`` clauses represent a case analysis over a single type, namely
+the input type to the function.
+However, Asteroid has a much broader view of multi-dispatch where the ``with`` clauses
+can represent a case analysis over different types.
+In order to demonstrate this type of multi-dispatch, we show the example program from the
+`multi-dispatch Wikipedia page <https://en.wikipedia.org/wiki/Multiple_dispatch>`_
+written in Asteroid,
 ::
     load system io.
     load system type.
 
-    let i if i > 0  = type @tointeger(io @input("Please enter a positive integer value: ")).
+    let pos_num = pattern %[x if type @isscalar(x) and x > 0]%.
 
-    for k in 1 to i do
-        io @println k.
+    structure Asteroid with
+       data size.
+       function __init_
+          with v:*pos_num do
+             let this @size = v.
+          end
     end
 
-The output is,
-::
-
-    Please enter a positive integer value: 3
-    1
-    2
-    3
-
-
-Finally, the function ``read`` reads from ``stdin`` and returns the input as a string.  The function ``write`` writes a string to ``stdout``.
-
-The Module System
------------------
-
-A module in Asteroid is a file with a set of valid Asteroid statements.
-You can load this file into other Asteroid code with the statement::
-
-   load "example_path/example_filename".
-
-or::
-
-   load example_modulename.
+    structure Spaceship with
+        data size.
+       function __init_
+          with v:*pos_num do
+             let this @size = v.
+          end
+    end
 
-The search strategy for a module to be loaded is as follows,
+    -- we use first-class pattern SpaceObject to
+    -- express that both asteroids and space ships are space objects.
+    let SpaceObject = pattern %[x if (x is %Asteroid) or (x is %Spaceship)]%.
 
-1. raw module name - could be an absolute path
-2. search in current directory
-3. search in directory where Asteroid is installed
-4. search in subdirectory where Asteroid was started
+    -- multi-dispatch function
+    function collide_with
+      with (a:%Asteroid, b:%Spaceship) do
+        return "a/s".
+      with (a:%Spaceship, b:%Asteroid) do
+        return "s/a".
+      with (a:%Spaceship, b:%Spaceship) do
+        return "s/s".
+      with (a:%Asteroid, b:%Asteroid) do
+        return "a/a".
+      end
 
-Modules defined by the Asteroid system should be loaded with the keyword ``system``
-in order to avoid any clashes with locally defined modules.  If the ``system``
-keyword is used then Asteroid only searches in its system folders
-rather than in user directories.
+    -- here we use the first-class pattern SpaceObject as a
+    -- constraint on the function parameters.
+    function collide with (x:*SpaceObject, y:*SpaceObject) do
+      return "Big boom!" if (x@size > 100 and y@size > 100) else collide_with(x, y).
+    end
 
-Say that you wanted to load the ``math`` module so you could execute a certain trigonometric function. The following Asteroid program loads the ``math`` module as well as the ``io``  module. Only after loading them would you be able to complete the sine function below,
+    io @println (collide(Asteroid(101), Spaceship(300))).
+    io @println (collide(Asteroid(10), Spaceship(10))).
+    io @println (collide(Spaceship(101), Spaceship(10))).
+Each ``with`` clause in the function ``collide_with`` introduces a new function body with its
+corresponding pattern.
+The function bodies in this case are simple ``return`` statements
+but they could be arbitrary computations.  The output of the program is,
 ::
-    load system io.
-    load system math.
 
-    let x = math @sin( math @pi / 2 ).
-    io @println("The sine of pi / 2 is " + x + ".").
-
-Both the function ``sin`` and the constant value ``pi`` are defined in the ``math`` module.
-In addition, the ``io`` module is where all input/output functions in Asteroid (such as ``println``) come from.
-If you want the complete list of modules, make sure to check out the reference guide `here <https://asteroid-lang.readthedocs.io/en/latest/Reference%20Guide.html>`_.
+    Big boom!
+    a/s
+    s/s
diff --git a/docs/User Guide.txt b/docs/User Guide.txt
index 8d3ce99b..f7447f8f 100644
--- a/docs/User Guide.txt
+++ b/docs/User Guide.txt
@@ -1,12 +1,14 @@
-/******************************************************************
-  This is the source file from which the user guide is generated.
-  We use cpp to insert live code snippets into the document.
-  In order to generate the user guide run the following command
-  on a Unix-like system in the directory of this doc:
+..
+    /******************************************************************
+    This is the source file from which the user guide is generated.
+    We use cpp to insert live code snippets into the document.
+    In order to generate the user guide run the following command
+    on a Unix-like system in the directory of this doc:
 
-  bash generate_docs
+    bash generate_docs
+
+    ******************************************************************/
 
- ******************************************************************/
 #include "header.txt"
 
 .. highlight:: none
@@ -17,12 +19,13 @@ Asteroid User Guide
 Introduction
 ------------
 
-Asteroid is a multi-paradigm programming language supporting first-class patterns.
-The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_, and makes pattern matching one of its core computational mechanisms.  We often refer to this as pattern-matching oriented programming. When we talk about pattern matching we mean structural pattern matching
+Asteroid is a modern, application-oriented, multi-paradigm programming language supporting first-class patterns.
+The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_.  Furthermore, Asteroid is 
+dynamically typed and makes pattern matching one of its core computational mechanisms.  When we talk about pattern matching we mean both structural pattern matching
 as well as regular expression matching.
 
 In this document we describe the major features of Asteroid and give plenty of examples.  If you have used a programming language like Python or JavaScript before, then Asteroid should appear very familiar.  However, there are some features which differ drastically from other programming languages due to the core pattern-matching programming
-paradigm.  Here are just two examples:
+paradigm with first-class patterns.  Here are just two examples:
 
 **Example:** All statements that look like assignments are actually pattern-match statements.  For example if we state,
 ::
@@ -55,14 +58,14 @@ with programming in Asteroid.
 The Basics
 ----------
 
-As with most languages we are familiar with, Asteroid has **variables** (alpha-numeric symbols starting with an alpha character) and **constants**.  Constants are available for all the **primitive data types**,
+As with most programming languages we are familiar with, Asteroid has variables (alpha-numeric symbols starting with an alpha character) and constants.  Constants are available for all the primitive data types,
 
 * ``integer``, e.g. ``1024``
 * ``real``, e.g. ``1.75``
 * ``string``, e.g. ``"Hello, World!"``
 * ``boolean``, e.g. ``true``
 
-Asteroid arranges these data types in a **type hierarchy**,
+Asteroid arranges these primitive data types in a type hierarchy,
 
 ``boolean`` < ``integer`` < ``real`` < ``string``
 
@@ -73,12 +76,12 @@ where automatic type promotion is used to put together a string from different d
 
 Here we associate the string ``"value: 1"`` with the variable ``x`` by first promoting the integer value ``1`` to the string ``"1"`` using the fact that ``integer`` < ``string``  according to our type hierarchy  and then interpreting the ``+`` operator as a string concatenation operator.
 
-Asteroid supports two more data types:
+Asteroid also supports the built-in data types:
 
 * ``list``
 * ``tuple``
 
-These are **structured data types** in that they can contain entities that belong to other data types. Both of these data types have constructors which are possibly empty sequences of comma separated values enclosed by square brackets for lists, e.g. ``[1,2,3]``, and enclosed by parentheses for tuples, e.g. ``(x,y)``. For tuples we have the caveat that the 1-tuple is represented by a value followed by a comma to distinguish it from parenthesized expressions, e.g. ``(3,)``.
+These are structured data types in that they can contain entities that belong to other data types. Both of these data types have constructors which are possibly empty sequences of comma separated values enclosed by square brackets for lists, e.g. ``[1,2,3]``, and enclosed by parentheses for tuples, e.g. ``(x,y)``. For tuples we have the caveat that the 1-tuple is represented by a value followed by a comma to distinguish it from parenthesized expressions, e.g. ``(3,)`` the 1-tuple versus ``(3)`` the parenthesized expression.
 Here are some examples,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-005.ast"
@@ -87,7 +90,7 @@ As we said above, in order to distinguish it from a parenthesized value the sing
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-006.ast"
 
-Lists and tuples themselves are also embedded in type hierarchies, although very simple ones:
+Lists are mutable objects whereas tuples are immutable.  Lists and tuples themselves are also embedded in type hierarchies, although very simple ones:
 
 * ``list`` < ``string``
 * ``tuple`` < ``string``
@@ -96,8 +99,9 @@ That is, any list or tuple can be viewed as a string.  This is very convenient f
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-007.ast"
 
+Here the ``+`` operator acts like a string concantenation operator with the list ``[1,2,3]`` promoted to a string according to the above type hierarchy.
 
-Finally, Asteroid supports one more type, namely the ``none`` type.  The ``none`` type has
+Asteroid supports the ``none`` type.  The ``none`` type has
 only one member: A constant named ``none``.  However, it turns out that the null-tuple, a tuple with no components
 indicated by ``()``, also belongs to this type rather than the tuple type discussed earlier. But the ``none``
 data type only has one constant, this implies that ``()`` and ``none`` mean the same thing and can be used
@@ -108,7 +112,15 @@ interchangeably.  That is, the following ``let`` statements will succeed,
 showing that ``()`` and ``none`` are equivalent and pattern-match each other.
 The ``none`` data type itself does not belong to any type hierarchy.
 
-By now you probably figured out that statements are terminated with a period and that comments start with a ``--`` symbol and continue till the end of the line.  You probably also figured out that the ``let`` statement is Asteroid's version of assignment even though the underlying mechanism is a bit different.
+We should mention here that because functions and patterns are both first-class citizens in Asteroid we 
+also have the types ``function`` and ``pattern``,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-008a.ast"
+
+Just like the ``none`` type, neither of these types are 
+part of a type hierarchy but we can use them in type patterns (see below).
+
+By now you probably figured out that statements are terminated with a period and that comments start with a ``--`` symbol and continue till the end of the line.  You probably also figured out that the ``let`` statement is Asteroid's version of assignment even though the underlying mechanism is a bit different as we will see when we discuss pattern matching in more detail.
 
 Data Structures
 ---------------
@@ -132,17 +144,18 @@ objects. We could rewrite the above example as,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-010.ast"
 
-The ``@`` operator allows you to access either individual elements, slices, or member functions of a list.
-Actually, the ``@`` operator is more general than that, it is Asteroid's substructure access operator.
+The ``@`` operator is Asteroid's general access operator.
+It allows you to access either individual elements, slices, or member functions of a list.
+It also allows for access to members and functions of tuples and objects.
 Notice that in order to access the ``println`` function of the ``io`` module we also use the ``@`` operator.
-This is because in Asteroid, **system modules are objects**, so you must use the ``@`` to access the functions
+This is because in Asteroid, system modules are objects, so you must use ``@`` to access the functions
 of the module.
 
-For a comprehensive treatment of available member functions for Asteroid lists please see the reference guide.
+For a comprehensive treatment of available member functions for lists and tuples please see the reference guide.  We look at objects later on in this guide.
 
-Besides using the default constructor for lists which consists of the
-square brackets enclosing a list of elements we can use **list comprehensions** to construct lists.  In Asteroid a list comprehension consist of a range specifier together with
-a step specifier allowing you to generate integer values within that range,
+Besides using the constructor for lists which consists of the
+square brackets enclosing comma separated elements we can use list comprehensions to construct lists.  In Asteroid a list comprehension consist of a range specifier together with
+an optional step specifier allowing you to generate integer values within that range,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-011.ast"
 
@@ -163,21 +176,12 @@ where the output is,
 
     [1,-1,1,-1,1,-1,1,-1,1,-1]
 
-Higher dimensional arrays can easily be simulated with lists of lists,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-013.ast"
-
-The output is,
-::
-    [[1,2,3]
-     [4,0,6]
-     [7,8,9]]
 
 
 Tuples
 ^^^^^^
 
-As we saw earlier, the ``tuple`` is another fundamental, built-in data structure that can be found in Asteroid.
+As we saw earlier, the tuple is another fundamental, built-in data structure that can be found in Asteroid.
 Below is an example of a tuple declaration and access.
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-014.ast"
@@ -186,7 +190,7 @@ Lists and tuples may be nested,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-015.ast"
 
-Unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared.  The following code block demonstrates this,
+As we have mentioned earlier, unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared.  The following program demonstrates this,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-016.ast"
 
@@ -201,7 +205,7 @@ Tuples tend to be preferred over lists when representing some sort of structure,
 like abstract syntax trees, where that structure is immutable meaning, for example,
 that the arity of a tree node cannot change.
 
-Custom Data Structures
+Structures and Objects
 ^^^^^^^^^^^^^^^^^^^^^^
 
 You can introduce custom data structures using the ``structure`` keyword.  For example,
@@ -212,10 +216,11 @@ the following statement introduces a structure of type ``A`` with data members `
        data b.
     end
 
-These custom data structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.   Asteroid creates
-a *default constructor* that instantiates an object from a given structure.  A default constructor copies the arguments given to it into the
-data member fields in the order that the data members appear in the
-structure definition and as they appear in the parameter list of the constructor.
+Structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.   
+
+For each structure Asteroid creates
+a default constructor that instantiates an object from that structure.  The default constructor copies the arguments given to it into the
+data member fields in the order that the arguments and data members appear in the program text.
 Also, the data fields of an object are accessed via
 their names rather than index values.  Here is a simple example that illustrates
 all this,
@@ -238,43 +243,71 @@ information from a ``Person`` object.
 In addition to the default constructor, structures in Asteroid also support user specified
 constructors and member functions.  We'll talk about those later when we talk about OO programming in Asteroid.
 
-The ``let`` Statement
----------------------
+The Let Statement
+-----------------
+
+The ``let`` statement is a pattern matching statement of the form,
+::
+    let <pattern> = <value>.
 
-The ``let`` statement is a pattern matching statement and can be viewed as Asteroid's version of the assignment statement even though statements like,
+where the pattern on the left side of the equal sign is matched against the value of the right side of the equal sign.  When the pattern consist of just a single variable then the let statement can be viewed as Asteroid's version of the assignment statement, e.g.,
+::
+    let x = 1.
+    
+However, statements like,
 ::
 
     let 1 = 1.
 
-where we take the term on the right side and match it to the pattern on the left side of
-the ``=`` operator are completely legal and highlight the fact that ``let`` statement is not equivalent to an assignment statement.  Simple patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, and user defined structures.
-Here is an example where we do some computations on the right side of a ``let`` statement and then match the result against a pattern on the left,
+where we pattern match the pattern 1 on the left side to the value 1 on the right side are completely legal and highlight the fact that the let statement is not equivalent to an assignment statement.  
+
+Simple patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, as well as user defined structures.
+The advantage of pattern matching is that it provides direct access to substructures of a particular value.
+Consider that we want to access the constituent values of the pair ``(1,2)``.  In a non-pattern-matching approach we would have to access each of these constituent values one-by-one,
+::
+    let p = (1,2).
+    let x = p@0.
+    let y = p@1.
+    assert (x==1 and y==2).
+
+But in a pattern-matching approach we can write a ``let`` statement with a pattern that looks like a pair with 
+the variables ``x`` and ``y`` where we expect our values to be,
+::
+    let p = (1,2).
+    let (x,y) = p.
+    assert (x==1 and y==2).
+
+Matching the pattern against the value ``(1,2)`` stored in ``p`` first matches the pair structure against the pair value and the matches the variables to the appropriate substructures.  Once the variables have been matched to value the ``let`` statement declares the variables in the current scope and they become available for computation.
+
+The following is an example involving structures and objects,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-018.ast"
 
-The output is: ``(1,3)``
+We first construct an object ``joe`` with the first ``let`` statement and the use pattern matching to desctructure it with the second ``let`` statement binding its substructures to the variables ``n``, ``a``, and ``p``.
 
-Asteroid supports special patterns called **type patterns** that match any value
+Asteroid supports special patterns called type patterns that match any value
 of a given type.  For instance, the ``%integer`` pattern matches any integer value.  Here is a simple example,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-019.ast"
 
-This ``let`` statement succeeds because ``1`` is an integer value can be pattern-matched against
-the type pattern ``%integer``.
+This let statement succeeds because ``1`` is an integer value can be pattern-matched against
+the type pattern ``%integer``. 
 
 Asteroid also
-supports something called a **named pattern** were a (sub)pattern on the left side
-of a ``let`` statement (or any pattern as it appears in Asteroid) can be given a name
+supports something called a named pattern were a (sub)pattern can be given a name
 and that name will be instantiated with a term during pattern matching.  For example,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-020.ast"
 
-Here, the construct ``t:(1,2)`` is called a named pattern and the variable ``t`` will be unified with the term ``(1,2)``, or more generally, the variable will be unified with term
+Here, the construct ``t:(x,y)`` is called a named pattern and the variable ``t`` will be unified with the term ``(1,2)``, or more generally, the variable will be unified with term
 that matches the pattern on the right of the colon.  The program will print,
 ::
-
     (1,2)
 
+Named patterns are a shorthand notation for conditional patterns; in this case,
+::
+    let t if t is (x,y) = (1,2).
+
 We can combine type patterns and named patterns to give us something that looks
 like a variable declaration in other languages. In Asteroid, though, it is still just all
 about pattern matching.  Consider,
@@ -284,8 +317,17 @@ about pattern matching.  Consider,
 The left side of the ``let`` statement is a named type pattern that matches any real value, and
 if that match is successful then the value is bound to the variable ``x``.  Note
 that even though this looks like a declaration, it is in fact a pattern matching
-operation.  The program will print the value ``3.14`` according to the format of
-4 characters with 2 characters after the decimal point.
+operation.  The program will print the value ``3.141592653589793``.
+
+Beware of the fact that even though the ``let`` statement above looks like a 
+declaration of a real variable it is not; it is a pattern match statement enforcing that the 
+value assigned to ``x`` matches the pattern ``%real``.  Since this is a pattern match statement, this 
+also means that standard type promotions such as promoting integers to reals during assignments in other 
+programming languages do not apply here.  For example, in Asteroid the following let statement fails,
+::
+    let x:%real = 1.
+
+because ``1`` is an integer value and does not match the pattern ``%real``.
 
 Flow of Control
 ---------------
@@ -317,7 +359,7 @@ The output is,
     the second bird is a duck
     the third bird is a chicken
 
-Here we first create a list of pairs using the ``zip`` function, over which we then
+In the loop we first create a list of pairs using the ``zip`` function, over which we then
 iterate pattern matching on each of the pairs on the list with the pattern ``(ix,bird)``.
 
 The following is a short program that demonstrates an ``if`` statement,
@@ -330,12 +372,12 @@ Functions
 ---------
 
 Functions in Asteroid resemble function definitions in functional programming languages such as Haskell and ML.
-Here functions have a single formal argument and function calls are expressed via juxtaposition
-of the function name and the actual argument.  Here is a simple example,
+Here functions definitions have a single formal argument and function calls are expressed via juxtaposition
+of the function name and the single actual argument.  Here is a simple example,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-025a.ast"
 
-In the ``with`` statement we pattern match the actual argument that is
+In the ``with`` expression we pattern match the actual argument that is
 being passed in against the variable ``i``.  Also note that the function call is expressed via juxtaposition,
 no parentheses necessary.
 
@@ -352,7 +394,7 @@ instantiated during this pattern match can be used within the function body.
 
 In Asteroid functions are multi-dispatch, that is,
 a single function can have multiple bodies each attached to a different pattern
-matching the formal argument.
+matching the actual argument.
 The following is the quick sort implemented in
 Asteroid where each ``with`` clause introduces a new function body with its
 corresponding pattern,
@@ -377,20 +419,21 @@ name.  Here is an example using a ``lambda`` function,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-027.ast"
 
-The output is ``2``.  Here, the lambda function is a function that takes a value
+The output is ``2``.  Here, the ``lambda`` function is a function that takes a value
 and increments it by one.  We then apply the value ``1`` to the function and the
 print function prints out the value ``2``.
 
 Pattern Matching
 ----------------
 
-Pattern matching lies at the heart of Asteroid.  We saw some of Asteroid's pattern matching ability when we discussed the ``let`` statement.  We can also have pattern matching
-in expressions using the ``is`` predicate.
+Pattern matching lies at the heart of Asteroid.  We saw some of Asteroid's pattern matching ability when we discussed the ``let`` statement.  Here is a more general discussion of pattern matching.
 
-Pattern Matching in Expressions: The ``is`` Predicate
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Pattern Matching in Expressions: The Is Predicate
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Consider the following example of this predicate among some patterns,
+We can also have pattern matching
+in expressions using the ``is`` predicate.
+Consider the following example,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-028.ast"
 
@@ -401,7 +444,7 @@ output of this program is,
     it's a pair with: 1,2
 
 Pattern matching with the ``is`` predicate can happen anywhere expressions can
-be used.  That means we can use the predicate also in ``let`` statements,
+be used.  That means we can use the predicate also on the right side of ``let`` statements,
 ::
 
     let true = (1,2) is (1,2).
@@ -410,7 +453,7 @@ This is kind of strange looking but it succeeds.  Here the
 left operand of the ``is`` predicate is a term and
 the right operand is a pattern.  Obviously this pattern match will succeed because the
 term and the pattern look identical.  The return value of the ``is`` predicate is then
-pattern matched against the ``true`` value on the left of the ``=`` symbol.
+pattern matched against the ``true`` pattern on the left of the ``=`` symbol.
 
 We can also employ pattern matching in loops.
 In the following program we use the ``is`` predicate to test whether a list is empty or not
@@ -425,31 +468,21 @@ The output is,
     2
     3
 
-In addition, the example employs pattern matching using the head-tail operator  in order to iterate over the list elements and print print them.  The
+The example employs pattern matching using the head-tail operator in order to iterate over the list elements and print them.  The
 termination condition of the loop is computed with the ``is`` predicate.
 
 Pattern Matching in Function Arguments
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 As we have seen earlier, Asteroid supports pattern matching on function arguments in the style of ML and many other functional programming languages.
-Here is an example that uses pattern matching on function arguments using custom data structures.  The program below implements `Peano addition <https://en.wikipedia.org/wiki/Peano_axioms#Addition>`_ on terms using the two Peano axioms,
-::
-
-    x + 0 = x
-    x + s(y) = s(x+y)
-
-Here ``x`` and ``y`` are variables, ``0`` represents the natural number with value zero, and ``s`` is the successor function.  In Peano arithmetic any natural number can be represented by the appropriate number of applications of the successor function to the natural number ``0``. Here is the program that implements
-the Peano arithmetic based on the two axiom where we replaced the ``+`` operator with the
-``add`` symbol,
+Here is an example that uses pattern matching on function arguments using binary tree data structures,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-030.ast"
 
-Our program defines the structure ``s`` to represent the successor function and the structure ``add`` to represent Peano addition. Next, it defines a function that uses pattern matching to identify the left sides of the two axioms.  If either pattern matches the input to the ``reduce`` function, it will activate the corresponding function body and rewrite the term recursively in an appropriate manner.  We have one additional pattern which matches if neither one of the Peano axiom patterns matches and terminates the recursion.  Finally,  on the last line, we use our ``reduce`` function to compute the Peano term for the addition of 2 + 3. As expected, the output of this program is,
-::
-
-    s(s(s(s(s(0)))))
-
-which represents the value 5.
+The structures ``Node`` and ``Leaf`` allow us to construct binary trees with embedded values.
+The ``traverse`` function traverses such trees and collects the values embedded in a tree on a list 
+and returns that list.  Notice the pattern matching on the tree node constructs in the ``with`` clauses
+of the ``traverse`` funtion.  
 
 Conditional Pattern Matching
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -466,9 +499,16 @@ Here we see that first, we make sure that we are being passed integers and secon
 that the integers are positive using the appropriate conditions on the input values. If
 we are being passed a negative integer, then we throw an error.
 
+The above factorial program can be simplified by rewriting the first condition on ``n`` in the conditional patterns as a named pattern.
+We can also take advantage of the fact that the last expression evaluated in a function body provides an implicit return value.
+This gives us,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-031a.ast"
+
+The parentheses as they appear in the conditional pattern expressions are necessary.
 
-Pattern Matching in ``for`` Loops
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Pattern Matching in For Loops
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 We have seen pattern matching in ``for`` loops earlier.  Here we show another
 example. This combines structural matching with regular expression matching
@@ -477,10 +517,10 @@ that selects certain items from a list. Suppose we want to print out the names o
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-032.ast"
 
-Here we pattern match the ``Person`` object in the ``for`` loop and then use a regular expression to see if the name of that person matches our requirement that it contains a lower case 'p'.  We can tag the pattern with a variable name, a named pattern, so that we can print out the name if the regular expression matches. The output is ``Sophie``.
+Here we pattern match the ``Person`` object in the ``for`` loop and then use a regular expression to see if the name of that person matches our requirement that it contains a lower case 'p'.  The output is ``Sophie``.
 
-Pattern Matching in ``try-catch`` Statements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Pattern Matching in Try-Catch Statements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Exception handling in Asteroid is very similar to exception handling in many of the other modern programming languages available today.  The example below shows an Asteroid program  that throws one of two exceptions depending on the randomly generated value ``i``,
 ::
@@ -492,8 +532,8 @@ It is worth noting that even though Asteroid has builtin exception objects such
 you can construct any kind of object and throw it as part of an exception.
 
 
-Structures, Object-Based Programming, and Pattern Matching
-----------------------------------------------------------
+Structures, Object-Oriented Programming, and Pattern Matching
+-------------------------------------------------------------
 
 We saw structures such as,
 ::
@@ -501,42 +541,40 @@ We saw structures such as,
     structure Person with
         data name.
         data age.
-        data gender.
-        end
+    end
 
 earlier.  It is Asteroid's way to create custom data structures. These structures
 introduce a new type name into a program. For instance, in the case above, the ``structure``
 statement introduces the type name ``Person``.   Given a structure definition, we can
-create **instances** of that structure.  For example,
+create objects from that structure.  For example,
 ::
 
-    let scarlett = Person("Scarlett",28,"F").
+    let scarlett = Person("Scarlett",28).
 
 The right side of the ``let`` statement invokes the default constructor for the
-structure in order to create an instance stored in the variable ``scarlett``. We
-can access members of the instance,
+structure in order to create an object stored in the variable ``scarlett``. We
+can access members of the object,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-034.ast"
 
 Asteroid allows you to attach functions to structures.  In member functions
-the object identity of the instance is available through the ``this`` keyword.
+the object identity is available through the ``this`` keyword.
 For example, we can
 extend our ``Person`` structure with the ``hello`` function that uses the ``name`` field
-of the instance,
+of the object,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-035.ast"
 
 This program will print out,
 ::
-
     Hello, my name is Scarlett
 
-The expression ``this @name`` accesses the ``name`` field of the instance the
+The expression ``this@name`` accesses the ``name`` field of the object the
 function ``hello`` was called on.
 Even though our structures are starting to look a bit more like object definitions,
 pattern matching continues to work in the same way from when we discussed structures.
-The only thing you need to keep in mind is that you **cannot** pattern match on a
-function field.  From a pattern matching perspective, a structure consists only of
+The only thing you need to keep in mind is that you cannot pattern match on a
+function member field.  From a pattern matching perspective, a structure consists only of
 data fields.  So even if we declare a structure like this,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-036.ast"
@@ -545,43 +583,41 @@ where the function ``hello`` is defined in the middle of the data fields,
 pattern matching simply ignores the function definition and pattern matches
 only on the data fields.  The output of the program is,
 ::
-
     Scarlett is 28 years old
 
-Here is a slightly more involved example based on the
+Here is a slightly more involved example loosely based on the
 dog example from the `Python documentation <https://docs.python.org/3/tutorial/classes.html>`_.
 The idea of the dog example is to have a structure that describes dogs by their
-names and the tricks that they can perform.  Tricks can be added to a particular
-dog instance by calling the ``add_trick`` function.  Rather than using the default
-constructor, we define a constructor for our instances with the ``__init__`` function.
+names and the tricks that they can perform.   Rather than using the default
+constructor, we define a constructor for our instances with the ``__init__`` function
+that performs some basic type checking on its arguments using type patterns and then 
+initializes the data members of the object.
 Here is the program listing for the example in Asteroid,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-037.ast"
 
-After declaring the structure we instantiate two dogs, Fido and Buddy, and add
-tricks to their respective trick repertoires.  The last couple of lines
+After declaring the structure we instantiate the dogs with their
+respective trick repertoires and put them on a list.  The last couple of lines
 of the program consist of a ``for`` loop over a list of our dogs.
 The ``for`` loop is interesting
 because here we use structural, conditional, and regular expression pattern
 matching in order to only select the dogs that know how to do ``fetch`` from
 the list of dogs.  The pattern is,
 ::
-
-    Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*"
+    Dog(name,tricks) if type @tostring tricks is ".*fetch.*"
 
 The structural part of the pattern is ``Dog(name,tricks)`` which simply matches
 any dog instance on the list.  However, that match is only successful if
 the conditional part of the pattern holds,
 ::
-
-    if type @tostring(tricks) is ".*fetch.*"
+    if type @tostring tricks is ".*fetch.*"
 
 This condition only succeeds if the ``tricks`` list viewed as a string matches
 the regular expression ``".*fetch.*"``. That is, if the list contains the word ``fetch``.
 The output is,
 ::
-
     Fido knows how to fetch
+    Bella knows how to fetch
 
 
 Patterns as First-Class Citizens
@@ -598,16 +634,16 @@ doesn't change what we can and cannot compute with the language. But it does cha
 we can express what we want to compute.  That is, it changes the expressiveness
 of a programming language.
 
-In Asteroid first-class patterns are introduced with the keywords ``pattern with``
+In Asteroid first-class patterns are introduced with the keyword ``pattern``
 and patterns themselves are values that we can store in variables and then reference
 when we want to use them.  Like so,
 ::
 
-    let P = pattern (x,y).
-    let *P = (1,2).
+    let p = pattern (x,y).  -- define a first-class pattern 
+    let *p = (1,2).         -- use the first-class pattern
 
-The left side of the second ``let`` statement dereferences the pattern stored in variable ``P``
-and uses the pattern to match against the term ``(1,2)``.
+The left side of the second ``let`` statement dereferences the pattern stored in variable ``p``
+and uses the pattern to match against the value ``(1,2)``.
 
 Here we look at three examples of how first-class patterns can add to a developer's
 programming toolbox.
@@ -619,31 +655,27 @@ Patterns can become very complicated especially when conditional pattern matchin
 is involved.  First-class patterns allow us to control the complexity of patterns
 by breaking patterns up into smaller subpatterns that are more easily managed. Consider
 the following function that takes a pair of values.  The twist is that
-the first component of the pair is restricted to the primitive data types of
+the first component of the pair is restricted to primitive data types of
 Asteroid,
 ::
 
-    function foo
-        with (x if (x is %boolean) or (x is %integer) or (x is %string),y) do
-            io @println (x,y).
-        end
+    function foo with (x if (x is %boolean) or (x is %integer) or (x is %string),y) do
+        io @println (x,y).
+    end
 
-That complicated pattern for the first component completely obliterates the
+That complicated pattern for the first component of the input pair completely obliterates the
 overall structure of the parameter pattern and makes the function definition
 difficult to read.
 
 We can express the same function with a first-class pattern,
 ::
+    let TP = pattern q if (q is %boolean) or
+                          (q is %integer) or
+                          (q is %string).
 
-    let TP = pattern
-        with q if (q is %boolean) or
-                  (q is %integer) or
-                  (q is %string).
-
-    function foo
-        with (x:*TP,y) do
-            io @println (x,y).
-        end
+    function foo with (x:*TP,y) do
+        io @println (x,y).
+    end
 
 It is clear now that the main input structure to the function is a pair and the
 conditional type restriction pattern has been relegated to a subpattern stored in the variable
@@ -669,7 +701,7 @@ The relevant patterns are now stored in the variables ``POS_INT`` and ``NEG_INT`
 which are then used in the function definitions.
 
 Constraint Patterns
--------------------
+^^^^^^^^^^^^^^^^^^^
 
 Sometimes we want to use patterns as constraints on other patterns.  Consider
 the following (somewhat artificial) example,
@@ -681,8 +713,8 @@ Here we want to use the pattern ``v if (v is %integer) and v > 0`` purely as a c
 on the pattern ``x`` in the sense that we want a match on ``x`` only to succeed
 if ``some_value`` is a positive integer.  The problem is that this constraint pattern
 introduces a spurious binding of the variable ``v`` into the current environment
-which might be undesirable due to variable name clashes.  Our notion of constraint pattern
-addresses this.  We can rewrite the above statement as follows,
+which might be undesirable due to variable name clashes.  Constraint patterns
+address this.  We can rewrite the above statement as follows,
 ::
 
    let x: %[v if (v is %integer) and v > 0]% = some_value.
@@ -704,109 +736,26 @@ With the ``%[...]%`` operators in place we prevent
 the pattern ``v if (v is %integer) and v > 0`` from instantiating the variable ``v`` thus preventing a non-linearity
 to occur in the argument list pattern.
 
-
-More on Multi-Dispatch
-----------------------
-
-With the ``qsort`` function above we saw functional programming style dispatch
-where the ``with`` clauses represent a case analysis over a single type, namely
-the input type to the function.
-However, Asteroid has a much broader view of multi-dispatch where the ``with`` clauses
-represent a case analysis over different types.
-In order to demonstrate this type of multi-dispatch, we show the example program from the
-`multi-dispatch Wikipedia page <https://en.wikipedia.org/wiki/Multiple_dispatch>`_
-written in Asteroid,
+Sometimes we need to use constraint patterns instead of straightforward patterns
+in order to avoid non-linearities but
+we also want controlled access to the variables these constraint patterns declare.
+We achieve this by using the ``bind`` keyword at the pattern-match site.  
+Consider the following program,
 ::
-#include "../asteroid/test-suites/ug-programs/prgm-044.ast"
+#include "../asteroid/test-suites/ug-programs/prgm-043a.ast"
 
-Each ``with`` clause in the function ``collide_with`` introduces a new function body with its
-corresponding pattern.
-The function bodies in this case are simple ``return`` statements
-but they could be arbitrary computations.  The output of the program is,
-::
+In the function definition of ``dot2d`` we see that the ``Pair`` pattern is used 
+twice to make sure that the function is called with a pair of pairs as its argument.
+However, in order to compute the dot product of those two pairs we need access 
+to the values each pair matched.  We use the ``bind`` keyword together with an 
+appropriate binding term list to extract the matched values.  For the first
+pair we map ``x`` and ``y`` to ``a1`` and ``a2`` and for the second 
+pair we map ``x`` and ``y`` to ``b1`` and ``b2``, respectively.
 
-    Big boom!
-    a/s
-    s/s
-
-
-
-More on Exceptions
-------------------
-
-This section will give further information on how to work with **exceptions**, or unexpected conditions that break the regular flow of execution.  Exceptions generated by Asteroid are ``Exception`` objects with the following structure,
-::
-
-    structure Exception with
-        data kind.
-        data value.
-    end
-
-The ``kind`` field will be populated by Asteroid with one of the following strings,
-
-* ``PatternMatchFailed`` - this exception will be thrown if the user attempted an
-  explicit pattern match which failed, e.g. a let statement whose left side pattern
-  does not match the term on the right side.
-
-* ``NonLinearPatternError`` - this exception occurs when a pattern has more than
-  one variable with the same name, e.g. ``let (x,x) = (1,2).``
-
-* ``RedundantPatternFound`` - this exception is thrown if one pattern makes another
-  superfluous, e.g. in a multi-dispatch function definition.
-
-* ``ArithmeticError`` - e.g. division by zero
-
-* ``FileNotFound`` - an attempt of opening a file failed.
-
-* ``SystemError`` - a general exception.
-
-In addition to the ``kind`` field, the ``value`` field holds a string with some further details on the exception. Specific exceptions can be caught by pattern matching on the ``kind`` field of the ``Exception`` object.  For
-example,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-045.ast"
-
-The output is,
-::
-
-    integer division or modulo by zero
-
-
-Asteroid also provides a predefined ``Error`` object for user level exceptions,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-046.ast"
-
-Of course the user can also use the ``Exception`` object for their own exceptions
-by defining a ``kind`` that does not interfere with the predefined ``kind`` strings above,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-047.ast"
-
-The output here is,
-::
-
-    something worth throwing
-
-In addition to the Asteroid defined exceptions,
-the user is allowed to construct user level exceptions with any kind of object including tuples and lists. Here is an example that constructs a tuple as an exception object,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-048.ast"
-
-The output of this program is ``42``.
-
-Now, if you don't care what kind of exception you catch, you need to use a ``wildcard`` or a variable because exception handlers are activated via pattern matching on the
-exception object itself.  Here is an example using a ``wildcard``,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-049.ast"
-
-Here is an example using a variable,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-050.ast"
-
-In this last example we simply convert the caught exception object into a string
-and print it,
-::
-
-    something happened: Exception(PatternMatchFailed,pattern match failed: term and pattern
-    lists/tuples are not the same length)
+As a quick aside, the ``as`` construction in the binding term list is only necessary 
+when trying to resolve non-linearities otherwise the binding term list can just consist
+of the variable names appearing in the pattern that you want to bind into the current
+scope.
 
 
 Basic Asteroid I/O
@@ -904,3 +853,108 @@ Say that you wanted to load the ``math`` module so you could execute a certain t
 Both the function ``sin`` and the constant value ``pi`` are defined in the ``math`` module.
 In addition, the ``io`` module is where all input/output functions in Asteroid (such as ``println``) come from.
 If you want the complete list of modules, make sure to check out the reference guide `here <https://asteroid-lang.readthedocs.io/en/latest/Reference%20Guide.html>`_.
+
+
+More on Exceptions
+------------------
+
+This section will give further information on how to work with exceptions, or unexpected conditions that break the regular flow of execution.  Exceptions generated by Asteroid are ``Exception`` objects with the following structure,
+::
+
+    structure Exception with
+        data kind.
+        data value.
+    end
+
+The ``kind`` field will be populated by Asteroid with one of the following strings,
+
+* ``PatternMatchFailed`` - this exception will be thrown if the user attempted an
+  explicit pattern match which failed, e.g. a let statement whose left side pattern
+  does not match the term on the right side.
+
+* ``NonLinearPatternError`` - this exception occurs when a pattern has more than
+  one variable with the same name, e.g. ``let (x,x) = (1,2).``
+
+* ``RedundantPatternFound`` - this exception is thrown if one pattern makes another
+  superfluous, e.g. in a multi-dispatch function definition.
+
+* ``ArithmeticError`` - e.g. division by zero
+
+* ``FileNotFound`` - an attempt of opening a file failed.
+
+* ``SystemError`` - a general exception.
+
+In addition to the ``kind`` field, the ``value`` field holds a string with some further details on the exception. Specific exceptions can be caught by pattern matching on the ``kind`` field of the ``Exception`` object.  For
+example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-045.ast"
+
+The output is,
+::
+
+    integer division or modulo by zero
+
+
+Asteroid also provides a predefined ``Error`` object for user level exceptions,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-046.ast"
+
+Of course the user can also use the ``Exception`` object for their own exceptions
+by defining a ``kind`` that does not interfere with the predefined ``kind`` strings above,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-047.ast"
+
+The output here is,
+::
+
+    something worth throwing
+
+In addition to the Asteroid defined exceptions,
+the user is allowed to construct user level exceptions with any kind of object including tuples and lists. Here is an example that constructs a tuple as an exception object,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-048.ast"
+
+The output of this program is ``42``.
+
+Now, if you don't care what kind of exception you catch, you need to use a ``wildcard`` or a variable because exception handlers are activated via pattern matching on the
+exception object itself.  Here is an example using a ``wildcard``,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-049.ast"
+
+Here is an example using a variable,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-050.ast"
+
+In this last example we simply convert the caught exception object into a string
+and print it,
+::
+
+    something happened: Exception(PatternMatchFailed,pattern match failed: term and pattern
+    lists/tuples are not the same length)
+
+
+More on Multi-Dispatch
+----------------------
+
+With the ``qsort`` function above we saw functional programming style dispatch
+where the ``with`` clauses represent a case analysis over a single type, namely
+the input type to the function.
+However, Asteroid has a much broader view of multi-dispatch where the ``with`` clauses
+can represent a case analysis over different types.
+In order to demonstrate this type of multi-dispatch, we show the example program from the
+`multi-dispatch Wikipedia page <https://en.wikipedia.org/wiki/Multiple_dispatch>`_
+written in Asteroid,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-044.ast"
+
+Each ``with`` clause in the function ``collide_with`` introduces a new function body with its
+corresponding pattern.
+The function bodies in this case are simple ``return`` statements
+but they could be arbitrary computations.  The output of the program is,
+::
+
+    Big boom!
+    a/s
+    s/s
+
+
diff --git a/docs/conf.py b/docs/conf.py
index 59974016..a8a52a69 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -22,7 +22,7 @@
 author = 'Lutz Hamel, Tim Colaneri, Oliver McLaughlin, Ariel Finkel, Theodore Henson, Calvin Higgins, Christian Tropeano'
 
 # The full version, including alpha/beta/rc tags
-release = '1.1.3'
+release = '1.1.4'
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/docs/generate_docs b/docs/generate_docs
index 3b798d16..4d5679c4 100755
--- a/docs/generate_docs
+++ b/docs/generate_docs
@@ -1,19 +1,24 @@
 #!/bin/bash
 
 echo "generating User Guide.rst"
-cpp -w -P -traditional "User Guide.txt" > "User Guide.rst"
+#cpp -w -P -traditional "User Guide.txt" > "User Guide.rst"
+pcpp --passthru-comments --line-directive nothing "User Guide.txt" > "User Guide.rst"
 
 echo "generating Reference Guide.rst"
 # note: we need to strip multiline C comments manually
 #       because cpp likes to preserve newlines of multiline comments...
 bash strip ../asteroid/grammar.txt >/tmp/grammar.tmp
-cpp -w -P -traditional "Reference Guide.txt" > "Reference Guide.rst"
+#cpp -w -P -traditional "Reference Guide.txt" > "Reference Guide.rst"
+pcpp --passthru-comments --line-directive nothing "Reference Guide.txt" > "Reference Guide.rst"
 
 echo "generating Asteroid in Action.rst"
-cpp -w -P -traditional "Asteroid in Action.txt" > "Asteroid in Action.rst"
+#cpp -w -P -traditional "Asteroid in Action.txt" > "Asteroid in Action.rst"
+pcpp --passthru-comments --line-directive nothing "Asteroid in Action.txt" > "Asteroid in Action.rst"
 
 echo "generating Quickstart Tutorial.rst"
-cpp -w -P -traditional "Quickstart Tutorial.txt" > "Quickstart Tutorial.rst"
+#cpp -w -P -traditional "Quickstart Tutorial.txt" > "Quickstart Tutorial.rst"
+pcpp --passthru-comments --line-directive nothing "Quickstart Tutorial.txt" > "Quickstart Tutorial.rst"
 
 echo "generating ADB.rst"
-cpp -w -P -traditional "ADB.txt" > "ADB.rst"
+#cpp -w -P -traditional "ADB.txt" > "ADB.rst"
+pcpp --passthru-comments --line-directive nothing "ADB.txt" > "ADB.rst"
diff --git a/docs/header.txt b/docs/header.txt
index eb548f7b..ffc3e15c 100644
--- a/docs/header.txt
+++ b/docs/header.txt
@@ -1,4 +1,5 @@
-/* header for generated .rst files */
+..
+   /* header for generated .rst files */
 
 ..
    *** DO NOT EDIT; MACHINE GENERATED ***
diff --git a/editor-support/asteroid.vim b/editor-support/asteroid.vim
index 49a4bc83..c5327efe 100644
--- a/editor-support/asteroid.vim
+++ b/editor-support/asteroid.vim
@@ -11,9 +11,45 @@ if exists("b:current_syntax")
 	finish
 endif
 
-syn keyword basic with end do load let for function structure in is pattern 
-syn keyword basic throw this system data global return to step if not
-syn keyword basic else or and
+syn keyword basic and
+syn keyword basic as
+syn keyword basic assert
+syn keyword basic bind
+syn keyword basic break
+syn keyword basic catch
+syn keyword basic data
+syn keyword basic do
+syn keyword basic elif
+syn keyword basic else
+syn keyword basic end
+syn keyword basic escape
+syn keyword basic eval
+syn keyword basic for
+syn keyword basic from
+syn keyword basic function
+syn keyword basic global
+syn keyword basic if
+syn keyword basic in
+syn keyword basic is
+syn keyword basic lambda
+syn keyword basic let
+syn keyword basic load
+syn keyword basic loop
+syn keyword basic not
+syn keyword basic or
+syn keyword basic orwith
+syn keyword basic pattern
+syn keyword basic repeat
+syn keyword basic return
+syn keyword basic step
+syn keyword basic structure
+syn keyword basic system
+syn keyword basic throw
+syn keyword basic to
+syn keyword basic try
+syn keyword basic until
+syn keyword basic while
+syn keyword basic with
 
 syn keyword delimeter escape
 
diff --git a/editor-support/vscode/syntaxes/asteroid.tmLanguage.json b/editor-support/vscode/syntaxes/asteroid.tmLanguage.json
index 8f68d8f9..4d51b2a2 100644
--- a/editor-support/vscode/syntaxes/asteroid.tmLanguage.json
+++ b/editor-support/vscode/syntaxes/asteroid.tmLanguage.json
@@ -90,7 +90,7 @@
 		{
 			"name": "keyword",
 			"comment": "keyword.other.asteroid",
-			"match": "\\b(assert|eval)\\b"
+			"match": "\\b(as|assert|bind|eval)\\b"
 		},
 		{
 			"name": "keyword.operator.comparison.asteroid",
diff --git a/setup.py b/setup.py
index 982ec5be..d9c253f1 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
 
 setup(
     name="asteroid-lang",
-    version="1.1.3",
+    version="1.1.4",
     author="University of Rhode Island",
     author_email="lutzhamel@uri.edu",
     description="A modern, multi-paradigm programming language.",


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index d66582f6..9fb263bb 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -2,7 +2,7 @@ name: Run Tests
 on:
     pull_request:
         branches:
-            - dev-1.1.4
+            - '!master'
 env:
     PYTHONPATH: ${{ github.workspace }}
 jobs:
diff --git a/asteroid/test-suites/action-tests/test013.ast b/asteroid/test-suites/action-tests/test013.ast
index a0211b23..3cea1353 100644
--- a/asteroid/test-suites/action-tests/test013.ast
+++ b/asteroid/test-suites/action-tests/test013.ast
@@ -15,8 +15,7 @@
   let pick_list = int_list+lc_list+uc_list+sp_list.
 
   -- generate the password and print it.
-  let pwd = pick @pick pick_list @pick(15)
-                           @join("").
+  let pwd = pick @pick pick_list @pickitems 15 @join("").
   io @println pwd.
 
   assert (pwd == "e3zvshdbS43brt#")
diff --git a/asteroid/test-suites/action-tests/test024.ast b/asteroid/test-suites/action-tests/test024.ast
index d2d1e37b..f8e3dbfe 100644
--- a/asteroid/test-suites/action-tests/test024.ast
+++ b/asteroid/test-suites/action-tests/test024.ast
@@ -1,7 +1,8 @@
   load system io.
   load system math.
 
+  let tau = 2 * math @pi.
+
   io @println (math @e).
-  io @println (math @tau). -- tau=2*pi
+  io @println tau.
 
-  assert (math @tau == 2 * math @pi)
diff --git a/asteroid/test-suites/ref-programs/pick.ast b/asteroid/test-suites/ref-programs/pick.ast
index 6378639c..1ba8821b 100644
--- a/asteroid/test-suites/ref-programs/pick.ast
+++ b/asteroid/test-suites/ref-programs/pick.ast
@@ -2,6 +2,6 @@
    load system pick.
 
    let po = pick @pick([1 to 10]).
-   let objects = po @pick(3).
+   let objects = po @pickitems 3.
    io @println objects.
    
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/sort.ast b/asteroid/test-suites/ref-programs/sort.ast
index 34ac21f7..f5b65dc7 100644
--- a/asteroid/test-suites/ref-programs/sort.ast
+++ b/asteroid/test-suites/ref-programs/sort.ast
@@ -1,5 +1,5 @@
    load system io.
    load system sort.
-   let sl = sort @sort((lambda with (x,y) do return true if x<y else false),
+   let sl = sort @sort((lambda with (x,y) do true if x<y else false),
                        [10,5,110,50]).
-    io @println sl.
+   io @println sl.
diff --git a/asteroid/test-suites/ref-programs/stream.ast b/asteroid/test-suites/ref-programs/stream.ast
index b4d85cd0..41971f97 100644
--- a/asteroid/test-suites/ref-programs/stream.ast
+++ b/asteroid/test-suites/ref-programs/stream.ast
@@ -1,9 +1,9 @@
    load system io.
    load system stream.
 
-   let s = stream @stream([1 to 10]).
-   while not s @ eof() do
-      io @ print (s @get()+" ").
+   let s = stream @stream [1 to 10].
+   while not s @eof() do
+      io @print (s @get() + " ").
    end
-   io @println ("").
+   io @println "".
    
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test004.ast b/asteroid/test-suites/regression-tests/test004.ast
index 50483b8c..1a7c7ee7 100644
--- a/asteroid/test-suites/regression-tests/test004.ast
+++ b/asteroid/test-suites/regression-tests/test004.ast
@@ -1,4 +1,5 @@
 
 load system io.
-let l:"\[.*\]" = [1,2,3].
+load system type.
+let l if type @tostring l is "\[.*\]" = [1,2,3].
 io @println l.
diff --git a/asteroid/test-suites/regression-tests/test008.ast b/asteroid/test-suites/regression-tests/test008.ast-not-valid
similarity index 64%
rename from asteroid/test-suites/regression-tests/test008.ast
rename to asteroid/test-suites/regression-tests/test008.ast-not-valid
index 71b82127..916061c2 100644
--- a/asteroid/test-suites/regression-tests/test008.ast
+++ b/asteroid/test-suites/regression-tests/test008.ast-not-valid
@@ -1,3 +1,6 @@
+-- this test case is no longer valid, we no longer allow
+-- patterns as constructors, except for the simplest
+-- cases because patterns have become too complicated
 load system io.
 
 structure Family with
@@ -10,7 +13,7 @@ structure Family with
     end
   end -- structure
   
-let FAMILY = pattern with Family(*PARENT1).
+let FAMILY = pattern with Family(PARENT1).
 
 structure Parent with
   data name.
diff --git a/asteroid/test-suites/regression-tests/test017.ast b/asteroid/test-suites/regression-tests/test017.ast
index d32904e9..3e412235 100644
--- a/asteroid/test-suites/regression-tests/test017.ast
+++ b/asteroid/test-suites/regression-tests/test017.ast
@@ -1,5 +1,6 @@
 
 load system io.
-load "util".
+load system type.
 
-let (l:%list) if l is "\[.*2.*\]" = [1,2,3].
+let (l:%list) if type @tostring l is "\[.*2.*\]" = [1,2,3].
+assert(l == [1,2,3]).
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test138.ast b/asteroid/test-suites/regression-tests/test138.ast
new file mode 100644
index 00000000..babbed0f
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test138.ast
@@ -0,0 +1,18 @@
+-- test case for issue #209
+load system io.
+
+function goo with none do
+   throw Error("exception").
+end
+
+function foo with none do
+   let a = 1.
+   try
+      goo().
+   catch _ do
+      io @println "exception caught".
+   end
+   assert(a==1).  -- make that a is still in scope
+end
+
+foo ().
diff --git a/asteroid/test-suites/regression-tests/test139.ast b/asteroid/test-suites/regression-tests/test139.ast
new file mode 100644
index 00000000..8fe0825b
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test139.ast
@@ -0,0 +1,9 @@
+-- test binding terms
+let Pair = pattern %[(x,y)]%.
+
+function add with ( *Pair bind [x as a, y as b], 
+                    *Pair bind [x as c, y as d] ) do
+   return (a+c, b+d).
+end 
+
+assert(add((1,2),(3,4))== (4,6)).
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test140.ast b/asteroid/test-suites/regression-tests/test140.ast
new file mode 100644
index 00000000..59a89303
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test140.ast
@@ -0,0 +1,6 @@
+-- test binding terms
+let Pair = pattern %[(x,y)]%.
+
+let *Pair bind [x as a, y] = (1,2).  -- bindings of the variables x and y are now visible again
+assert( a == 1).
+assert(y == 2).
diff --git a/asteroid/test-suites/regression-tests/test141.ast b/asteroid/test-suites/regression-tests/test141.ast
new file mode 100644
index 00000000..24665d96
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test141.ast
@@ -0,0 +1,7 @@
+let Pair = pattern (x,y).
+
+try 
+   let *Pair bind [x as a, y] = (1,2).  -- bindings of the variables x and y are now visible again
+catch Exception(errortype,s) do
+   assert(s is ".*binding term lists.*").
+end
diff --git a/asteroid/test-suites/regression-tests/test142.ast b/asteroid/test-suites/regression-tests/test142.ast
new file mode 100644
index 00000000..78cbf440
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test142.ast
@@ -0,0 +1,5 @@
+load system io.
+
+for c in (1,2,3) do
+   io @println c.
+end
diff --git a/asteroid/test-suites/regression-tests/test143.ast b/asteroid/test-suites/regression-tests/test143.ast
new file mode 100644
index 00000000..d6321277
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test143.ast
@@ -0,0 +1,19 @@
+-- define a structure of type Person
+structure Person with
+      data name.
+      data age.
+      function __init__ with (name:%string,age:%integer) do -- constructor
+         let this @name = name.
+         let this @age = age.
+      end
+      function __str__ with none do
+         return this@name+" is "+this@age+" years old".
+      end
+end
+
+let betty = Person("Betty",21).  -- call constructor
+assert( betty @name == "Betty" ).
+assert( betty @age == 21 ).
+
+load system type.
+assert(type @tostring betty is "Betty is 21 years old").
diff --git a/asteroid/test-suites/regression-tests/test144.ast b/asteroid/test-suites/regression-tests/test144.ast
new file mode 100644
index 00000000..d58ef9ac
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test144.ast
@@ -0,0 +1,2 @@
+let a = eval "1+1".
+assert(a == 2).
diff --git a/asteroid/test-suites/regression-tests/test145.ast b/asteroid/test-suites/regression-tests/test145.ast
new file mode 100644
index 00000000..496682e7
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test145.ast
@@ -0,0 +1,5 @@
+let p = pattern (x,y)
+let x = 1.
+let y = 2.
+let o = eval p.
+assert(o is (1,2)).
diff --git a/asteroid/test-suites/run-tests.py b/asteroid/test-suites/run-tests.py
index b17eb248..9cb9cffa 100755
--- a/asteroid/test-suites/run-tests.py
+++ b/asteroid/test-suites/run-tests.py
@@ -7,7 +7,7 @@
 # the following is a list of directories of test cases the script will run
 
 dirs = [
-	'action-tests',
+	    'action-tests',
         'first-class-redundant-pattern-tests',
         'redundant-pattern-test',
         'ref-programs',
@@ -41,8 +41,12 @@
 # the working directory to that path
 file_path = os.path.dirname(os.path.abspath( __file__ ))
 os.chdir(file_path)
+# append the parent dir of our current dir to the PYTHONPATH
+# so that we can easily find our Asteroid modules
+(parent_dir,_) = os.path.split(file_path)
+sys.path.append(parent_dir)
 
-from asteroid.interp import interp
+from interp import interp
 
 for d in dirs:
     tests = os.listdir(d)
diff --git a/asteroid/test-suites/ug-programs/prgm-008a.ast b/asteroid/test-suites/ug-programs/prgm-008a.ast
new file mode 100644
index 00000000..f4337f67
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-008a.ast
@@ -0,0 +1,9 @@
+   load system type.
+
+   -- define a function
+   function inc with x do
+      return x+1.
+   end
+
+   -- show that 'inc' is of type 'function'
+   assert (type @gettype(inc) == "function").
\ No newline at end of file
diff --git a/asteroid/test-suites/ug-programs/prgm-009.ast b/asteroid/test-suites/ug-programs/prgm-009.ast
index 48962bf3..79ea85f1 100644
--- a/asteroid/test-suites/ug-programs/prgm-009.ast
+++ b/asteroid/test-suites/ug-programs/prgm-009.ast
@@ -1,5 +1,5 @@
-    load system io.    -- load the io module so we can print
+    load system io.   
 
-    let a = [1,2,3].             -- construct list a
-    let b = [a @2, a @1, a @0].  -- reverse list a
+    let a = [1,2,3].          -- construct list a
+    let b = [a@2, a@1, a@0].  -- reverse list a
     io @println b.
diff --git a/asteroid/test-suites/ug-programs/prgm-009a.ast b/asteroid/test-suites/ug-programs/prgm-009a.ast
index 126df5f9..3b1d5253 100644
--- a/asteroid/test-suites/ug-programs/prgm-009a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-009a.ast
@@ -1,5 +1,5 @@
-    load system io.    -- load the io module so we can print
+    load system io.  
 
     let a = [1,2,3].     -- construct list a
-    let b = a @[2,1,0].  -- reverse list a using slice [2,1,0]
+    let b = a@[2,1,0].   -- reverse list a using slice [2,1,0]
     io @println b.
diff --git a/asteroid/test-suites/ug-programs/prgm-010.ast b/asteroid/test-suites/ug-programs/prgm-010.ast
index 4fa9e71b..8353f72a 100644
--- a/asteroid/test-suites/ug-programs/prgm-010.ast
+++ b/asteroid/test-suites/ug-programs/prgm-010.ast
@@ -1,5 +1,5 @@
     load system io.
 
     let a = [1,2,3].
-    let b = a @reverse(). -- reverse list using member function 'reverse'
+    let b = a @reverse (). -- reverse list using member function 'reverse'
     io @println b.
diff --git a/asteroid/test-suites/ug-programs/prgm-011.ast b/asteroid/test-suites/ug-programs/prgm-011.ast
index 77d47063..2b1a2671 100644
--- a/asteroid/test-suites/ug-programs/prgm-011.ast
+++ b/asteroid/test-suites/ug-programs/prgm-011.ast
@@ -6,5 +6,5 @@
 
     -- reverse the list using a slice computed as comprehension
     let slice = [4 to 0 step -1]. -- list comprehension
-    let b = a @slice.
+    let b = a@slice.
     io @println ("reversed list: " + b).
diff --git a/asteroid/test-suites/ug-programs/prgm-012.ast b/asteroid/test-suites/ug-programs/prgm-012.ast
index bd980355..e44c738a 100644
--- a/asteroid/test-suites/ug-programs/prgm-012.ast
+++ b/asteroid/test-suites/ug-programs/prgm-012.ast
@@ -1,7 +1,7 @@
     load system io.
     load system math.
 
-    let a = [1 to 10] @map(lambda with x do return math @mod(x,2))
-                      @map(lambda with x do return 1 if x else -1).
+    let a = [1 to 10] @map (lambda with x do math @mod (x,2))
+                      @map (lambda with x do 1 if x else -1).
 
     io @println a.
diff --git a/asteroid/test-suites/ug-programs/prgm-013.ast b/asteroid/test-suites/ug-programs/prgm-013.ast
deleted file mode 100644
index 335fe853..00000000
--- a/asteroid/test-suites/ug-programs/prgm-013.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-    load system io.
-
-    -- build a 2-D array
-    let b = [[1,2,3],
-             [4,5,6],
-             [7,8,9]].
-
-    -- modify an element in the array
-    let b @1 @1 = 0.
-    io @println ("["+b@0+"\n "+b@1+"\n "+b@2+"]").
diff --git a/asteroid/test-suites/ug-programs/prgm-014.ast b/asteroid/test-suites/ug-programs/prgm-014.ast
index 06b1d6a9..53c8605d 100644
--- a/asteroid/test-suites/ug-programs/prgm-014.ast
+++ b/asteroid/test-suites/ug-programs/prgm-014.ast
@@ -1,3 +1,3 @@
     let a = (1,2,3).    -- construct tuple a
-    let b = a @1.       -- access the second element in tuple a
-    assert(b == 2).     -- assert that the value of the second element is correct
+    let b = a@1.        -- access the second element in tuple a, tuples are 0-indexed
+    assert (b == 2).    -- assert that the value of the second element is correct
diff --git a/asteroid/test-suites/ug-programs/prgm-015.ast b/asteroid/test-suites/ug-programs/prgm-015.ast
index f46f73c1..69ddbcc8 100644
--- a/asteroid/test-suites/ug-programs/prgm-015.ast
+++ b/asteroid/test-suites/ug-programs/prgm-015.ast
@@ -3,4 +3,4 @@
              ("d","e","f"),
              ("g","h","i")].
     -- Access an element in the nested structure.
-    assert(b @1 @1 == "e").
+    assert (b@0@1 == "b").
diff --git a/asteroid/test-suites/ug-programs/prgm-016.ast b/asteroid/test-suites/ug-programs/prgm-016.ast
index 0a6f25b9..d50f3e9e 100644
--- a/asteroid/test-suites/ug-programs/prgm-016.ast
+++ b/asteroid/test-suites/ug-programs/prgm-016.ast
@@ -3,7 +3,7 @@
     let b = ("a","b","c"). -- build a tuple
     
     try
-        let b @1 = "z". -- attempt to modify an element in the tuple
-    catch Exception(kind,message) do
+        let b@1 = "z". -- attempt to modify an element in the tuple
+    catch Exception (kind,message) do
         io @println (kind+": "+message).
     end.
diff --git a/asteroid/test-suites/ug-programs/prgm-017.ast b/asteroid/test-suites/ug-programs/prgm-017.ast
index 02d72732..e3683a34 100644
--- a/asteroid/test-suites/ug-programs/prgm-017.ast
+++ b/asteroid/test-suites/ug-programs/prgm-017.ast
@@ -8,15 +8,15 @@
 
     -- make a list of persons
     let people = [
-        -- use default constructors to construct Person instances
+        -- use default constructors to construct Person objects
         Person("George", 32, "man"),
         Person("Sophie", 46, "woman"),
         Person("Oliver", 21, "man")
     ].
 
     -- retrieve the second person on the list and use pattern
-    -- matching to extract member values
-    let Person(name,age,gender) = people @1.
+    -- matching on Person objects to extract member values
+    let Person(name,age,gender) = people@1.
 
     -- print out the member values
     io @println (name + " is " + age + " years old and is a " +  gender + ".").
diff --git a/asteroid/test-suites/ug-programs/prgm-017a.ast b/asteroid/test-suites/ug-programs/prgm-017a.ast
index 074d6751..d45d1d99 100644
--- a/asteroid/test-suites/ug-programs/prgm-017a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-017a.ast
@@ -4,6 +4,6 @@
         data b.
     end
 
-    let obj = A(1,2).       -- call constructor
-    assert( obj @a == 1 ).  -- access first data member
-    assert( obj @b == 2 ).  -- access second data member
+    let obj = A(1,2).     -- default constructor, a<-1, b<-2
+    assert (obj@a == 1).  -- access first data member
+    assert (obj@b == 2).  -- access second data member
diff --git a/asteroid/test-suites/ug-programs/prgm-018.ast b/asteroid/test-suites/ug-programs/prgm-018.ast
index ee65c533..b886c6b4 100644
--- a/asteroid/test-suites/ug-programs/prgm-018.ast
+++ b/asteroid/test-suites/ug-programs/prgm-018.ast
@@ -1,4 +1,11 @@
-    load system io.
+    structure Person with
+        data name.
+        data age.
+        data profession.
+    end
 
-    let [x,2,y] = [1+0,1+1,1+2].
-    io @println (x,y).
+    let joe = Person("Joe", 32, "Cook").  -- construct an object
+    let Person(n,a,p) = joe.              -- pattern match object
+
+    assert (n=="Joe" and a==32 and p=="Cook").
+    
diff --git a/asteroid/test-suites/ug-programs/prgm-020.ast b/asteroid/test-suites/ug-programs/prgm-020.ast
index 8b0bba4b..6574914e 100644
--- a/asteroid/test-suites/ug-programs/prgm-020.ast
+++ b/asteroid/test-suites/ug-programs/prgm-020.ast
@@ -1,4 +1,4 @@
     load system io.
 
-    let t:(1,2) = (1,2).  -- using a named pattern on lhs
+    let t:(x,y) = (1,2).  -- using a named pattern on lhs
     io @println t.
diff --git a/asteroid/test-suites/ug-programs/prgm-021.ast b/asteroid/test-suites/ug-programs/prgm-021.ast
index 6410a980..6e678701 100644
--- a/asteroid/test-suites/ug-programs/prgm-021.ast
+++ b/asteroid/test-suites/ug-programs/prgm-021.ast
@@ -1,6 +1,5 @@
     load system io.
     load system math.
-    load system type.
 
     let x:%real = math @pi.
-    io @println (type @tostring (x,type @stringformat (4,2))).
+    io @println x.
diff --git a/asteroid/test-suites/ug-programs/prgm-023.ast b/asteroid/test-suites/ug-programs/prgm-023.ast
index dbccbe5f..52c58fa8 100644
--- a/asteroid/test-suites/ug-programs/prgm-023.ast
+++ b/asteroid/test-suites/ug-programs/prgm-023.ast
@@ -1,6 +1,9 @@
     load system io.
     load system util
 
-    for (ix,bird) in util @zip (["first","second","third"],["turkey","duck","chicken"]) do
+    let indexes = ["first","second","third"].
+    let birds = ["turkey","duck","chicken"].
+
+    for (ix,bird) in util @zip (indexes,birds) do
         io @println ("the "+ix+" bird is a "+bird).
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-025a.ast b/asteroid/test-suites/ug-programs/prgm-025a.ast
index 696076da..8081d86d 100644
--- a/asteroid/test-suites/ug-programs/prgm-025a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-025a.ast
@@ -1,7 +1,6 @@
-    function double
-        with i do -- pattern match the actual arg with i
-            return 2*i.
-        end
+    function double with i do -- pattern match the actual arg with i
+        return 2*i.
+    end
 
-    let d = double 2.  -- function call via juxtaposition
-    assert( d == 4 ).
+    let d = double 2.  -- function call via juxtaposition, no parentheses necessary
+    assert (d == 4).
diff --git a/asteroid/test-suites/ug-programs/prgm-025b.ast b/asteroid/test-suites/ug-programs/prgm-025b.ast
index 91649958..36057ff9 100644
--- a/asteroid/test-suites/ug-programs/prgm-025b.ast
+++ b/asteroid/test-suites/ug-programs/prgm-025b.ast
@@ -1,7 +1,6 @@
-    function reduce
-        with (a,b) do -- pattern match the actual argument
-            return a*b.
-        end
+    function reduce with (a,b) do -- pattern match the actual argument
+        return a*b.
+    end
 
     let r = reduce (2,4).  -- function call via juxtaposition
-    assert( r == 8 ).
+    assert (r == 8).
diff --git a/asteroid/test-suites/ug-programs/prgm-026.ast b/asteroid/test-suites/ug-programs/prgm-026.ast
index 1f1315a7..2961d6cb 100644
--- a/asteroid/test-suites/ug-programs/prgm-026.ast
+++ b/asteroid/test-suites/ug-programs/prgm-026.ast
@@ -11,9 +11,9 @@
 
             for e in rest do
                 if e < pivot do
-                    let less = less + [e].
+                    less @append e.
                 else
-                    let more = more + [e].
+                    more @append e.
                 end
             end
 
diff --git a/asteroid/test-suites/ug-programs/prgm-027.ast b/asteroid/test-suites/ug-programs/prgm-027.ast
index 57b2775f..ef7dd579 100644
--- a/asteroid/test-suites/ug-programs/prgm-027.ast
+++ b/asteroid/test-suites/ug-programs/prgm-027.ast
@@ -1,3 +1,3 @@
     load system io.
 
-    io @println ((lambda with n do return n+1) 1).
+    io @println ((lambda with n do n+1) 1).
diff --git a/asteroid/test-suites/ug-programs/prgm-030.ast b/asteroid/test-suites/ug-programs/prgm-030.ast
index e7a5681d..7c5cd29e 100644
--- a/asteroid/test-suites/ug-programs/prgm-030.ast
+++ b/asteroid/test-suites/ug-programs/prgm-030.ast
@@ -1,23 +1,20 @@
-    -- implements Peano addition on terms
-    load system io.
+    structure Node with -- internal tree node with a value
+        data value.
+        data left_child.
+        data right_child.
+    end
 
-    structure s with
-        data val.
-        end
+    structure Leaf with -- leaf node with a value
+        data value.
+    end
 
-    structure add with
-        data left.
-        data right.
-        end
+    -- traverse a tree and collect all the values in the tree in a list
+    function traverse
+        with Leaf(v) do
+            return [v].
+        with Node(v,l,r) do
+            return [v] + traverse l + traverse r.
+    end
 
-    function reduce
-        with add(x,0) do
-            return reduce(x).
-        with add(x,s(y))  do
-            return s(reduce(add(x,y))).
-        with term do
-            return term.
-        end
-
-    -- add 2 3
-    io @println (reduce(add(s(s(0)),s(s(s(0)))))).
+    let tree = Node(1,Leaf(2),Leaf(3)).
+    assert (traverse(tree) == [1,2,3]).
\ No newline at end of file
diff --git a/asteroid/test-suites/ug-programs/prgm-031.ast b/asteroid/test-suites/ug-programs/prgm-031.ast
index 287e7ec8..ee7e2fcb 100644
--- a/asteroid/test-suites/ug-programs/prgm-031.ast
+++ b/asteroid/test-suites/ug-programs/prgm-031.ast
@@ -3,10 +3,10 @@
     function factorial
         with 0 do
             return 1
-        with (n:%integer) if n > 0 do
+        with n if (n is %integer) and (n > 0) do
             return n * factorial (n-1).
-        with (n:%integer) if n < 0 do
+        with n if (n is %integer) and (n < 0) do
             throw Error("factorial is not defined for "+n).
-        end
+    end
 
     io @println ("The factorial of 3 is: " + factorial 3).
diff --git a/asteroid/test-suites/ug-programs/prgm-031a.ast b/asteroid/test-suites/ug-programs/prgm-031a.ast
new file mode 100644
index 00000000..6bc53b22
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-031a.ast
@@ -0,0 +1,12 @@
+    load system io.
+
+    function factorial
+        with 0 do
+            1
+        with (n:%integer) if n > 0 do
+            n * factorial (n-1).
+        with (n:%integer) if n < 0 do
+            throw Error("factorial is not defined for "+n).
+    end
+
+    io @println ("The factorial of 3 is: " + factorial 3).
diff --git a/asteroid/test-suites/ug-programs/prgm-032.ast b/asteroid/test-suites/ug-programs/prgm-032.ast
index 333784c4..303d5f04 100644
--- a/asteroid/test-suites/ug-programs/prgm-032.ast
+++ b/asteroid/test-suites/ug-programs/prgm-032.ast
@@ -3,16 +3,16 @@
     structure Person with
         data name.
         data age.
-        end
+    end
 
     -- define a list of persons
     let people = [
         Person("George", 32),
         Person("Sophie", 46),
         Person("Oliver", 21)
-        ].
+    ].
 
     -- print names that contain 'p'
-    for Person(name:".*p.*",_) in people do
+    for Person(name if name is ".*p.*",age) in people do
         io @println name.
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-033.ast b/asteroid/test-suites/ug-programs/prgm-033.ast
index 5ac29575..8e7f52d5 100644
--- a/asteroid/test-suites/ug-programs/prgm-033.ast
+++ b/asteroid/test-suites/ug-programs/prgm-033.ast
@@ -4,21 +4,21 @@
 
     structure Head with
         data val.
-        end
+    end
 
     structure Tail with
         data val.
-        end
+    end
 
     try
-        let i = random @random().
+        let i = random @random ().
         if i >= 0.5 do
-            throw Head(i).
+            throw Head i.
         else do
-            throw Tail(i).
+            throw Tail i.
         end
-    catch Head(v) do
-        io @println("you win with "+type @tostring(v,type @stringformat(4,2))).
-    catch Tail(v) do
-        io @println("you loose with "+type @tostring(v,type @stringformat(4,2))).
+    catch Head v do
+        io @println ("you win with "+type @tostring (v,type @stringformat (4,2))).
+    catch Tail v do
+        io @println ("you loose with "+type @tostring (v,type @stringformat (4,2))).
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-034.ast b/asteroid/test-suites/ug-programs/prgm-034.ast
index f04f9415..bf7d61d3 100644
--- a/asteroid/test-suites/ug-programs/prgm-034.ast
+++ b/asteroid/test-suites/ug-programs/prgm-034.ast
@@ -3,9 +3,8 @@
     structure Person with
         data name.
         data age.
-        data gender.
-        end
+    end
 
-    let scarlett = Person("Scarlett",28,"F").
+    let scarlett = Person("Scarlett",28).
     -- access the name field of the structure instance
-    io @println (scarlett @name).
+    io @println (scarlett@name).
diff --git a/asteroid/test-suites/ug-programs/prgm-035.ast b/asteroid/test-suites/ug-programs/prgm-035.ast
index 21776cd7..ddcec581 100644
--- a/asteroid/test-suites/ug-programs/prgm-035.ast
+++ b/asteroid/test-suites/ug-programs/prgm-035.ast
@@ -3,13 +3,11 @@
     structure Person with
         data name.
         data age.
-        data gender.
-        function hello
-            with none do
-                io @println ("Hello, my name is "+this @name).
-            end
+        function hello with none do
+            io @println ("Hello, my name is "+this@name).
         end
+    end
 
-    let scarlett = Person("Scarlett",28,"F").
+    let scarlett = Person("Scarlett",28).
     -- call the member function
-    scarlett @hello().
+    scarlett @hello ().
diff --git a/asteroid/test-suites/ug-programs/prgm-036.ast b/asteroid/test-suites/ug-programs/prgm-036.ast
index 8cfa4f16..5a3a2f16 100644
--- a/asteroid/test-suites/ug-programs/prgm-036.ast
+++ b/asteroid/test-suites/ug-programs/prgm-036.ast
@@ -3,14 +3,12 @@
     structure Person with
         data name.
         -- the function is defined in the middle of the data fields
-        function hello
-            with none do
-                io @println ("Hello, my name is "+this @name).
-            end
-        data age.
-        data gender.
+        function hello with none do
+            io @println ("Hello, my name is "+this@name).
         end
+        data age.
+    end
 
     -- pattern matching ignores function definitions
-    let Person(name,age,_) = Person("Scarlett",28,"F").
+    let Person(name,age) = Person("Scarlett",28).
     io @println (name+" is "+age+" years old").
diff --git a/asteroid/test-suites/ug-programs/prgm-037.ast b/asteroid/test-suites/ug-programs/prgm-037.ast
index 2dcf0e58..7784cc17 100644
--- a/asteroid/test-suites/ug-programs/prgm-037.ast
+++ b/asteroid/test-suites/ug-programs/prgm-037.ast
@@ -1,33 +1,22 @@
-    load system io.
-    load system type.
-
-    structure Dog with
-
-       data name.
-       data tricks.
-
-       function add_trick
-          with new_trick:%string do
-             this @tricks @append new_trick.
-          end
-
-       function __init__
-          with name:%string do
-             let this @name = name.
-             let this @tricks = [].
-          end
-
-    end
-
-    let fido = Dog "Fido".
-    fido @add_trick "play dead".
-    fido @add_trick "fetch".
-
-    let buddy = Dog "Buddy".
-    buddy @add_trick "sit stay".
-    buddy @add_trick "roll over".
-
-    -- print out all the dogs that know how to fetch
-    for (Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*") in [fido,buddy] do
-        io @println (name+" knows how to fetch").
-    end
+   load system io.
+   load system type.
+
+   structure Dog with
+      data name.
+      data tricks.
+      function __init__ with (name:%string, tricks:%list) do -- constructor
+         let this@name = name.
+         let this@tricks = tricks.
+      end
+   end
+
+   let fido = Dog("Fido",["play dead","fetch"]).
+   let buddy = Dog("Buddy",["sit stay","roll over"]).
+   let bella = Dog("Bella",["roll over","fetch"]).
+
+   let dogs = [fido,buddy,bella].
+
+   -- print out all the dogs that know how to fetch
+   for (Dog(name,tricks) if type @tostring tricks is ".*fetch.*") in dogs do
+      io @println (name+" knows how to fetch").
+   end
diff --git a/asteroid/test-suites/ug-programs/prgm-038.ast b/asteroid/test-suites/ug-programs/prgm-038.ast
index 89b17f1c..3728c0fc 100644
--- a/asteroid/test-suites/ug-programs/prgm-038.ast
+++ b/asteroid/test-suites/ug-programs/prgm-038.ast
@@ -5,7 +5,7 @@
             return n * fact (n-1).
         with (n:%integer) if n < 0 do
             throw Error("fact undefined for negative values").
-        end
+    end
 
     function sign
         with 0 do
@@ -14,4 +14,4 @@
             return 1.
         with (n:%integer) if n < 0 do
             return -1.
-        end
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-039.ast b/asteroid/test-suites/ug-programs/prgm-039.ast
index 252bfd21..0ea8da05 100644
--- a/asteroid/test-suites/ug-programs/prgm-039.ast
+++ b/asteroid/test-suites/ug-programs/prgm-039.ast
@@ -8,13 +8,13 @@
             return n * fact (n-1).
         with *NEG_INT do
             throw Error("fact undefined for negative values").
-        end
+    end
 
     function sign
         with 0 do
-                return 1
-            with *POS_INT do
-                return 1.
-            with *NEG_INT do
-                return -1.
-            end
+            return 1
+        with *POS_INT do
+            return 1.
+        with *NEG_INT do
+            return -1.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-043a.ast b/asteroid/test-suites/ug-programs/prgm-043a.ast
new file mode 100644
index 00000000..20c09726
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-043a.ast
@@ -0,0 +1,13 @@
+   -- declare a pattern that matches scalar values
+   let Scalar = pattern %[p if (p is %integer) or (p is %real)]%.
+
+   -- declare a pattern that matches pairs of scalars
+   let Pair = pattern %[(x:*Scalar,y:*Scalar)]%.
+
+   -- compute the dot product of two pairs of scalars
+   function dot2d 
+      with (*Pair bind [x as a1, y as a2], *Pair bind [x as b1, y as b2]) do
+         a1*b1 + a2*b2
+   end
+
+   assert(dot2d((1,0),(0,1)) == 0).
\ No newline at end of file