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

Issue:
make files modules
make files modules along the lines of Python modules and get rid of the 'module' statement.

This simplifies the 'load' statement semantics: now loading a file simply means loading a module and does not rely on the fact whether the file implements a 'module' statement or not.

The good news, from a user perspective of the current Asteroid modules nothing changes!
implemented runtime stack commands in MAD

Experimental
This PR represents a major code renovation of the 'unify' function to make it
1. more efficient
2. more understandable and robust

There were two major casualties due to this renovation,
1. The capabilities of the redundancy checker have been reduced to checking simple structural patterns. This comes from the insight that first-class patterns almost always involve conditional patterns and therefore potentially arbitrary computations that cannot be checked.  Therefore support for first-class patterns was dropped from the redundancy checker.  Also, head-tail checking was dropped due to code complexity/utility issues.
2. The 'explicit' mode of the debugger has been eliminated.  The main issue was that this mode exposed internal implementation details of structures such as objects and tuples that a debugger user should never see.  To the debugger unification now appears as an atomic step.
evaluate pattern expression upon construction
We need to evaluate pattern expressions upon construction so that the following code works,
```
function combine with (p1:%pattern, p2:%pattern) do
   pattern (*p1, *p2).
end

let pos_int = pattern (x:%integer) if x > 0.
let neg_int = pattern (y:%integer) if x < 0.

let pair = combine(pos_int,neg_int).
assert ((1,-1) is pattern *pair).
```

match expressions
Add match expressions a la Rust to Asteroid,
```
let p = (1,2).
let x = (match p
   with (x,y) if x > y do
      "GT"
   with (x,y) if x < y do
      "LT"
   with _ do
      throw Error("not a valid tuple"))
assert(x =="LT").
```
Since it is an expression it does not have an `end` keyword, the `end` keyword would look really weird in expressions, but therefore this expression is syntactically very ambiguous similarly to lambda functions and needs to be surrounded by parens in most cases.
make files modules
make files modules along the lines of Python modules and get rid of the 'module' statement.

This simplifies the 'load' statement semantics: now loading a file simply means loading a module and does not rely on the fact whether the file implements a 'module' statement or not.

The good news, from a user perspective of the current Asteroid modules nothing changes!
make files modules
make files modules along the lines of Python modules and get rid of the 'module' statement.

This simplifies the 'load' statement semantics: now loading a file simply means loading a module and does not rely on the fact whether the file implements a 'module' statement or not.

The good news, from a user perspective of the current Asteroid modules nothing changes!
review documentation for 2.0.1 release
We need to review the documentation for the 2.0.1 release.  In particular the User Guide.  A lot of terminology has been refined and that should be reflected in the documentation.
review documentation for 2.0.1 release
We need to review the documentation for the 2.0.1 release.  In particular the User Guide.  A lot of terminology has been refined and that should be reflected in the documentation.
review documentation for 2.0.1 release
We need to review the documentation for the 2.0.1 release.  In particular the User Guide.  A lot of terminology has been refined and that should be reflected in the documentation.
first class patterns need static scoping
First-class patterns arefirst-class patterns need static scoping so that patterns like,
```
load system math.
let even = pattern %[(x:%integer) if math@mod(x,2) == 0]%.
```
work anywhere.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/generate_documentation.yml b/.github/workflows/generate_documentation.yml
index 82c49287..0c774804 100644
--- a/.github/workflows/generate_documentation.yml
+++ b/.github/workflows/generate_documentation.yml
@@ -1,12 +1,16 @@
+# this script throws an error when trying to commit the generated documentation
+# right now set to 'none' branch that will not match anything in this repo
 name: Documentation Generation
 on:
     pull_request:
         branches:
-           - 'dev-**'
+           #- 'dev-**'
+           - 'none'
 
     push:
         branches:
-            - 'dev-**'
+            #- 'dev-**'
+            - 'none'
 env:
     PYTHONPATH: ${{ github.workspace }}
 jobs:
diff --git a/README.md b/README.md
index a9be6f31..235cf1f6 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,31 @@ 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 2.0.1
+
+* We now support the ASTEROIDPATH environment variable which is expected to have a colon seperated list of directories to search for user defined modules.
+
+* The logical operators 'and' and 'or' are now evaluated in short-circuit fashion.
+
+* Files loaded with the 'load' statement are now considered modules and work similarly to Python modules.
+
+* Added the 'toplevel' function which returns true if control is in the module originally loaded by the interpreter.
+
+* Added the match statement similar to the match statement in Python.
+
+* No longer supports type hierarchies for the primitive types.  The functions in the 'type' module are now considered builtins. The 'type' module itself has been eliminated.
+
+* The Minimal Asteroid Debugger (MAD) replaces ADB in this release.
+
+* The shorthand conditional pattern can now be applied to arbitrary patterns. E.g. The pattern 
+  ```
+  (a,b,c):(%integer,%integer,%integer)
+  ```
+  constrains the triple `(a,b,c)` to be a triple of integers.  The above shorthand conditional pattern is equivalent to the conditional pattern,
+  ```
+  (a,b,c) if (a,b,c) is (%integer,%integer,%integer)
+  ```
+  
 ## New in Release 1.1.4
 
 * Allows pattern constraint operator to map certain variables that a pattern 
diff --git a/asteroid/__init__.py b/asteroid/__init__.py
index b14400fd..3810bd63 100755
--- a/asteroid/__init__.py
+++ b/asteroid/__init__.py
@@ -12,44 +12,45 @@
 from asteroid.interp import interp
 from asteroid.repl import repl
 from asteroid.version import VERSION
-from asteroid.adb import adb
+from asteroid.mad import MAD
 
 def display_help():
-    print("** Asteroid Version {} **".format(VERSION))
+    print("Asteroid {}".format(VERSION))
     print("(c) University of Rhode Island")
-    print("usage: asteroid [-<switch>] <input file>")
+    print("usage: asteroid [<switch>] <input file>")
     print("")
-    print("command line flags:")
+    print("command line switches:")
+    print(" -d             run program through debugger")
+    print(" -e             show Python exceptions")
+    print(" -F             functional mode")
+    print(" -h, --help     display help")
+    print(" -p             disable prologue")
+    print(" -r             disable redundant pattern detector")
     print(" -s             enable symbol table dump")
     print(" -t             AST dump")
     print(" -v, --version  version")
     print(" -w             disable tree walk")
+    print(" -W             disable warnings")
     print(" -z             generate pstats")
-    print(" -p             disable prologue")
-    print(" -h, --help     display help")
-    print(" -r             disable redundant pattern detector")
-    print(" -e             show Python exceptions")
-    print(" -F             functional mode")
-    print(" -g, --adb      run program through debugger")
 
 def main():
-    # defaults for the flags - when the flag is set on the command line
+    # defaults for the switches or flags - when the flag is set on the command line
     # it simply toggles the default value in this table.
     flags = {
+        '-d' : False,    # Short debugger flag
+        '-e' : False,  # show full exceptions
+        '-F' : False,  # functional mode
+        '--help' : False,  # display help flag
+        '-h' : False,  # display help flag
+        '-p' : True,   # prologue flag
+        '-r' : True,   # redundant pattern dectector
         '-s' : False,  # symbol table dump flag
         '-t' : False,  # AST dump flag
         '--version' : False,  # version flag
         '-v' : False,  # version flag
         '-w' : True,   # tree walk flag
+        '-W' : True,   # warnings
         '-z' : False,  # generate pstats flag
-        '-p' : True,   # prologue flag
-        '--help' : False,  # display help flag
-        '-h' : False,  # display help flag
-        '-r' : True,   # redundant pattern dectector
-        '-e' : False,  # show full exceptions
-        '-F' : False,  # functional mode
-        '--adb': False, # debugger flag
-        '-g': False    # Short debugger flag
     }
 
     flag_names = list(flags.keys())
@@ -80,10 +81,10 @@ def main():
         sys.exit(0)
 
     if flags['--version'] or flags['-v']:
-        print("** Asteroid Version {} **".format(VERSION))
+        print("Asteroid {}".format(VERSION))
         sys.exit(0)
 
-    debug_flag = flags['--adb'] or flags['-g']
+    debug_flag = flags['-d']
 
     # determine if we are starting in interactive mode or not
     # Note: first non-switch argument has to be an Asteroid source file
@@ -108,22 +109,11 @@ def main():
         print("error: unknown file '{}'".format(input_file))
         sys.exit(1)
 
-    # 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'],
-            'prologue': flags['-p'],
-            'functional_mode': flags['-F'],
-            'exceptions': flags['-e'],
-        }
-        db.run(input_file)
-        sys.exit(0)
+        db = MAD()
+    else:
+        db = None
 
     # execute the interpreter
     f = open(input_file, 'r')
@@ -134,18 +124,21 @@ def main():
     interp_object = \
     '''interp(program=input_stream,
            program_name = input_file,
-           tree_dump=flags['-t'],
-           do_walk=flags['-w'],
-           symtab_dump=flags['-s'],
            exceptions=flags['-e'],
-           redundancy=flags['-r'],
+           functional_mode=flags['-F'],
            prologue=flags['-p'],
-           functional_mode=flags['-F'])'''
+           redundancy=flags['-r'],
+           symtab_dump=flags['-s'],
+           tree_dump=flags['-t'],
+           do_walk=flags['-w'],
+           warnings=flags['-W'],
+           debugger=db
+           )'''
 
     if flags['-z']:
         # generates pstats into the file 'pstats'
         # see https://docs.python.org/3/library/profile.html
-        cProfile.run(interp_object, 'pstats')
+        cProfile.runctx(interp_object, globals(), locals(), filename='pstats')
     else:
         exec(interp_object)
 
diff --git a/asteroid/adb/__init__.py b/asteroid/adb/__init__.py
deleted file mode 100644
index e69de29b..00000000
diff --git a/asteroid/adb/adb.py b/asteroid/adb/adb.py
deleted file mode 100644
index b1e78783..00000000
--- a/asteroid/adb/adb.py
+++ /dev/null
@@ -1,978 +0,0 @@
-"""
-The Asteroid Debugger
-"""
-
-from asteroid.repl import repl
-from asteroid.adb.command import DebuggerParser
-from asteroid.interp import interp, load_prologue
-from asteroid.state import dump_trace, state
-from asteroid.support import term2string, map2boolean
-
-from asteroid.walk import function_return_value
-
-# Used for showing full exceptions
-import traceback
-
-class ADB:
-    """
-    This class implements the behavior and state managment for the
-    asteroid debugger
-    """
-    def __init__(self):
-        # List of options to run the interpreter under
-        self.interp_options = {
-            'redundancy': False,
-            'prologue': True,
-            'functional_mode': False,
-            'exceptions': False,
-        }
-
-        # Table of breakpoints and conditions
-        self.breakpoints = {}
-
-        #############################
-        # Execution control table
-        self.exc = {
-            'CONTINUE': False,
-            'STEP':     False,
-            'RETURN':   False,
-            'UNTIL':    False,
-            'NEXT':     True,
-        }
-
-        #############################
-        # A copy of the most recent return value
-        self.retval = None
-
-        #############################
-        # If our program is executing at the top level
-        self.top_level = True
-
-        # Explicit mode is the verbose mode where more information
-        # about the computation is detailed
-        self.explicit_enabled = False
-
-        #############################
-        # The current level of tabulation
-        self.tab_level = 0
-
-        #############################
-        # Debugger's internal lineinfo
-        # We maintain this separate from the state's lineinfo
-        # to help keep track of the currently executing line.
-        # Between things like imports or function calls to
-        # other modules, the state's lineinfo can fall slightly
-        # behind.
-        self.lineinfo = None
-
-        #############################
-        # Name-content file dictionary
-        self.program_text = {}
-
-        # The original filename
-        self.filename = None
-
-        #############################
-        # The parser for incoming commands
-        self.dbgp = DebuggerParser()
-
-        #############################
-        # Dictionary of macros
-        self.macros = {
-            # A clear screen macro
-            'clear': [('EVAL', 'escape "import os;os.system(\'clear\') "')]
-        }
-
-        #############################
-        # The queue of commands being executed
-        self.command_queue = []
-
-        #############################
-        # Stack frame information
-        self.config_offset = 0          # The index of the current config we're using
-        self.original_config = None     # The original config we started with (before moving between frames)
-        self.original_lineinfo = None   # The original lineinfo we started with (before moving between frames)
-
-        #############################
-        # Old lineinfo to be stored when until command is used
-        self.old_lineinfo = None
-
-    def reset_defaults(self):
-        """
-        Resets the debugger's default config
-        """
-        # Reset defaults
-        self.exc['CONTINUE'] = False
-        self.exc['STEP'] = False
-        self.exc['NEXT'] = True
-        self.exc['RETURN'] = False
-        self.exc['UNTIL'] = False
-
-        self.top_level = True
-        self.explicit_enabled = False
-        self.old_lineinfo = None
-
-    def reset_config(self):
-        """
-        Reset the symbol table's original config
-        """
-        if self.original_config:
-            state.symbol_table.set_config(self.original_config)
-            self.original_config = None
-            self.original_lineinfo = None
-            self.config_offset = 0
-
-    def make_tab_level(self):
-        """
-        Make the tab level for nested messaging
-        """
-        return self.tab_level*"|   "
-
-    def message_explicit(self, message, level = "primary"):
-        """
-        Sends a message in explicit mode
-
-        Explicit messaging only gets shown in two scenarios if explicit mode is enabled:
-            1. The user is NOT continuing and they're in the same file
-            2. The user is stepping through a function call
-        """
-        if self.explicit_enabled and \
-            (not self.exc['CONTINUE'] and self.lineinfo[0] == self.filename) or \
-            (self.exc['STEP']):
-
-            tl = self.make_tab_level()
-            if level == 'primary':
-                print("{}- {}".format(tl, message))
-            elif level == 'secondary':
-                print("{} ** {}".format(tl, message))
-            else:
-                print("{}  * {}".format(tl, message))
-
-    def message(self, message):
-        """
-        print a formatted message through the debugger
-        """
-        print("----- {} -----".format(message))
-
-    def handle_run_exception(self, e):
-        # Handle exceptions from the interpretation session
-        (module, lineno) = state.lineinfo
-        print("\nERROR: {}: {}: {}".format(module, lineno, e))
-        if self.interp_options['exceptions']:
-            print(traceback.format_exc())
-
-        # Set out lineinfo here to be sure that the file is in
-        # our program_text dictionary
-        self.set_lineinfo( (module, lineno) )
-
-        print("    ==>> " + self.program_text[module][lineno - 1].strip())
-        print()
-        self.message("Error occured, session will restart after commands")
-
-    def run(self, filename):
-        """
-        This function runs the given filename through the asteroid debugger
-        """
-
-        # Set our primary filename
-        self.filename = filename
-
-        # Open and read the file
-        f = open(filename, 'r')
-        input_stream = f.read()
-        f.close()
-
-        from asteroid.adb.version import VERSION
-        print("Welcome to ADB version {}.".format(VERSION))
-        print("(c) University of Rhode Island")
-        print("Type \"help\" for help.")
-        print("Type \"quit\" to leave the debugger.")
-        print("ADB is experimental and under active development")
-        print("Report any suggestions or bugs to https://github.com/asteroid-lang/")
-        print()
-
-        # Main debug loop
-        while True:
-            try:
-                # Reset the debugging status
-                import asteroid.walk
-                asteroid.walk.debugging = False
-
-                # Reinitialize the state and reload the prologue
-                state.initialize()
-
-                # Load the prologue if user requests
-                if self.interp_options['prologue']:
-                    load_prologue()
-
-                # Interpret our file
-                interp(input_stream,
-                    program_name = filename,
-
-                    # If we wanted to load the prologue, we already would have
-                    prologue=False,
-
-                    # Don't re-initialize the state
-                    initialize_state=False,
-
-                    # User options
-                    redundancy=self.interp_options['redundancy'],
-                    functional_mode=self.interp_options['functional_mode'],
-
-                    # Set exceptions so we can wrap them
-                    exceptions=True,
-                    debugger=self)
-
-                asteroid.walk.debugging = True
-
-                # Give us one final tick before restarting
-                # This gives us one last tick before EOF is reached
-                self.set_lineinfo( (self.filename, len(self.program_text[self.filename])) )
-                self.tick()
-                print()
-
-                # Restart session
-                self.message("End of file reached, restarting session")
-                self.reset_defaults()
-
-            except (EOFError, KeyboardInterrupt):
-                break;
-
-            except Exception as e:
-                # Handle the runtime exception
-                self.handle_run_exception(e)
-
-                # One last tick so the user can play around in
-                # the error scope/line
-                try:
-                    self.tick()
-                except (EOFError, KeyboardInterrupt):
-                    # If the user tries to exit with CTRL+C/D, exit
-                    break;
-
-                # Reset the debugger's default state
-                self.message("Session restarted")
-                self.reset_defaults()
-                continue
-
-    def has_breakpoint_here(self):
-        """
-        Check if the user has set a breakpoint at the current line
-        """
-        # Condition 1: Is there a breakpoint at this line?
-        breakpoint_at_line = (self.lineinfo[1] in self.breakpoints)
-
-        # Condition 2, are we in the original file (TODO: Expand this)
-        in_same_file = (self.lineinfo[0] == self.filename)
-
-        # Preliminary check
-        if not (breakpoint_at_line and in_same_file):
-            return False
-
-        # Get the break condition for this breakpoint
-        break_cond = self.breakpoints.get(self.lineinfo[1])
-
-        # Assume the break condition is true until proven false
-        break_cond_met = True
-
-        # If there's a break condition
-        if break_cond:
-
-            # Save our old lineinfo/explicit state
-            old_lineinfo = self.lineinfo
-            old_explicit = self.explicit_enabled
-            self.explicit_enabled = False
-
-            old_state_lineinfo = state.lineinfo
-
-            import asteroid.walk
-            asteroid.walk.debugging = False
-            # interpret the break conition
-            try:
-                interp(break_cond,
-                    program_name = "<COMMAND>",
-                    prologue=False,
-                    initialize_state=False,
-
-                    redundancy=self.interp_options['redundancy'],
-                    functional_mode=self.interp_options['functional_mode'],
-
-                    debugger=None,
-                    exceptions=True
-            )
-
-            # If an error occurs in the break condition, show the error
-            except Exception as e:
-                print("Breakpoint condition error: {}".format(e))
-
-            # Else, get the value of the expression calculated.
-            else:
-                break_cond_met = map2boolean(function_return_value[-1])[1]
-
-            asteroid.walk.debugging = True
-
-            # Reenable everything
-            self.explicit_enabled = old_explicit
-            self.set_lineinfo(old_lineinfo)
-
-            # Reset the state's internal lineinfo
-            state.lineinfo = old_state_lineinfo
-
-        # If there's no break cond, then by default it is true
-        else:
-            break_cond_met = True
-
-        # Return the state of the break condition
-        return break_cond_met
-
-    def set_top_level(self, tl):
-        """
-        Set our flag that tells the debugger if it's at the top level of a program or not
-
-        We use this to get the `next` command working
-        """
-        self.top_level = tl
-
-    def set_lineinfo(self, lineinfo):
-        """
-        Set the debugger's internal lineinfo
-        """
-        from os.path import exists
-
-        self.lineinfo = lineinfo
-
-        # If the program text isn't already loaded and the file actually exists
-        # (isn't a stream line <input> or <command>)
-        if lineinfo[0][0] == '<' and lineinfo[0][-1] == '>':
-            return
-
-        if not self.program_text.get(lineinfo[0]) and exists(lineinfo[0]):
-            with open(lineinfo[0], "r") as f:
-                self.program_text[lineinfo[0]] = f.readlines()
-
-            # Always add an EOF specifier
-            self.program_text[lineinfo[0]].append("[EOF]\n")
-
-    def print_given_line(self, lineinfo, header=True):
-        """
-        print the current line nicely
-        """
-
-        # Get the program text
-        pt = self.program_text[lineinfo[0]]
-
-        # Isolate the current line
-        prog_line = pt[lineinfo[1] - 1][:-1].strip()
-
-        outline = ""
-
-        # The current call stack
-        call_stack = [s[-1] for s in state.trace_stack][1:]
-
-        if header:
-            # Format it nicely
-            outline =  ("[" + lineinfo[0] + " (" + str(lineinfo[1]) + ")]")
-
-            # Display the call stack
-            if len(call_stack) > 0 and (self.config_offset < len(call_stack)):
-                outline += " ("
-
-                offset = -self.config_offset - 1
-                for c in call_stack[:offset]:
-                    outline += c + "->"
-                outline += call_stack[offset] + ")"
-
-        # If the line is empty don't bother showing it
-        if prog_line != "" and header:
-            outline += ("\n-->> " + prog_line)
-        elif prog_line != "" and not header:
-            outline += ("    " + prog_line)
-        print(outline)
-
-    def list_breakpoints(self):
-        """
-        List the breakpoints and their conditions
-        """
-        self.message("Breakpoints")
-
-        # For eaxch breakpoint
-        for b in self.breakpoints:
-
-            # Get the condition
-            c = self.breakpoints[b]
-
-            # print the breakpoint number and condition if available
-            print("* {} {}".format(
-                b, ": " + c if c else ''))
-
-    def list_program(self, relative=False):
-        """
-        List the program contents
-        """
-        self.message("Program Listing")
-
-        # Get the program text for the current file
-        pt = self.program_text[self.lineinfo[0]]
-
-        # Length around the current line to display if relative
-        length = 4
-
-        # Relative offset for the file listing
-        start = 0
-
-        if relative:
-            lineno = self.lineinfo[1]
-
-            # Compute the start and end of relative listing
-            start = (lineno - length) if lineno >= length else 0
-            end = lineno + length if lineno < len(pt) - 2 else len(pt)
-
-            # Set the program text to the slice between start and end
-            pt = pt[start:end]
-
-        # Start of line is blank by default
-        start_of_line = "  "
-
-        # GO through each line in the program text
-        for ix, l in enumerate(pt):
-
-            # If the offset line number is in breakpoints
-            if ix+1+start in self.breakpoints:
-                # Set the special start of line
-                start_of_line = "* "
-
-            # If the offset linenumber is the current line
-            if self.lineinfo[1] == ix+1+start:
-                # Set the special start of line
-                start_of_line = "> "
-
-            # print the given line
-            print(start_of_line, ix+1+start, l[:-1])
-
-            # Reset the start of line
-            start_of_line = "  "
-
-    def set_exc(self, step=False, cont=False, next=False):
-        """
-        Set the debugger movement configuration
-        """
-        self.exc['STEP'] = step
-        self.exc['CONTINUE'] = cont
-        self.exc['NEXT'] = next
-
-    def display_macros(self):
-        """
-        Displays all currently active macros
-        """
-        for m in self.macros:
-            print("* {} : {}".format(
-                m, self.macro_to_string(m)))
-
-    def macro_to_string(self, macro_name):
-        contents = self.macros[macro_name]
-
-        outstr = ""
-
-        for cmd in contents:
-            if cmd == ('MACRO',):                      outstr += 'macro'
-            elif cmd[0] == 'EVAL':                     outstr += 'eval("{}")'.format(cmd[1])
-            elif cmd == ('BANG', ):                    outstr += '!'
-            elif cmd[0] == 'HELP':                     outstr += 'help {}'.format(cmd[1])
-            elif cmd == ('UP',):                       outstr += '<'
-            elif cmd == ('DOWN',):                     outstr += '>'
-            elif cmd == ('WHERE',):                    outstr += 'where'
-            elif cmd == ('LONGLIST',):                 outstr += 'longlist'
-            elif cmd == ('LIST',):                     outstr += 'list'
-            elif cmd == ('RETVAL',):                   outstr += '__retval__'
-            elif cmd[0] ==  'UNTIL':                   outstr += 'until{}'.format((" "+cmd[1]) if cmd[1] else "")
-            elif cmd == ('RETURN',):                   outstr += 'return'
-            elif cmd[0] == 'EXPLICIT':                 outstr += 'explicit {}'.format(
-                cmd[1] if cmd[1] else "")
-            elif cmd == ('STEP', ):                    outstr += 'step'
-            elif cmd == ('CONTINUE', ):                outstr += 'continue'
-            elif cmd == ('NEXT', ):                    outstr += 'next'
-
-            # TODO: (OWM) print out conditions for these
-            elif cmd[0] == 'BREAK':                    outstr += "break {}".format(
-                ' '.join([str(n) for n in cmd[1]]))
-            elif cmd == 'DELETE':                      outstr += "delete {}".format(
-                ' '.join([str(n) for n in cmd[1]]))
-
-            elif cmd[0] == 'NAME':                     outstr += str(cmd[1])
-            elif cmd == ('QUIT', ):                    outstr += 'quit'
-            elif cmd == ('NOOP', ):                    outstr += 'noop'
-
-            outstr += '; '
-
-        return outstr
-
-    def set_new_macro(self, name, l):
-        """
-        Sets a new macro
-        """
-        self.macros[name] = l
-        self.message("Macro {}".format(name))
-
-    def do_eval_command(self, value):
-        """
-        Evaluates a given value
-        """
-        # Save the old lineinfo and explicit state
-        old_lineinfo = self.lineinfo
-        old_explicit = self.explicit_enabled
-        old_state_lineinfo = state.lineinfo
-
-        # Set the explicit state to false
-        self.explicit_enabled = False
-
-        # Set the debugging flag to false
-        import asteroid.walk
-        asteroid.walk.debugging = False
-
-        # Run the asteroid code
-        try:
-            interp(value,
-                program_name = "<EVAL>",
-                prologue=False,
-                initialize_state=False,
-
-                redundancy=self.interp_options['redundancy'],
-                functional_mode=self.interp_options['functional_mode'],
-
-                debugger=None,
-                exceptions=True)
-
-        except Exception as e:
-            print("Command error: {}".format(e))
-
-        else:
-            # Check if there's actually a return value in
-            # the register
-            if function_return_value[-1]:
-                # Get the last return value (type, value)
-                ret = function_return_value[-1]
-
-                # If it isn't none, print out the value
-                if ret[1] != None:
-                    print(term2string(ret))
-
-        # Reset debugging state
-        asteroid.walk.debugging = True
-
-        # Reset explicit mode and lineinfo
-        self.explicit_enabled = old_explicit
-        self.set_lineinfo(old_lineinfo)
-
-        # Reset the state's internal lineinfo
-        state.lineinfo = old_state_lineinfo
-
-    def do_repl_command(self):
-        """
-        Runs a repl in the current stack frame
-        """
-        # Keep our lineinfo, and explicit state. Disable explicit state
-        old_lineinfo = self.lineinfo
-        old_explicit = self.explicit_enabled
-        self.explicit_enabled = False
-
-        # Save the *state*'s old lineinfo
-        old_state_lineinfo = state.lineinfo
-
-        # Turn off debugging
-        import asteroid.walk
-        asteroid.walk.debugging = False
-
-        # Run the repl
-        repl(
-            new=False,
-            prologue=False,
-            redundancy=self.interp_options['redundancy'],
-            functional_mode=self.interp_options['functional_mode']
-            )
-
-        # Restore debugging flag and give state its old lineinfo
-        asteroid.walk.debugging = True
-        state.lineinfo = old_state_lineinfo
-
-        # Reenable explicit and reset lineinfo
-        self.explicit_enabled = old_explicit
-        self.set_lineinfo(old_lineinfo)
-
-    def do_help_command(self, name):
-        """
-        Lists help options and prints help info
-        """
-        from asteroid.adb.help import command_description_table
-
-        # If a command name is supplied
-        if name:
-            # Get the command description for that name
-            help_msg = command_description_table.get(name)
-            # if there's a description, print the info
-            if help_msg:
-                self.message("Info for {}".format(name))
-                print(help_msg)
-            # Else, print an error
-            else:
-                self.message("Unknown command for help: {}".format(
-                    name
-                ))
-
-        # If no command is supplied, then just print out the default command menu
-        else:
-            print("Type 'help NAME' to get help for a command")
-            print("Available commands:")
-            for c in command_description_table:
-                print("* {}".format(c))
-
-    def move_frame_up(self):
-        """
-        Moves the context to the next higher stack frame
-        """
-        if self.config_offset == len(state.trace_stack) - 1:
-            self.message("At topmost frame")
-        else:
-            self.config_offset += 1
-            # We're at the bottommost frame and want to go up, but need
-            # to save the original config
-            if self.original_config == None:
-                self.original_config = state.symbol_table.get_config()
-                self.original_lineinfo = state.lineinfo
-
-            # Get the associated module and line for this frame
-            (module, line, _) = state.trace_stack[-self.config_offset]
-
-            # Set the config
-            state.symbol_table.set_config(
-                state.symbol_table.saved_configs[-self.config_offset]
-            )
-
-            self.set_lineinfo( (module, line) )
-            self.print_given_line(self.lineinfo)
-
-    def move_frame_down(self):
-        """
-        Moves the context to the next lowest stack frame
-        """
-        stack = state.trace_stack
-
-        if self.config_offset == 0:
-            self.message("At bottommost frame")
-
-        else:
-            self.config_offset -= 1
-            bottom_level = (self.config_offset == 0)
-
-            if bottom_level:
-                if self.original_config:
-                    state.symbol_table.set_config(self.original_config)
-                    self.set_lineinfo( (self.original_lineinfo) )
-            else:
-                # We're at the bottommost frame and want to go up, but need
-                # to save the original config
-                (module, line, _) = state.trace_stack[-self.config_offset]
-
-                state.symbol_table.set_config(
-                    state.symbol_table.saved_configs[-self.config_offset])
-
-                self.set_lineinfo( (module, line) )
-
-            self.print_given_line(self.lineinfo)
-
-    # This function is super spaghetti but the behavior is complicated
-    def do_where_command(self):
-        """
-        Displays a list of available frames and shows the user
-        where they currently are
-        """
-        self.message("Available Frames")
-        stack_copy = state.trace_stack[1:].copy()
-
-        # The call stack
-        call_stack = [s[-1] for s in state.trace_stack][1:]
-
-        # If we're inside of some scope, append a "bottom" to the stack copy
-        if len(call_stack) > 0:
-            stack_copy.append((*state.lineinfo, "<bottom>"))
-
-        start_of_line = "*"
-
-        # If we're just at the top level, just note that
-        if len(stack_copy) == 0:
-            print("-> <toplevel>")
-
-        # For each list in the stack
-        for i, s in enumerate(stack_copy):
-            # There's only the top level
-            if len(stack_copy) == 1:
-                start_of_line = ">"
-
-            # We're at the bottom of the stack
-            elif (self.config_offset == 0 and len(stack_copy) > 0) and i == len(stack_copy) - 1:
-                start_of_line = ">"
-
-            # We're traversing frames
-            elif self.config_offset != 0:
-                if i == (len(stack_copy) - self.config_offset) - 1:
-                    start_of_line = ">"
-
-            # Bottom of stack
-            if s[2] == "<bottom>":
-                print("{} {} {}".format(start_of_line, s[0], s[1]))
-                self.print_given_line( (s[0], s[1]) , header=False)
-
-            else:
-                print("{} {} {} (Calling {})".format(start_of_line, s[0], s[1], s[2]))
-                self.print_given_line( (s[0], s[1]) , header=False)
-            start_of_line = "*"
-
-    def walk_command(self, cmd):
-        """
-        Walk a given command
-        """
-        # Loop sentinel value
-        # This is returned as True ~iff~ a movement command is
-        # executed
-        exit_loop = False
-
-        # Match command to behavior
-        if cmd[0] == 'MACRO' and len(cmd) == 1: self.display_macros()
-
-        elif cmd[0] == 'MACRO':
-            name, l = cmd[1], cmd[2]
-            self.set_new_macro(name, l)
-
-        elif cmd[0] == 'EVAL':
-            value = cmd[1]
-            self.do_eval_command(value)
-
-        elif cmd[0] == 'HELP':
-            name = cmd[1]
-            self.do_help_command(name)
-
-        elif cmd == ('BANG', ):            self.do_repl_command()
-        elif cmd == ('UP',):               self.move_frame_up()
-        elif cmd == ('DOWN',):             self.move_frame_down()
-        elif cmd == ('WHERE',):            self.do_where_command()
-        elif cmd == ('LONGLIST',):         self.list_program()
-        elif cmd == ('LIST',):             self.list_program(relative=True)
-
-        elif cmd == ('RETVAL',):
-            if self.retval:
-                self.message("Most recent return value: {}".format(self.retval))
-            else:
-                self.message("No values have been returned yet")
-        elif cmd[0] == 'UNTIL':
-            lineno = cmd[1]
-
-            self.exc['UNTIL'] = True
-            if lineno:
-                self.old_lineinfo = (self.lineinfo[0], int(lineno) - 1)
-            else:
-                self.old_lineinfo = self.lineinfo
-
-            self.set_exc()
-            exit_loop = True
-        elif cmd == ('RETURN',):
-            if len(state.trace_stack) == 1:
-                self.message("Cannot continue to return on the top level")
-            else:
-                self.exc['RETURN'] = True
-                self.set_exc(step=False, next=False, cont=False)
-                exit_loop = True
-
-        elif cmd[0] == 'EXPLICIT':
-            set_explicit = cmd[1]
-
-            if set_explicit == False:
-                self.explicit_enabled = False
-            elif set_explicit == True:
-                self.explicit_enabled = True
-            else:
-                self.explicit_enabled = not self.explicit_enabled
-        # Step
-        elif cmd == ('STEP', ):
-            self.set_exc(step=True)
-            exit_loop = True
-        # Continue
-        elif cmd == ('CONTINUE', ):
-            self.set_exc(cont=True)
-            exit_loop = True
-        # Next
-        elif cmd == ('NEXT', ):
-            self.set_exc(next=True)
-            exit_loop = True
-        # Break
-        elif cmd[0] == 'BREAK':
-            nums, conds = cmd[1], cmd[2]
-            if nums:
-                for ix, n in enumerate(nums):
-                    self.breakpoints[n] = conds[ix]
-            else:
-                self.list_breakpoints()
-        # Delete
-        elif cmd[0] == 'DELETE':
-            nums = cmd[1]
-            for n in nums:
-                self.breakpoints.pop(n)
-        # Macro/Unknown
-        elif cmd[0] == 'NAME':
-            v = cmd[1]
-            # If the command name is in macros
-            if v in self.macros:
-                self.command_queue += self.macros[v]
-            else:
-                raise ValueError("Unknown macro: {}".format(str(v)))
-        # Quit command
-        elif cmd == ('QUIT', ):
-            raise SystemExit()
-
-        elif cmd == ('NOOP', ):
-            pass
-
-        else:
-            raise ValueError("Unknown command: {}".format(str(cmd)))
-
-        return exit_loop
-
-    def command_loop(self, in_pattern=False):
-        """
-        Main command loop for ADB
-        """
-        exit_loop = False
-
-        # Main command loop
-        while not exit_loop:
-
-            # in_pattern in explicit mode is a flag for currently stepping
-            # through a pattern
-            if in_pattern:
-                query_symbol = "[Pattern] "
-            else:
-                # Format the input symbol to reflect explicitness
-                query_symbol = "(ADB)[e] " if self.explicit_enabled else "(ADB) "
-
-            # Get the command
-            cmd = input(query_symbol)
-
-            # Try to walk the command
-            try:
-                # Parse the command
-                (LINE, node) = self.dbgp.parse(cmd)
-
-                # Add the new commands to the queue
-                self.command_queue += node
-
-                # Add the list of commands to the queue
-                while self.command_queue:
-                    # Walk the command and get the exit state
-                    exit_loop = self.walk_command(self.command_queue.pop(0))
-
-                    # Exit if necessary
-                    if exit_loop:
-                        self.reset_config()
-                        break;
-
-            # Intercept debugger command errors
-            except ValueError as e:
-                print("Debugger command error [{}]".format(e))
-
-            # If we are in a pattern but disabled explicit mode, that's
-            # grounds for loop exiting
-            if in_pattern and not self.explicit_enabled:
-                exit_loop = True
-
-        return exit_loop
-
-    def tick(self):
-        """
-        "Tick" the debugger. This refers to hitting some point where the user
-        has decided they would like the debugger to come back to life and entering
-        the command selection phase.
-
-        The debugger uses a queue to store working commands. This allows for more
-        complex command execution
-        """
-        exit_loop = False
-
-        # Clear out the command queue
-        while self.command_queue:
-            exit_loop = self.walk_command(self.command_queue.pop(0))
-            if exit_loop:
-                if self.original_config:
-                    self.reset_config()
-                return
-
-        # print the current line with lineinfo
-        self.print_given_line(self.lineinfo)
-
-        # Main command loop
-        self.command_loop()
-
-        # Reset the tab level
-        self.tab_level = 0
-
-    def notify_explicit(self):
-        """
-        Run a command loop ~iff~ we're in explicit mode
-        """
-        if self.exc['STEP'] and self.explicit_enabled:
-            self.command_loop(in_pattern=True)
-
-    def notify(self, at_return=False):
-        """
-        Notify the debugger that a potential tick-point has
-        occured and do the necessary checks to see if we can
-        tick here.
-
-        This function is a little complicated because the
-        behavior is complicated.
-
-        Explicit mode is a mode in which extra steps in
-        computations are revealed to the user
-        """
-
-        # If we have a breakpoint here and we're not trying to go
-        # to the next top level statement, then tick
-        if self.has_breakpoint_here() and not self.exc['NEXT']:
-            self.message("Breakpoint")
-            self.tick()
-
-        # If we're at the top level and we're not continuing
-        # to the next breakpoint, and we're going to the next statement
-        # do a tick
-        elif self.top_level and self.exc['NEXT'] and not self.exc['CONTINUE']:
-            if self.has_breakpoint_here():
-                self.message("Breakpoint")
-            self.tick()
-
-        # If we're at a return statement and we're continuing onto a return
-        # we need to first send the message that we've arrived and then
-        # set the execution control such that when the return statement
-        # is walked, we always catch it
-        elif at_return and self.exc['RETURN']:
-            self.exc['RETURN'] = False
-            self.message('Return reached!')
-
-            # This is set to step so that we always hit the impending
-            # return statement
-            self.set_exc(step=True)
-
-        # If the until command is active, we basically continue until we're
-        # at a greater linenumber within the file.
-        elif self.exc['UNTIL']:
-            # Grab the old and current lineinfo
-            (old_file_name, old_lineno) = self.old_lineinfo
-            (cur_file_name, cur_lineno) = self.lineinfo
-
-            # Compare them
-            if (old_file_name == cur_file_name) and (cur_lineno > old_lineno):
-                self.exc['UNTIL'] = False
-                self.tick()
-
-        # Otherwhise, if we're stepping through the program, always tick
-        elif self.exc['STEP']:
-            self.tick()
-
-        # Reset the top level so that nested statements don't come in
-        self.set_top_level(False)
diff --git a/asteroid/adb/command.py b/asteroid/adb/command.py
deleted file mode 100644
index 05dcd52c..00000000
--- a/asteroid/adb/command.py
+++ /dev/null
@@ -1,257 +0,0 @@
-import re
-
-class Token:
-    def __init__(self,type,value):
-        self.type = type
-        self.value = value
-
-    def __str__(self):
-        return 'Token({},{})'.format(self.type,self.value)
-
-class DebuggerLexer:
-    def __init__(self, input_string):
-        self.token_specs = [
-        #   type:          value:
-            ('STRING',     r'"(\\"|\\.|[^"])*"'),
-            
-            ('NEXT',        r'\bnext\b|\bn\b'),
-            ('STEP',        r'\bstep\b|\bs\b'),
-            ('CONTINUE',    r'\bcontinue\b|\bcont\b|\bc\b'),
-            ('RETURN',      r'\breturn\b|\bret\b|\br\b'),
-            ('UNTIL',       r'\buntil\b|\bu\b'),
-
-            ('EVAL',        r'\beval\b'),
-            ('BANG',        r'!'),
-
-            ('BREAK',       r'\bbreak\b|\bb\b'),
-            ('DELETE',      r'\bdelete\b|\bdel\b|\bd\b'),
-
-            ('MACRO',       r'\bmacro\b'),
-            ('LIST',        r'\blist\b|\bl\b'),
-            ('LONGLIST',    r'\blonglist\b|\bll\b'),
-
-            ('RETVAL',      r'\b__retval__\b|\b_\b'),
-            
-            ('EXPLICIT',    r'\bexplicit\b|\be\b'),
-            ('ON',          r'\bon\b'),
-            ('OFF',         r'\boff\b'),
-
-            ('HELP',        r'\bh\b|\bhelp\b'),
-            ('WHERE',       r'\bwhere\b|\bw\b'),
-            ('UP',          r'\<'),
-            ('DOWN',        r'\>'),
-
-            ('IF',          r'\bif\b'),
-
-            ('NUM',         r'[+-]?([0-9]*[.])?[0-9]+'),
-            ('EQUAL',       r'='),
-            ('SEMI',        r';'),
-            ('COMMA',       r','),
-            ('LPAREN',      r'\('),
-            ('RPAREN',      r'\)'),
-
-            ('QUIT',        r'\bquit\b|\bq\b'),
-
-            ('NAME',        r'[a-zA-Z_\$][a-zA-Z0-9_\$]*'),
-            ('WHITESPACE',  r'[ \t\n]+'),
-            ('UNKNOWN',     r'.')
-        ]
-
-        # used for sanity checking in lexer.
-        self.token_types = set(type for (type,_) in self.token_specs)
-        self.tokens = self.tokenize(input_string)
-        # the following is always valid because we will always have
-        # at least the EOF token on the tokens list.
-        self.curr_token_ix = 0
-
-    def pointer(self):
-        return self.tokens[self.curr_token_ix]
-
-    def next(self):
-        if not self.end_of_file():
-            self.curr_token_ix += 1
-        return self.pointer()
-
-    def match(self, token_type):
-        if token_type == self.pointer().type:
-            tk = self.pointer()
-            self.next()
-            return tk
-        elif token_type not in self.token_types:
-            raise ValueError("unknown token type '{}'".format(token_type))
-        else:
-            raise ValueError('unexpected token {} while parsing, expected {}'
-                              .format(self.pointer().type, token_type))
-
-    def end_of_file(self):
-        if self.pointer().type == 'EOF':
-            return True
-        else:
-            return False
-
-    def tokenize(self, code):
-        tokens = []
-        re_list = ['(?P<{}>{})'.format(type,re) for (type,re) in self.token_specs]
-        combined_re = '|'.join(re_list)
-        match_object_list = list(re.finditer(combined_re, code))
-        for mo in match_object_list:
-            type = mo.lastgroup
-            value = mo.group()
-
-            if type == 'WHITESPACE':
-                continue #ignore
-            elif type == 'STRING':
-                tokens.append(Token('STRING', value.encode('utf-8')
-                                                   .decode('unicode-escape')[1:-1]))
-            elif type == 'UNKNOWN':
-                raise ValueError("unexpected character '{}'".format(value))
-            else: 
-                tokens.append(Token(type, value))
-        tokens.append(Token('EOF', '\eof'))
-        return tokens
-
-class DebuggerParser:
-    def __init__(self):
-        self.dlx = None
-
-    def parse(self, input_string):
-        self.dlx = DebuggerLexer(input_string)
-        return self.line()
-
-    def line(self):
-        if self.dlx.pointer().type == 'MACRO':
-            return self.macro()
-
-        else:
-            cmds = [self.command()]
-            while self.dlx.pointer().type in ['SEMI']:
-                self.dlx.match('SEMI')
-
-                if self.dlx.pointer().type == 'EOF':
-                    break
-
-                cmds += [self.command()]
-
-            return ('LINE', cmds)
-    
-    def macro(self):
-        self.dlx.match('MACRO')
-
-        if self.dlx.pointer().type == 'EOF':
-            return ('LINE', [('MACRO',)])
-
-        else:
-            name = self.dlx.match('NAME')
-            self.dlx.match('EQUAL')
-
-            l = self.line()
-
-            return ('LINE', [('MACRO', name.value, l[1])] )
-
-    def eval_cmd(self):
-        self.dlx.match("EVAL")
-        self.dlx.match('LPAREN')
-        code = self.dlx.match('STRING')
-        self.dlx.match('RPAREN')
-        
-        return ('EVAL', code.value)
-    
-    def break_cmd(self):
-        self.dlx.match('BREAK')
-        nums = []
-        conds = []
-        first = True
-
-        while self.dlx.pointer().type == 'NUM':
-            if first:
-                first = False
-            
-            nums.append(self.dlx.match('NUM').value)
-
-            if self.dlx.pointer().type == 'IF':
-                self.dlx.match('IF')
-                self.dlx.match('EVAL')
-                self.dlx.match('LPAREN')
-                code = self.dlx.match('STRING')
-                self.dlx.match('RPAREN')
-                conds.append(code.value)
-            else:
-                conds.append(None)
-
-            if not first:
-                if self.dlx.pointer().type == 'COMMA':
-                    self.dlx.match('COMMA')
-                    continue
-                elif self.dlx.pointer().type == 'EOF':
-                    self.dlx.match('EOF')
-                    break
-
-        return ('BREAK', list(map(int, nums)), conds)
-
-    def delete_cmd(self):
-        self.dlx.match('DELETE')
-        nums = [self.dlx.match('NUM').value]
-        
-        while self.dlx.pointer().type == 'NUM':
-            nums.append(self.dlx.match('NUM').value)
-        
-        return ('DELETE', list(map(int, nums)))
-
-
-    def help_cmd(self):
-        self.dlx.match('HELP')
-        
-        n = None
-        if self.dlx.pointer().type != 'EOF':
-            n = self.dlx.pointer().value
-            self.dlx.next()
-        
-        return ('HELP', n)
-
-    def explicit_cmd(self):
-        self.dlx.match('EXPLICIT')
-
-        set_exp = None
-        if self.dlx.pointer().type in ['ON', 'OFF']:
-            set_exp = (self.dlx.pointer().type == 'ON')
-            self.dlx.next()
-        
-        return ('EXPLICIT', set_exp)
-
-    def until_cmd(self):
-        self.dlx.match('UNTIL')
-        
-        n = None
-        if self.dlx.pointer().type == 'NUM':
-            n = self.dlx.pointer().value
-            self.dlx.next()
-        
-        return ('UNTIL', n)
-
-    def command(self):
-        t = self.dlx.pointer().type
-        
-        if t ==  'EVAL':     return self.eval_cmd()
-        elif t ==  'BREAK':    return self.break_cmd()
-        elif t ==  'DELETE':   return self.delete_cmd()
-        elif t ==  'HELP':     return self.help_cmd()
-        elif t ==  'EXPLICIT': return self.explicit_cmd()
-        elif t ==  'UNTIL':    return self.until_cmd()
-        
-        elif t in ['BANG', 'LONGLIST', 'LIST', 'QUIT', 'RETURN', 'RETVAL',
-             'STEP', 'CONTINUE', 'NEXT', 'UP', 'DOWN', 'WHERE']:
-            t = self.dlx.pointer().type
-            self.dlx.match(t)
-            return (t,)
-        
-        elif t ==  'NAME':
-            n = self.dlx.match('NAME').value
-            return ('NAME', n)
-        
-        elif t in  ['EOF', 'SEMI']:
-            return ('NOOP',)
-        
-        else:
-            raise ValueError("Unknown command: {}".format(
-                str(self.dlx.pointer().value)
-            ))
\ No newline at end of file
diff --git a/asteroid/adb/help.py b/asteroid/adb/help.py
deleted file mode 100644
index bd42f574..00000000
--- a/asteroid/adb/help.py
+++ /dev/null
@@ -1,97 +0,0 @@
-command_description_table = {
-    'macro':        """macro (name) = (command list)
-    Define a macro with name "name" and a list of commands.
-
-    Typing solely "macro" will list off the macros currently enabled
-    Example:
-        macro see_x = continue; explicit; n; p x;
-    """,
-    
-    'step':         """[s]tep
-    Step to the next executing line
-    """,
-
-    'until':        """[u]ntil ?lineno
-    Without a given line number, continue execution until a line that is greater than the current
-    one is reached.
-
-    With a line number, continue execution until a line that is greater than or equal to that one
-    is reached.
-
-    In both cases, stop when the current frame returns.
-    """,
-    
-    'continue':     """[[c]ont]inue
-    Continue to the next breakpoint
-    """,
-    
-    'next':         """[n]ext
-    Go to the next top level statement
-    """,
-    
-    'break':        """[b]reak (linenum (if eval("command")))
-    Set a breakpoint at linenum. If you supply a command, the breakpoint
-    becomes conditional
-    """,
-
-    'eval' :     """eval("command")
-    Execute asteroid code
-    Example:
-        eval("let x = 10. io@println(\\"10\\")")
-
-    -- Print out the contents of variable x
-        eval("x")
-    """,
-    
-    'delete':       """[[d]el]ete (linenum)
-    Delete the breakpoint at linenum
-    """,
-    
-    '!':            """!
-    Start a REPL session
-    """,
-    
-    'longlist':     """[ll] longlist
-    List the contents of the entire program
-    """,
-    
-    'list':         """[l]ist
-    List the contents of the program around the current line
-    """,
-
-    'retval':       """[[r]et]val
-    Print the most recent return value
-    """,
-    
-    '>':            """>
-    Move down one frame
-    """,
-
-    '<':            """<
-    Move up one frame
-    """,
-
-    'where':        """[w]here
-    Lists the currently available stack frames and shows the user
-    the currently active one.
-    """,
-
-    'quit':         """[q]uit
-    Exit ADB
-    """,
-    
-    'explicit':     """[e]xplicit (on|off)?
-    Toggle explicit mode or set explicit mode to a specific state.
-
-    For more information about explicit mode, refer to "ADB in action".
-
-    Example:
-        explicit    -- Toggles explicit mode
-        explicit on -- Turns explicit mode on
-        explcit off -- Turns explicit mode off
-    """,
-    
-    'help':         """[h]elp ?(name)
-    Get help for a command
-    """
-}
diff --git a/asteroid/adb/version.py b/asteroid/adb/version.py
deleted file mode 100644
index a96ce905..00000000
--- a/asteroid/adb/version.py
+++ /dev/null
@@ -1,1 +0,0 @@
-VERSION = "1.0"
\ No newline at end of file
diff --git a/asteroid/frontend.py b/asteroid/frontend.py
index 423c706c..0341d44e 100644
--- a/asteroid/frontend.py
+++ b/asteroid/frontend.py
@@ -46,7 +46,7 @@ def dbg_print(string):
 
 exp_lookahead = {
     'PATTERN',
-    'LCONSTRAINT',} | primary_lookahead
+    'LSCOPE',} | primary_lookahead
 
 exp_lookahead_no_ops = exp_lookahead - ops
 
@@ -63,6 +63,8 @@ def dbg_print(string):
     'LET',
     'LOAD',
     'LOOP',
+    'MATCH',
+    'MODULE',
     'REPEAT',
     'RETURN',
     'STRUCTURE',
@@ -103,7 +105,7 @@ def parse(self, input):
     #   stmt_list
     def prog(self):
         dbg_print("parsing PROG")
-        sl = self.stmt_list()
+        sl = ('stmt-list', self.stmt_list())
         if not self.lexer.EOF():
             raise SyntaxError("expected 'EOF' found {}." \
                               .format(token_lookup(self.lexer.peek().type)))
@@ -118,29 +120,10 @@ def stmt_list(self):
         dbg_print("parsing STMT_LIST")
 
         sl = []
-        while self.stmt_coming_up():
+        while self.lexer.peek().type in stmt_lookahead:
             sl += [('lineinfo', state.lineinfo)]
-
-            # Get the statment
-            stmt = self.stmt()
-
-            # This set of conditionals gives us the behavior we want
-            # wrt implicit return values. There's only one situation
-            # in which we want to set the return value. That is when
-            # a top level expression is the last in a stmt_list
-
-            # If there's a statement coming up or the current statement
-            # is not a top level expression, just append the statement
-            if self.stmt_coming_up() or stmt[0] != 'top-level-exp':
-                sl += [stmt]
-
-            # Otherwhise, if there's no statement coming up and the
-            # last statement was a top level expression, set the
-            # ret val
-            else:
-                sl += [('clear-ret-val',)]
-                sl += [('set-ret-val', stmt)]             
-
+            sl += [('clear-ret-val',)]
+            sl += [self.stmt()]
         return ('list', sl)
 
     ###########################################################################################
@@ -150,7 +133,7 @@ def stmt_list(self):
     #
     # stmt
     #    : '.' // NOOP
-    #    | LOAD SYSTEM? (STRING | ID) '.'?
+    #    | LOAD SYSTEM? (STRING | ID) (AS ID)? '.'?
     #    | GLOBAL id_list '.'?
     #    | ASSERT exp '.'?
     #    | STRUCTURE ID WITH struct_stmts END
@@ -160,6 +143,7 @@ def stmt_list(self):
     #    | WHILE exp DO stmt_list END
     #    | REPEAT (DO?) stmt_list UNTIL exp '.'?
     #    | BREAK
+    #    | MATCH exp (WITH pattern DO stmt_list)* END
     #    | IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE (DO?) stmt_list)? END
     #    | RETURN exp? '.'?
     #    | TRY stmt_list (CATCH pattern DO stmt_list)+ END
@@ -182,22 +166,24 @@ def stmt(self):
             # allow module names without quotes
             if self.lexer.peek().type in ['STRING', 'ID']:
                 str_tok = self.lexer.match(self.lexer.peek().type)
+                name_tok = None
             elif self.lexer.peek().type == 'EOF':
                 raise ExpectationError(expected="valid module name", found='EOF' )
             else:
                 raise SyntaxError("invalid module name '{}'"
                                   .format(self.lexer.peek().value))
+            # look for the 'as' modifier
+            if self.lexer.peek().type == 'AS':
+                self.lexer.match('AS')
+                name_tok = self.lexer.match('ID')
             self.lexer.match_optional('DOT')
 
             raw_pp = PurePath(str_tok.value)
-            module_name = raw_pp.stem
-
-            # if module is on the list of modules then we have loaded
-            # it already -- ignore -- continue parsing the program file
-            if module_name in state.modules:
-                # lhh
-                # print("Ignoring module {}".format(module_name))
-                return self.stmt_list()
+            base_name = raw_pp.stem
+            if name_tok:
+                module_name = name_tok.value
+            else:
+                module_name = base_name
 
             # search for module file:
             # 0. raw module name - could be an absolute path
@@ -209,12 +195,19 @@ def stmt(self):
             if not sys_flag:
                 search_list.append(str_tok.value)
                 search_list.append(str_tok.value + asteroid_file_suffix)
-                search_list.append(os.path.join(os.getcwd(), module_name))
-                search_list.append(os.path.join(os.getcwd(), module_name + asteroid_file_suffix))
-                search_list.append(os.path.join(os.getcwd(), 'modules', module_name))
-                search_list.append(os.path.join(os.getcwd(), 'modules', module_name + asteroid_file_suffix))
-            search_list.append(os.path.join(os.path.split(os.path.abspath(__file__))[0], 'modules', module_name))
-            search_list.append(os.path.join(os.path.split(os.path.abspath(__file__))[0], 'modules', module_name + asteroid_file_suffix))
+                search_list.append(os.path.join(os.getcwd(), base_name))
+                search_list.append(os.path.join(os.getcwd(), base_name + asteroid_file_suffix))
+                search_list.append(os.path.join(os.getcwd(), 'modules', base_name))
+                search_list.append(os.path.join(os.getcwd(), 'modules', base_name + asteroid_file_suffix))
+                # check the ASTEROIDPATH variable
+                env_val = os.getenv('ASTEROIDPATH')
+                if env_val:
+                    path_list = env_val.split(':')
+                    for p in path_list:
+                        search_list.append(p+'/'+base_name+asteroid_file_suffix)
+
+            search_list.append(os.path.join(os.path.split(os.path.abspath(__file__))[0], 'modules', base_name))
+            search_list.append(os.path.join(os.path.split(os.path.abspath(__file__))[0], 'modules', base_name + asteroid_file_suffix))
 
             file_found = False
 
@@ -237,16 +230,15 @@ def stmt(self):
 
             old_lineinfo = state.lineinfo
             with open(ast_module_file) as f:
-                #state.modules.append(module_name)
-                state.modules.append(ast_module_file)
                 data = f.read()
-
                 # Give the absolute path to the parser
                 fparser = Parser(str(ast_module_path))
-                (STMT_LIST, fstmts) = fparser.parse(data)
+                fstmts = fparser.parse(data)
             
             state.lineinfo = old_lineinfo
-            return ('import_stmt', fstmts)
+            return ('load-stmt', 
+                    ('module-def',
+                     ('id', module_name), fstmts))
 
         elif tt == 'GLOBAL':
             dbg_print("parsing GLOBAL")
@@ -255,13 +247,6 @@ def stmt(self):
             self.lexer.match_optional('DOT')
             return ('global', id_list)
 
-        elif tt == 'ASSERT':
-            dbg_print("parsing ASSERT")
-            self.lexer.match('ASSERT')
-            exp = self.exp()
-            self.lexer.match_optional('DOT')
-            return ('assert', exp)
-
         elif tt == 'FUNCTION':
             return self.function_def()
 
@@ -349,6 +334,32 @@ def stmt(self):
             self.lexer.match('BREAK')
             return ('break',)
 
+        elif tt == 'MATCH':
+            if self.functional_mode and not self.is_system_module():
+                raise SyntaxError("match statement is not supported in functional mode")
+            # we implement the match statement as a cascade of if-clauses
+            if_list = []
+            dbg_print("parsing MATCH")
+            self.lexer.match('MATCH')
+            temp = ('id', gettemp())
+            exp = self.exp()
+            while self.lexer.peek().type == 'WITH':
+                dbg_print("parsing WITH")
+                old_lineinfo = state.lineinfo
+                self.lexer.match('WITH')
+                pattern = self.pattern()
+                self.lexer.match('DO')
+                stmts = self.stmt_list()
+                if_list.append(('lineinfo',old_lineinfo))
+                if_list.append(
+                    ('if-clause', 
+                      ('cond', ('is', temp, pattern)), 
+                      ('stmt-list', stmts)))
+            self.lexer.match('END')
+            return ('match',
+                     ('unify', temp, exp), 
+                     ('if', ('list', if_list)))
+
         elif tt == 'IF':
             if self.functional_mode and not self.is_system_module():
                 raise SyntaxError("if statement is not supported in functional mode")
@@ -413,7 +424,7 @@ def stmt(self):
             pattern = self.pattern()
             self.lexer.match('DO')
             stmts = self.stmt_list()
-            catch_list.append(('catch', ('pattern', pattern), ('stmt-list', stmts)))
+            catch_list.append(('catch', ('catch-pattern', pattern), ('stmt-list', stmts)))
 
             while self.lexer.peek().type == 'CATCH':
                 dbg_print("parsing CATCH")
@@ -421,7 +432,7 @@ def stmt(self):
                 pattern = self.pattern()
                 self.lexer.match('DO')
                 stmts = self.stmt_list()
-                catch_list.append(('catch',('pattern', pattern), ('stmt-list', stmts)))
+                catch_list.append(('catch',('catch-pattern', pattern), ('stmt-list', stmts)))
 
             self.lexer.match('END')
             #self.lexer.match_optional('TRY')
@@ -440,7 +451,7 @@ def stmt(self):
         elif tt in exp_lookahead:
             v = self.exp()
             self.lexer.match_optional('DOT')
-            return ('top-level-exp', v)
+            return ('exp-stmt', ('set-ret-val', v))
 
         else:
             raise SyntaxError("syntax error at '{}'"
@@ -458,7 +469,8 @@ def function_def(self):
         #self.lexer.match('FUNCTION')
 
         # check if any useless patterns exist within the function
-        #lhh check_redundancy( body_list, id_tok )
+        #from asteroid.walk import check_redundancy
+        #check_redundancy( body_list, id_tok )
 
         # functions are function expressions bound to names
         return ('unify',
@@ -532,7 +544,7 @@ def id_list(self):
 
     ###########################################################################################
     # body_defs
-    #   : WITH pattern DO stmt_list (ORWITH pattern DO stmt_list)*
+    #   : WITH pattern DO stmt_list (WITH pattern DO stmt_list)*
     def body_defs(self):
         dbg_print("parsing BODY_DEFS")
 
@@ -545,11 +557,10 @@ def body_defs(self):
         self.lexer.match('DO')
         sl = self.stmt_list()
         body_list.append( ('lineinfo', cur_lineinfo) )
-        body_list.append(('body', ('pattern', p), ('stmt-list', sl)))
+        body_list.append(('body', ('body-pattern', p), ('stmt-list', sl)))
 
         while self.lexer.peek().type in ['ORWITH','WITH']:
             cur_lineinfo = state.lineinfo
-
             if self.lexer.peek().type == 'ORWITH':
                 warning("'orwith' has been deprecated, please replace with 'with'")
             self.lexer.match(self.lexer.peek().type)
@@ -557,7 +568,7 @@ def body_defs(self):
             self.lexer.match('DO')
             sl = self.stmt_list()
             body_list.append( ('lineinfo', cur_lineinfo) )
-            body_list.append(('body', ('pattern', p), ('stmt-list', sl)))
+            body_list.append(('body', ('body-pattern', p), ('stmt-list', sl)))
 
         return ('body-list', ('list', body_list))
 
@@ -582,15 +593,15 @@ def pattern(self):
             self.lexer.match_optional('WITH')
             v = self.exp()
             return ('pattern', v)
-        elif self.lexer.peek().type == 'LCONSTRAINT': #constraint-only pattern match
-            self.lexer.match('LCONSTRAINT')
+        elif self.lexer.peek().type == 'LSCOPE': # scoped pattern
+            self.lexer.match('LSCOPE')
             v = self.exp()
-            self.lexer.match('RCONSTRAINT')
+            self.lexer.match('RSCOPE')
             if self.lexer.peek().type == 'BIND':
                 bl = self.binding_list()            
-                return ('constraint', v, bl)
+                return ('scope', v, bl)
             else:
-                return ('constraint', v, ('nil',))
+                return ('scope', v, ('nil',))
         else:
             v = self.head_tail()
             return v
@@ -692,7 +703,7 @@ def compound(self):
 
     ###########################################################################################
     # NOTE: Builtin operators are mapped to 'apply' so that they don't have to be
-    #       special cased during pattern matching.  See operator_symbols above.
+    #       special cased during pattern matching.  See builtin in globals.
     ###########################################################################################
     # logic/relational/arithmetic operators with their precedence
     # logic_exp0
@@ -823,8 +834,6 @@ def call_or_index(self):
     #    | NOT call_or_index
     #    | MINUS call_or_index
     #    | PLUS call_or_index
-    #    | ESCAPE STRING
-    #    | EVAL exp
     #    | '(' tuple_stuff ')' /* tuple/parenthesized expr */
     #    | '[' list_stuff ']'  /* list or list access */
     #    | function_const
@@ -894,16 +903,6 @@ def primary(self):
             else:
                 return ('apply', ('id', '__uplus__'), v)
 
-        elif tt == 'ESCAPE':
-            self.lexer.match('ESCAPE')
-            str_tok = self.lexer.match('STRING')
-            return ('escape', str_tok.value)
-
-        elif tt == 'EVAL':
-            self.lexer.match('EVAL')
-            exp = self.primary()
-            return ('eval', exp)
-
         elif tt == 'LPAREN':
             # Parenthesized expressions have the following meaning:
             #       (A)    means a parenthesized value A
@@ -1039,8 +1038,3 @@ def function_const(self):
         body_list = self.body_defs()
 
         return ('function-exp', body_list)
-
-    ###########################################################################################
-    # Minor helper function
-    def stmt_coming_up(self):
-        return self.lexer.peek().type in stmt_lookahead
\ No newline at end of file
diff --git a/asteroid/globals.py b/asteroid/globals.py
index 98edc0bc..e70dfaa7 100644
--- a/asteroid/globals.py
+++ b/asteroid/globals.py
@@ -1,7 +1,7 @@
 ###########################################################################################
 # globals for Asteroid
 #
-# (c) Lutz Hamel, University of Rhode Island
+# (c) University of Rhode Island
 ###########################################################################################
 
 from asteroid.support import term2string #Used by redundantPatternFound exception
@@ -11,7 +11,10 @@
 asteroid_file_suffix = ".ast"
 
 ###########################################################################################
-# symbols for builtin operators.
+# symbols for builtin operators and functions. these operators and functions do not 
+# need/are not allowed to have a function local scope.  therefore they are implemented
+# here as builtins as part of the interpreter proper.  for other builtins that do 
+# not have this restriction see the prologue.
 # NOTE: if you add new builtins make sure to keep this table in sync.
 
 binary_operators = {
@@ -27,15 +30,22 @@
     '__lt__',
     '__ge__',
     '__gt__',
-    }
+}
 
 unary_operators = {
     '__uminus__',
     '__uplus__',
     '__not__',
+    'assert',
+    'escape',
+    'eval',
     }
 
-operator_symbols = binary_operators | unary_operators
+nullary_operators = {
+    'toplevel',
+}
+
+builtins = binary_operators | unary_operators | nullary_operators
 
 #########################################################################
 # Use the exception mechanism to return values from function calls
@@ -121,11 +131,9 @@ def __init__(self, pattern1, pattern2,function_name,location1,location2):
         if (location1 != None):
             self.file = location1[0]
         self.function = function_name
-        self.message = "Redundant Pattern Detected\n"
-        self.message += "\tFunction: " + self.function + " from file " + self.file
-        self.message += "\n\tPattern: " + term2string(self.pattern1) + " on line " + self.line1
-        self.message += "\n\twill consume all matches for"
-        self.message += "\n\tPattern: " + term2string(self.pattern2) + " on line " + self.line2
+        self.message = "redundant pattern detected in '{}': ".format(self.function)
+        self.message += "the pattern on line {} will consume all matches for pattern on line {}"\
+                            .format(self.line1,self.line2)
         super().__init__(self.message)
 
     def __str__(self):
@@ -141,7 +149,6 @@ def __str__(self):
     'where-list',
     'raw-to-list',
     'raw-where-list',
-    'if-exp',
     'foreign',
     'escape',
     'is',
@@ -169,4 +176,5 @@ def __str__(self):
 ###########################################################################################
 # list of structures that a pattern type-pattern will subsume/overlap
 
-pattern_subsumes = patterns - {'id'}
\ No newline at end of file
+pattern_subsumes = patterns - {'id'}
+
diff --git a/asteroid/grammar.txt b/asteroid/grammar.txt
index 0c540c7b..42215adc 100644
--- a/asteroid/grammar.txt
+++ b/asteroid/grammar.txt
@@ -1,16 +1,21 @@
-/**************************************************************************************
- Grammar for Asteroid written in EBNF/PEG format.
- (c) University of Rhode Island
-
- Notes:
- - We generate documentation directly from this grammar file.  In order to
-   be properly formatted in the target documentation please respect the
-   indentation given below.
- - 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 -- like the one you are reading right now...
- **************************************************************************************/
+
+#define NOTE(x)  
+
+  NOTE("
+  **************************************************************************************
+  Grammar for Asteroid written in EBNF/PEG format.
+  (c) University of Rhode Island
+
+  Notes:
+  - We generate documentation directly from this grammar file.  In order to
+    be properly formatted in the target documentation please respect the
+    indentation given below.
+  - Use C++ style comments for any comments that you DO want to be displayed
+    in the target documentation.
+  - Use the NOTE macro for any comments that you DO NOT want to be displayed
+    in the target documentation -- like the one you are reading right now...
+  **************************************************************************************
+  ")
   ////////////////////////////////////////////////////////////////////////////////////////
   // statements
 
@@ -22,15 +27,15 @@
 
   stmt
     : '.' // NOOP
-    | LOAD SYSTEM? (STRING | ID) '.'?
+    | LOAD SYSTEM? (STRING | ID) (AS ID)? '.'?
     | GLOBAL id_list '.'?
-    | ASSERT exp '.'?
     | STRUCTURE ID WITH struct_stmts END
     | LET pattern '=' exp '.'?
     | LOOP DO? stmt_list END
     | FOR pattern IN exp DO stmt_list END
     | WHILE exp DO stmt_list END
     | REPEAT DO? stmt_list UNTIL exp '.'?
+    | MATCH exp (WITH pattern DO stmt_list)* END
     | IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE DO? stmt_list)? END
     | TRY DO? stmt_list (CATCH pattern DO stmt_list)+ END
     | THROW exp '.'?
@@ -61,28 +66,27 @@
 
   ////////////////////////////////////////////////////////////////////////////////////////
   // expressions/patterns
-  /*
-   NOTE: There is no syntactic difference between a pattern
-   and an expression. We introduce the 'pattern' nonterminal
-   to highlight the SEMANTIC difference between patterns and
-   expressions.
-  */
+  NOTE("
+  There is no syntactic difference between a pattern and an expression. We introduce
+  the 'pattern' nonterminal to highlight the SEMANTIC difference between patterns and
+  expressions.
+  ")
   exp
     : pattern
 
   pattern
     : PATTERN WITH? exp
-    | '%[' exp ']%' binding_list?    /* constraint-only pattern match */
+    | '%[' exp ']%' binding_list?    NOTE(" scoped pattern  ")
     | head_tail
 
   head_tail
     : conditional ('|' exp)?
 
-  /*
-   conditional patterns are now supported via 'pattern if cond'
-   no else part. Since this overlaps with conditional expressions
-   we check for correct usage semantically.
-  */
+  NOTE("
+  conditional patterns are now supported via 'pattern if cond'
+  no else part. Since this overlaps with conditional expressions
+  we check for correct usage semantically.
+  ")
   conditional
     : compound (IF exp (ELSE exp)?)?
 
@@ -90,8 +94,8 @@
     : logic_exp0
         (
            (IS pattern) |
-           (IN exp) |               /* exp has to be a list */
-           (TO exp (STEP exp)?) |   /* list comprehension */
+           (IN exp) |               NOTE(" exp has to be a list ")
+           (TO exp (STEP exp)?) |   NOTE(" list comprehension ")
         )?
 
   logic_exp0
@@ -113,7 +117,7 @@
     : call_or_index (('*' | '/') call_or_index)*
 
   call_or_index
-    : primary (primary | '@' primary)* (':' pattern)?  /* named pattern when ': pattern' exists */
+    : primary (primary | '@' primary)* (':' pattern)?  NOTE(" conditional pattern when ': pattern' exists ")
 
   ////////////////////////////////////////////////////////////////////////////////////////
   // primary expressions/patterns
@@ -126,18 +130,16 @@
     | FALSE
     | NONE
     | ID
-    | '*' call_or_index  binding_list? /* pattern dereferencing */
+    | '*' call_or_index  binding_list? NOTE(" pattern dereferencing ")
     | NOT call_or_index
     | MINUS call_or_index
     | PLUS call_or_index
-    | ESCAPE STRING
-    | EVAL primary
-    | '(' tuple_stuff ')' /* tuple/parenthesized expr */
-    | '[' list_stuff ']'  /* list or list access */
+    | '(' tuple_stuff ')' NOTE(" tuple/parenthesized expr ")
+    | '[' list_stuff ']'  NOTE(" list or list access ")
     | function_const
     | TYPEMATCH           // TYPEMATCH == '%'<typename>
 
-/* Note: binding lists are only supported for constraint patterns */
+NOTE(" Note: binding lists are only supported for scoped patterns ")
 
   binding_list
     : BIND binding_list_suffix
diff --git a/asteroid/interp.py b/asteroid/interp.py
index f6d112a7..e677f9f1 100644
--- a/asteroid/interp.py
+++ b/asteroid/interp.py
@@ -11,7 +11,7 @@
 from asteroid.support import *
 from asteroid.frontend import Parser
 from asteroid.state import state, dump_trace
-from asteroid.walk import walk_program, debug_walk
+from asteroid.walk import walk
 
 # the prologue file is expected to be in the 'modules' folder
 prologue_name = 'prologue.ast'
@@ -26,22 +26,19 @@ def load_prologue():
 
     if os.path.isfile(module_path):
         prologue_file = module_path
-    
     elif os.path.isfile(working_path):
         prologue_file = working_path
-    
     else:
         raise ValueError("Asteroid prologue '{}' not found"
                         .format(prologue_file_base))
     
     with open(prologue_file) as f:
-        state.modules.append(prologue_name)
         data = f.read()
         pparser = Parser(prologue_file)
-        (LIST, pstmts) = pparser.parse(data)
+        pstmts = pparser.parse(data)
 
-    state.AST = ('list', pstmts)
-    walk_program(state.AST)
+    state.AST = pstmts
+    walk(state.AST)
     state.AST = None
 
 def interp(program,
@@ -54,6 +51,7 @@ def interp(program,
            prologue=True,
            debugger=None,
            functional_mode=False,
+           warnings=True,
            initialize_state = True
            ):
     '''
@@ -71,6 +69,7 @@ def interp(program,
       * prologue: a flag indicating whether the Asteroid prologue file should be loaded
       * functional_mode: if set then the Asteroid interpreter behaves like an interpreter
                          functional programming language.
+      * warnings: if set will display warnings
       * initialize_state: if set then the interpreter will (re)initialize its state.  
     '''
     try:
@@ -81,22 +80,31 @@ def interp(program,
         if prologue:
             load_prologue()
 
-        # initialize "check for useless clauses" flag
+        # initialize state flags
         state.eval_redundancy = redundancy
+        state.warning = warnings
 
         # build the AST
         parser = Parser(program_name, functional_mode)
-        (LIST, istmts) = parser.parse(program)
-        state.AST = ('list', istmts)
+        stmts = parser.parse(program)
+        state.AST = stmts
+        state.mainmodule = state.lineinfo[0]
 
         # walk the AST
         if tree_dump:
             dump_AST(state.AST)
+        if debugger:
+            state.debugger = debugger
+            (module,line) = state.lineinfo
+            state.lineinfo = (module,1)
+            debugger.start(state)
         if do_walk:
-            if debugger:
-                debug_walk(state.AST, debugger)
-            else:
-                walk_program(state.AST)
+            try:
+                walk(state.AST)
+                if debugger: debugger.stop()
+            except Exception as e:
+                if debugger: debugger.error(e)
+                raise e
         if symtab_dump:
             state.symbol_table.dump()
 
@@ -127,17 +135,17 @@ def interp(program,
             sys.exit(1)
 
     except  KeyboardInterrupt as e:
-        if debugger:
-            raise e
-
         dump_trace()
         print("error: keyboard interrupt")
         # needed for REPL
         if not exceptions:
             sys.exit(1)
 
-    except SystemExit:
-        exit(0)
+    except SystemExit as e:
+        # we simply pass along the exception
+        # this is just here in case in the future we need to 
+        # perform special handling
+        raise e
 
     except Exception as e:
         if exceptions: # rethrow the exception so that you can see the full backtrace
diff --git a/asteroid/lex.py b/asteroid/lex.py
index f5c0d293..ff53931e 100644
--- a/asteroid/lex.py
+++ b/asteroid/lex.py
@@ -14,7 +14,6 @@
 #   value:          type:
     'and'           : 'AND',
     'as'            : 'AS',
-    'assert'        : 'ASSERT',
     'bind'          : 'BIND',
     'break'         : 'BREAK',
     'catch'         : 'CATCH',
@@ -23,8 +22,6 @@
     'elif'          : 'ELIF',
     'else'          : 'ELSE',
     'end'           : 'END',
-    'escape'        : 'ESCAPE',
-    'eval'          : 'EVAL',
     'for'           : 'FOR',
     'from'          : 'FROM',
     'function'      : 'FUNCTION',
@@ -36,13 +33,13 @@
     'let'           : 'LET',
     'load'          : 'LOAD',
     'loop'          : 'LOOP',
+    'match'         : 'MATCH',
     'not'           : 'NOT',
     'or'            : 'OR',
-    'orwith'        : 'ORWITH',
     'pattern'       : 'PATTERN',
     'repeat'        : 'REPEAT',
     'return'        : 'RETURN',
-    'step'        : 'STEP',
+    'step'          : 'STEP',
     'structure'     : 'STRUCTURE',
     'system'        : 'SYSTEM',
     'throw'         : 'THROW',
@@ -84,8 +81,8 @@
     (r'>=',                                       "'>='",       'GE'),
     (r'>',                                        "'>'",        'GT'),
     (r'@',                                        "'@'",        'AT'),
-    (r'\%\[',                                     "'%['",       'LCONSTRAINT'),
-    (r'\]\%',                                     "']%'",       'RCONSTRAINT'),
+    (r'\%\[',                                     "'%['",       'LSCOPE'),
+    (r'\]\%',                                     "']%'",       'RSCOPE'),
     (r'\(',                                       "'('",        'LPAREN'),
     (r'\)',                                       "')'",        'RPAREN'),
     (r'\[',                                       "'['",        'LBRACKET'),
diff --git a/asteroid/mad.py b/asteroid/mad.py
new file mode 100644
index 00000000..ea58261f
--- /dev/null
+++ b/asteroid/mad.py
@@ -0,0 +1,400 @@
+###########################################################################################
+# Minimal Asteroid Debugger (MAD)
+#
+# (c) University of Rhode Island
+###########################################################################################
+# This is a very basic debugger for Asteroid and is designed around the callback API
+# from the interpreter,
+#     start           - called after the AST has been created and just before 
+#                       execution begins
+#     stop            - called after execution terminates just before the 
+#                       interpreter terminates
+#     error           - this is called when the interpreter encounters an error 
+#                       as part of the error handler of the interpreter
+#     enter_function  - this call signals that the interpreter is just about to 
+#                       execute a function, when the interpreter calls this function
+#                       the function stackframe and the function local variables have
+#                       been properly initialized
+#     exit_function   - this call signals that the interpreter just finished executing 
+#                       function, this call is issued just before the function stack frame
+#                       is popped off the stack
+#     enter_module    - a module is just about to be executed, the module scope has 
+#                       has been pushed on the stack
+#     exit_module     - the interpreter is just about to exit a module, module stack frame
+#                       is still on the stack.
+#     step            - this is called by the interpreter at more or less statementlevel 
+#                       granularity and represents a single computational step, step always
+#                       point to the next statement just about to be executed
+#
+# the debugger object maintains state accross the callbacks from the interpreter. in particular
+# it remembers whether or not it is in "continue" mode, that is, computation should proceed
+# uninterrupted  until breakpoint is encountered.  it also remembers whether or not a "next" 
+# command was used to step over nested scopes such as functions and modules. At each
+# "step" callback the debugger uses the following logic in order to decide whether or not
+# to hand back control to the interpreter:
+#      if breakpoint encountered:
+#         print "reached breakpoint"
+#         reset all mode variables
+#         return to interactive debugger session
+#      elif in continue_mode:
+#         return control to the interpreter
+#      elif completed execution of nested scope:
+#         reset scope mode variable
+#         return to interactive debugger session
+#      if executing nested scope via 'next' command:
+#         return control to the interpreter
+#      else:
+#         return to interactive debugger session
+###########################################################################################
+
+from os.path import exists, split, basename
+from asteroid.support import term2string
+from asteroid.version import MAD_VERSION
+import copy 
+
+START_DEBUGGER = False   # interactive debugging session
+RETURN_TO_INTERP = True  # return control to interpreter
+
+class MAD:
+
+   ###########################################################################################
+   def __init__(self):
+      # a reference to the interpreter state object
+      self.interp_state = None
+      # a lookup table for the program texts used during debugging
+      self.program_text = {}
+      # continue mode is used in the implementation of the continue cmd
+      self.continue_mode = False
+      # scope counter is used as a scope stack in the implementation of the over cmd
+      self.scope_counter = -1
+      # the frame we are looking at
+      # Note: continue, next, and step reset this to 0
+      self.frame_ix = 0
+      # command dispatch table, only uses the first two letters of each command
+      # in order to interpret the commands
+      self.dispatch_table = {
+                  'bre'     : self._handle_breakpoints,
+                  'cle'     : self._handle_clear,
+                  'con'     : self._handle_continue,
+                  'dow'     : self._handle_down,
+                  'fra'     : self._handle_frame,
+                  'hel'     : self._handle_help,
+                  'lis'     : self._handle_list,
+                  'nex'     : self._handle_next,
+                  'pri'     : self._handle_print,
+                  'qui'     : self._handle_quit,
+                  'set'     : self._handle_set,
+                  'sta'     : self._handle_stack,
+                  'ste'     : self._handle_step,
+                  'tra'     : self._handle_stack,
+                  'up '     : self._handle_up,
+                  'whe'     : self._handle_where,
+               }
+      # the following tables of tuples (func/line#,file) that describes break points at 
+      #function entry points or lines
+      self.function_breakpoints = []
+      self.line_breakpoints = []
+
+   ###########################################################################################
+   # debugger API from interpreter
+   def start(self, state):
+      self.interp_state = state
+      print("Minimal Asteroid Debugger {}".format(MAD_VERSION))
+      print("(c) University of Rhode Island")
+      print("type \"help\" for additional information")
+      self._prompt_cmd(show_code=False)
+
+   def stop(self):
+      print("stopping MAD")
+      self._prompt_cmd(show_code=False)
+
+   def error(self, e):
+      print("error: {}".format(str(e)))
+      self._prompt_cmd()
+
+   def enter_function(self, fname):
+      # deal with function break points
+      (file,_) = self.interp_state.lineinfo
+      if self.function_breakpoints.count((fname,basename(file))):
+         print("reached breakpoint ({} @{})".format(file,fname))
+         self.continue_mode = False
+         self.scope_counter = -1
+      elif self._check_enter_scope(fname) == RETURN_TO_INTERP:
+         return
+      print("entering function {}".format(fname))
+      self._prompt_cmd()
+
+   def exit_function(self, fname):
+      if self._check_exit_scope(fname) == RETURN_TO_INTERP:
+         return
+      print("exiting function {}".format(fname))
+      self._prompt_cmd()
+
+   def enter_module(self, modname):
+      if self._check_enter_scope(modname) == RETURN_TO_INTERP:
+         return
+      print("entering module {}".format(modname))
+      self._prompt_cmd()
+
+   def exit_module(self, modname):
+      if self._check_exit_scope(modname) == RETURN_TO_INTERP:
+         return
+      print("exiting module {}".format(modname))
+      self._prompt_cmd()
+
+   def step(self):
+      if self._check_step() == RETURN_TO_INTERP:
+         return
+      self._prompt_cmd()
+
+   ###########################################################################################
+   # at each call-back from the interpreter we have to make decisions whether or not
+   # to return control back to the interpreter or to start the debugger command line
+   # interface.  The following functions handle this decision.  With one exception:
+   # function break points, these are handled directly by the 'enter_function' API
+   # function
+
+   def _check_enter_scope(self,scopename):
+      #print("entering scope {} with {}".format(scopename,self.scope_counter))
+      if self.continue_mode:
+         return RETURN_TO_INTERP
+      elif self.scope_counter > 0:
+         self.scope_counter += 1
+         return RETURN_TO_INTERP
+      else:
+         return START_DEBUGGER
+
+   def _check_exit_scope(self,scopename):
+      #print("exiting scope {} with {}".format(scopename,self.scope_counter))
+      if self.continue_mode:
+         return RETURN_TO_INTERP
+      elif self.scope_counter > 1:
+         self.scope_counter -= 1
+         return RETURN_TO_INTERP
+      else:
+         return START_DEBUGGER
+
+   def _check_step(self):
+      (file,line) = self.interp_state.lineinfo
+      if (int(line),file) in self.line_breakpoints:
+         print("reached breakpoint ({}:{})".format(file,line))
+         self.continue_mode = False
+         self.scope_counter = -1
+         return START_DEBUGGER
+      elif self.continue_mode:
+         return RETURN_TO_INTERP
+      elif self.scope_counter == 1:
+         self.scope_counter = -1
+         return START_DEBUGGER
+      if self.scope_counter > 1:
+         return RETURN_TO_INTERP
+      else:
+         return START_DEBUGGER
+
+   ###########################################################################################
+   def _print_line(self):
+      (file,lineno) = self.interp_state.lineinfo
+      self._load_program_text(file)
+      pt = self.program_text[file]
+      pt_display = pt[lineno-1].strip()
+      print("{}:{}:{}".format(file,lineno,pt_display))
+
+   ###########################################################################################
+   def _load_program_text(self,fname):
+      # load program text into a text cache
+      if not self.program_text.get(fname) and exists(fname):
+         with open(fname, "r") as f:
+               self.program_text[fname] = f.readlines()
+         # Always add an EOF specifier
+         self.program_text[fname].append("[EOF]\n")
+
+   ###########################################################################################
+   # the following is the command interpretation interface using the 
+   # debugger dispatch table from above
+   # Note: functions of the format _handle_xxxx are functions that
+   #       are dispatched by the dispatch table
+
+   def _prompt_cmd(self, show_code=True):
+      if show_code:
+         #self._print_line()
+         self._handle_list([])
+      # loop while interpreting commands
+      while True:
+         cmd = input("mad> ")
+         # if the command returns true return control
+         # to the Asteroid interpreter
+         if self._interpret_cmd(cmd):
+            break
+
+   def _interpret_cmd(self, cmd):
+      # use the dispatch table in order to interpret commands
+      cmd_list = cmd.split()
+      # special case our 2-char command
+      if cmd_list[0] == 'up': 
+         cmd_list[0] = 'up '
+      if len(cmd_list) > 0:
+         val = self.dispatch_table.get(cmd_list[0][0:3],lambda _:-1) (cmd_list[1:])
+         if val == -1:
+            print("error: unknown command {}".format(cmd_list[0]))
+            return START_DEBUGGER
+         else:
+            return val
+      else:
+         # assume implicit step when user just hits return
+         return self._handle_step([])
+
+   def _handle_breakpoints(self,_):
+      print("breakpoints:")
+      for (bp,file) in self.function_breakpoints:
+         print("{} @{}".format(file,bp))
+      for (bp,file) in self.line_breakpoints:
+         print("{}:{}".format(file,bp))
+      return START_DEBUGGER
+      
+   def _handle_clear(self,_):
+      # TODO: allow for specicific breakpoints to be cleared
+      self.function_breakpoints = []
+      self.line_breakpoints = []
+      return START_DEBUGGER
+      
+   def _handle_continue(self,_):
+      self.continue_mode = True
+      self.frame_ix = 0
+      return RETURN_TO_INTERP
+
+   def _handle_down(self, args):
+      if self.frame_ix == 0:
+         print("error: no such frame")
+      else:
+         self.frame_ix -= 1
+         self._handle_frame(args)
+      return START_DEBUGGER
+
+   def _handle_help(self,_):
+      print()
+      print("Available commands:")
+      print("breakpoints\t\t- show all breakpoints")
+      print("clear\t\t\t- clear all breakpoints")
+      print("continue\t\t- continue execution to next breakpoint")
+      print("down\t\t\t- move down one stack frame")
+      print("frame\t\t\t- display current stack frame number")
+      print("help\t\t\t- display help")
+      print("list\t\t\t- display source code")
+      print("next\t\t\t- step execution across a nested scope")
+      print("print <name>|*\t\t- print contents of <name>, * lists all vars in scope")
+      print("quit\t\t\t- quit debugger")
+      print("set [<func>|<line#> [<file>]]\n\t\t\t- set a breakpoint")
+      print("stack\t\t\t- display runtime stack")
+      print("step\t\t\t- step to next executable statement")
+      print("trace\t\t\t- display runtime stack")
+      print("up\t\t\t- move up one stack frame")
+      print("where\t\t\t- print current program line")
+      print()
+      return START_DEBUGGER
+
+   def _handle_list(self, _):
+      (file,lineno) = self.interp_state.lineinfo
+      self._load_program_text(file)
+      pt = self.program_text[file]
+      # Length around the current line to display
+      length = 4
+      # Compute the start and end of listing
+      start = (lineno - length) if lineno >= length else 0
+      end = lineno + length if lineno < len(pt) - 2 else len(pt)
+      pt_display = pt[start:end]
+      start_of_line = "  "
+      # GO through each line in the program text
+      for ix, l in enumerate(pt_display):
+         # if the offset line number is in breakpoints
+         if (ix+1+start,file) in self.line_breakpoints:
+               start_of_line = "* "
+         # mark the current line
+         if lineno == ix+1+start:
+               start_of_line = "> "
+         print(start_of_line, ix+1+start, l[:-1])
+         start_of_line = "  "
+      return START_DEBUGGER
+
+   def _handle_next(self,_):
+      # initialize the "scope stack", as long as the scope
+      # counter value is > 0 all call backs from the interpreter
+      # immediately return control back to the interpreter with
+      # one exception: breakpoints.  If a breakpoint is hit
+      # the scope counter is reset to -1.
+      self.scope_counter = 1
+      self.frame_ix = 0
+      return RETURN_TO_INTERP
+
+   def _handle_print(self,args):
+      if len(args) > 1:
+         print("error: too many arguments")
+         return False
+      elif len(args) == 0:
+         print("error: no argument given")
+         return False
+      if args[0] == '*':
+         var_list = self.interp_state.symbol_table.get_curr_scope(scope=self.frame_ix, option="items")
+         for (name,val) in var_list:
+            print("{}: {}".format(name,term2string(val)))
+      else:
+         val = self.interp_state.symbol_table.lookup_sym(args[0],strict=False)
+         if not val:
+            print("error: variable {} not found".format(args[0]))
+         else:
+            print("{}: {}".format(args[0],term2string(val)))
+      return START_DEBUGGER
+
+   def _handle_quit(self,_):
+      raise SystemExit()
+   
+   def _handle_set(self,args):
+      if len(args) == 0:
+         # set a breakpoint at the current line
+         (file,lineno) = self.interp_state.lineinfo
+         self.line_breakpoints.append((lineno,file))
+         return START_DEBUGGER
+      elif len(args) == 1:
+         (file,_) = self.interp_state.lineinfo
+         if args[0].isnumeric(): 
+            self.line_breakpoints.append((int(args[0]),file))
+         else:
+            self.function_breakpoints.append((args[0],file))
+         return START_DEBUGGER
+      elif len(args) == 2:
+         if args[0].isnumeric(): 
+            self.line_breakpoints.append((int(args[0]),args[1]))
+         else:
+            self.function_breakpoints.append((args[0],args[1]))
+         return START_DEBUGGER
+      else:
+         print("error: too many arguments to set")
+         return START_DEBUGGER
+
+   def _handle_frame(self,_):
+      print("you are looking at frame #{}".format(self.frame_ix))
+      return START_DEBUGGER
+
+   def _handle_step(self,_):
+      self.frame_ix = 0
+      return RETURN_TO_INTERP
+
+   def _handle_stack(self,_):
+      trace = copy.copy(self.interp_state.trace_stack)
+      trace.reverse()
+      print("Runtime stack (most recent call first):")
+      for i in range(self.frame_ix,len(trace)):
+         (module,lineno,fname) = trace[i]
+         print("frame #{}: {} @{}".format(i,module,fname))
+      return START_DEBUGGER
+
+   def _handle_up(self, args):
+      if self.frame_ix+1 == len(self.interp_state.trace_stack):
+         print("error: no such frame")
+      else:
+         self.frame_ix += 1
+         self._handle_frame(args)
+      return START_DEBUGGER
+
+   def _handle_where(self,_):
+      self._print_line()
+      return START_DEBUGGER
diff --git a/asteroid/modules/bitwise.ast b/asteroid/modules/bitwise.ast
index 8ef19dc0..b83c29bc 100644
--- a/asteroid/modules/bitwise.ast
+++ b/asteroid/modules/bitwise.ast
@@ -6,13 +6,6 @@
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
--- define the bitwise module object
-
-------------------------------------------------------------------
-structure __BITWISE_MODULE__
-------------------------------------------------------------------
-with
-
 ------------------------------------------------------------------
 function band
 ------------------------------------------------------------------
@@ -180,8 +173,3 @@ __retval__ = ('integer', x_val.bit_length())
 "
 end
 
-end -- __BITWISE__
-
-------------------------------------------------------------------
--- instantiate the bitwise module object
-let bitwise = __BITWISE_MODULE__().
diff --git a/asteroid/modules/dataframe.ast b/asteroid/modules/dataframe.ast
index 2b341551..7c8c6576 100644
--- a/asteroid/modules/dataframe.ast
+++ b/asteroid/modules/dataframe.ast
@@ -7,9 +7,8 @@
 ------------------------------------------------------------------
 
 ------------------------------------------------------------------
-structure __DATAFRAME__
+structure DataFrame with
 ------------------------------------------------------------------
-with
 
 ------------------------------------------------------------------
 data df.
@@ -30,6 +29,7 @@ header_row_val = state.symbol_table.lookup_sym('header_row')
 # destructure object
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 # read as Pandas dataframe
@@ -56,6 +56,7 @@ ix_val = state.symbol_table.lookup_sym('ix')
 # destructure object
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
  # the dataframe is in the first slot in the object memory
@@ -95,6 +96,7 @@ ix_val = state.symbol_table.lookup_sym('ix')
 # destructure object
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
  # the dataframe is in the first slot in the object memory
@@ -132,6 +134,7 @@ this_val = state.symbol_table.lookup_sym('this')
 # destructure object
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
  # the dataframe is in the first slot in the object memory
@@ -152,6 +155,7 @@ this_val = state.symbol_table.lookup_sym('this')
 # destructure object
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
  # the dataframe is in the first slot in the object memory
@@ -159,18 +163,11 @@ this_val = state.symbol_table.lookup_sym('this')
 __retval__ = ('integer', df_val.shape[1])
 "
 end
-end -- __DATAFRAME__
+end -- DataFrame structure
 
-------------------------------------------------------------------
-structure __DATAFRAME_MODULE__
-------------------------------------------------------------------
-with
 
 function dataframe with none do
-  return __DATAFRAME__().
+  return DataFrame().
 end
 
-end -- __DATAFRAME_MODULE__
 
-------------------------------------------------------------------
-let dataframe = __DATAFRAME_MODULE__().
diff --git a/asteroid/modules/hash.ast b/asteroid/modules/hash.ast
index c57e3366..87cebc16 100644
--- a/asteroid/modules/hash.ast
+++ b/asteroid/modules/hash.ast
@@ -5,10 +5,10 @@
 --
 -- (c) Lutz Hamel, University of Rhode Island
 ------------------------------------------------------------------
-load system type.
+
 
 ------------------------------------------------------------------
-structure __HASH__ with
+structure Hash with
 ------------------------------------------------------------------
 -- Asteroid hash table implementation using Python dictionaries
 
@@ -26,6 +26,7 @@ this_val = state.symbol_table.lookup_sym('this')
 # destructure object
 (OBJECT,
  (STRUCT_ID, (ID, struct_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 # the table is in the first slot in the object memory
@@ -37,8 +38,10 @@ end -- __init__
 ------------------------------------------------------------------
 function insert
 ------------------------------------------------------------------
-with (name,value) do escape
+with (name,value) do 
+return escape
 "
+global __retval__
 this_val = state.symbol_table.lookup_sym('this')
 name_val = state.symbol_table.lookup_sym('name')
 value_val = state.symbol_table.lookup_sym('value')
@@ -46,17 +49,21 @@ value_val = state.symbol_table.lookup_sym('value')
 # destructure object
 (OBJECT,
  (STRUCT_ID, (ID, struct_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 # the table is in the first slot in the object memory
 # insert name-value pair
 (FOREIGN, dictionary) = memory[0]
 dictionary[name_val] = value_val
+
+__retval__ = this_val
 "
 with item_list:%list do
   for (k,v) in item_list do
     this @insert (k,v).
   end
+  return this
 end -- insert
 
 ------------------------------------------------------------------
@@ -72,6 +79,7 @@ name_val = state.symbol_table.lookup_sym('name')
 # destructure object
 (OBJECT,
  (STRUCT_ID, (ID, struct_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 # the table is in the first slot in the object memory
@@ -96,6 +104,7 @@ this_val = state.symbol_table.lookup_sym('this')
 # destructure object
 (OBJECT,
  (STRUCT_ID, (ID, struct_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 # the table is in the first slot in the object memory
@@ -121,21 +130,14 @@ end -- aslist
 function __str__
 ------------------------------------------------------------------
 with none do
-  return type @tostring (this @aslist ()).
+  return tostring (this @aslist ()).
 end -- __str__
 
-end -- __HASH__
-
-------------------------------------------------------------------
-structure __HASH_MODULE__
-------------------------------------------------------------------
-with
+end -- Hash structure
 
+-- here for backwards compatibility
 function hash with none do
-   return __HASH__().
+   return Hash().
 end
 
-end -- __HASH_MODULE__
 
-------------------------------------------------------------------
-let hash = __HASH_MODULE__().
diff --git a/asteroid/modules/io.ast b/asteroid/modules/io.ast
index 8a2fe0ff..a2a080c5 100644
--- a/asteroid/modules/io.ast
+++ b/asteroid/modules/io.ast
@@ -5,14 +5,14 @@
 --
 -- (c) University of Rhode Island
 
-
-load system type.
+-- define the io module.
 
 ------------------------------------------------------------------
--- Basic file i/o
+
 ------------------------------------------------------------------
 structure __FILE__ with
 ------------------------------------------------------------------
+-- Basic file i/o
 
 data fd.
 
@@ -32,6 +32,7 @@ mode_val = state.symbol_table.lookup_sym('mode')
 # destructure object
 (OBJECT,
 (CLASS_ID, (ID, class_id)),
+(MEMBER_NAMES, (LIST, member_names)),
 (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 # Open file
@@ -62,6 +63,7 @@ else:
 # destructure object
 (OBJECT,
 (CLASS_ID, (ID, class_id)),
+(MEMBER_NAMES, (LIST, member_names)),
 (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 memory[0] = ('foreign', stream)
@@ -80,6 +82,7 @@ this_val = state.symbol_table.lookup_sym('this')
 
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 (FOREIGN, f_val) = memory[0]
@@ -99,6 +102,7 @@ this_val = state.symbol_table.lookup_sym('this')
 
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 (FOREIGN, f_val) = memory[0]
@@ -118,6 +122,7 @@ this_val = state.symbol_table.lookup_sym('this')
 
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 (FOREIGN, f_val) = memory[0]
@@ -137,11 +142,12 @@ what_val = state.symbol_table.lookup_sym('what')
 
 (OBJECT,
  (CLASS_ID, (ID, class_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 (FOREIGN, f_val) = memory[0]
 
-f_val.write(what_val[1])
+f_val.write(term2string(what_val))
 "
 end
 
@@ -151,21 +157,11 @@ end -- __FILE__
 
 
 
--- define the io module object.
-------------------------------------------------------------------
-structure __IO_MODULE__ with
-------------------------------------------------------------------
 
 -- Predefined standard stream constants
-data __STDIN__.
-data __STDOUT__.
-data __STDERR__.
-
-function __init__ with none do
-   let this @__STDIN__ = __FILE__("__STDIN__").
-   let this @__STDOUT__ = __FILE__("__STDOUT__").
-   let this @__STDERR__ = __FILE__("__STDERR__").
-end
+let __STDIN__ = __FILE__("__STDIN__").
+let __STDOUT__ = __FILE__("__STDOUT__").
+let __STDERR__ = __FILE__("__STDERR__").
 
 -- File I/O library functions
 ------------------------------------------------------------------
@@ -190,9 +186,8 @@ function read
 ------------------------------------------------------------------
 with(file:%__FILE__) do
     return file @read().
-
 with none do
-    return this @__STDIN__ @ read().
+    return __STDIN__ @ read().
 end
 
 ------------------------------------------------------------------
@@ -209,7 +204,7 @@ function readln
 with(file:%__FILE__) do
     return file @readln().
 with none do
-    return this @__STDIN__ @readln().
+    return __STDIN__ @readln().
 end
 
 ------------------------------------------------------------------
@@ -217,13 +212,8 @@ function write
 -- Write to a given file
 ------------------------------------------------------------------
 with what:%string do
-this @__STDOUT__ @write(what).
-
-escape "
-import sys
-sys.stdout.flush()
-"
-
+    __STDOUT__ @write(what).
+    escape "import sys;sys.stdout.flush()".
 with(file:%__FILE__, what:%string) do
     file @write(what).
 end
@@ -233,7 +223,7 @@ function writeln
 -- Write a complete line to a given file
 ------------------------------------------------------------------
 with what:%string do
-    this @__STDOUT__ @write(what + "\n").
+    __STDOUT__ @write(what + "\n").
 
 with(file:%__FILE__, what:%string) do
     file @write(what + "\n").
@@ -246,14 +236,14 @@ end
 function println
 ------------------------------------------------------------------
 with item do
-    this @writeln(type @tostring item).
+    writeln(tostring item).
 end
 
 ------------------------------------------------------------------
 function print
 ------------------------------------------------------------------
 with item do
-    this @write(type @tostring item).
+    write(tostring item).
 end
 
 ------------------------------------------------------------------
@@ -261,10 +251,10 @@ function input
 ------------------------------------------------------------------
 -- input drops the trailing newline char
 with none do
-    return this @readln() @replace("\n","").
+    return readln() @replace("\n","").
 with prompt do
-    this @write (type @tostring prompt).
-    return this @readln() @replace("\n","").
+    write (tostring prompt).
+    return readln() @replace("\n","").
 end
 
 ------------------------------------------------------------------
@@ -280,9 +270,3 @@ pprint(item_val)
 return none
 end
 
-end -- __IO_MODULE__
-
-
-------------------------------------------------------------------
--- instantiate the io module object
-let io = __IO_MODULE__().
diff --git a/asteroid/modules/math.ast b/asteroid/modules/math.ast
index 2e89c9e7..5580def5 100644
--- a/asteroid/modules/math.ast
+++ b/asteroid/modules/math.ast
@@ -7,31 +7,14 @@
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
-structure __MATH_MODULE__ with
 
 ------------------------------------------------------------------
 -- Constants
 ------------------------------------------------------------------
-data pi.
-data e.
 
-function __init__ with none do
-
-let this @pi = escape -- init pi constant
-"
-from math import pi
-global __retval__
-__retval__ = ('real',pi)
-"
-
-let this @e = escape -- init e constant
-"
-from math import e
-global __retval__
-__retval__ = ('real',e)
-"
-
-end -- __init__
+let pi = escape "from math import pi;global __retval__;__retval__=('real',pi)"
+let tau = escape "from math import tau;global __retval__;__retval__=('real',tau)"
+let e = escape "from math import e;global __retval__;__retval__=('real',e)"
 
 ------------------------------------------------------------------
 -- Power and logarithmic functions
@@ -115,10 +98,201 @@ __retval__ = ('real',sqrt(val_a[1]))
 "
 end
 
+------------------------------------------------------------------
+function isqrt
+------------------------------------------------------------------
+-- Return the integer square root of the nonnegative integer n. 
+-- This is the floor of the exact square root of n, or the greatest 
+-- integer a such that a^2 <= n.
+with a do return escape
+"
+global __retval__
+from asteroid.state import state
+from math import isqrt
+
+val_a = state.symbol_table.lookup_sym('a')
+if val_a[0] not in ['integer','real']:
+  raise ValueError('unsupported type \'{}\' for isqrt'.format(val_a[0]))
+__retval__ = ('integer',isqrt(val_a[1]))
+"
+end
+
+------------------------------------------------------------------
+function ldexp
+------------------------------------------------------------------
+-- Return x * (2**i)
+with (x,i) do return escape
+"
+global __retval__
+from math import ldexp
+
+val_x = state.symbol_table.lookup_sym('x')
+val_i = state.symbol_table.lookup_sym('i')
+
+if val_x[0] not in ['integer','real'] or val_i[0] not in ['integer','real']:
+  raise ValueError('unsupported type for ldexp')
+__retval__ = ('real',ldexp(val_x[1],val_i[1]))
+"
+end
+
+------------------------------------------------------------------
+function expm1
+------------------------------------------------------------------
+-- Return e raised to the power x, minus 1.
+with x do return escape
+"
+global __retval__
+from math import expm1
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['integer','real']:
+  raise ValueError('unsupported type for expm1')
+__retval__ = ('real',expm1(val_x[1]))
+"
+end
+
+------------------------------------------------------------------
+function log1p
+------------------------------------------------------------------
+-- Return the natural logarithm of 1+x (base e).
+with x do return escape
+"
+global __retval__
+from math import log1p
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['integer','real']:
+  raise ValueError('unsupported type for log1p')
+__retval__ = ('real',log1p(val_x[1]))
+"
+end
+
+------------------------------------------------------------------
+function log2
+------------------------------------------------------------------
+-- Return the base-2 logarithm of x.
+with x do return escape
+"
+global __retval__
+from math import log2
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['integer','real']:
+  raise ValueError('unsupported type for log2')
+__retval__ = ('real',log2(val_x[1]))
+"
+end
+
+------------------------------------------------------------------
+function log10
+------------------------------------------------------------------
+-- Return the base-10 logarithm of x.
+with x do return escape
+"
+global __retval__
+from math import log10
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['integer','real']:
+  raise ValueError('unsupported type for log10')
+__retval__ = ('real',log10(val_x[1]))
+"
+end
+
 ------------------------------------------------------------------
 -- Number-theoretic and representation functions
 ------------------------------------------------------------------
 
+------------------------------------------------------------------
+function prod
+------------------------------------------------------------------
+-- Returns the product of a list or tuple
+-- conditional pattern match asserts the the input is a list or 
+-- tuple and that every element is a real or integer value. This 
+-- is to avoid strings getting in and having Python's definition 
+-- of multiplication between ints and strings applied.
+with x if ((x is %list) or (x is %tuple)) 
+          do return escape
+"
+global __retval__
+from math import prod
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['list','tuple'] :
+  raise ValueError('unsupported type for prod')
+
+__val__ =  prod( to_python_list(val_x) )
+
+if isinstance(__val__,float):
+  __retval__ = ('real',__val__)
+else:
+  __retval__ = ('integer',__val__)
+"
+end
+
+------------------------------------------------------------------
+function sum
+------------------------------------------------------------------
+-- Returns the sum of a list or tuple
+with x do return escape
+"
+global __retval__
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['list','tuple'] :
+  raise ValueError('unsupported type for sum')
+
+__val__ =  sum( to_python_list(val_x) )
+
+if isinstance(__val__,float):
+  __retval__ = ('real',__val__)
+else:
+  __retval__ = ('integer',__val__)
+"
+end
+
+------------------------------------------------------------------
+function fsum
+------------------------------------------------------------------
+-- Returns the sum of a list or tuple. Returns an accurate 
+-- floating point sum of values in the iterable. Avoids loss of
+-- precision by tracking multiple intermediate partial sums.
+with x do return escape
+"
+global __retval__
+from math import fsum
+
+val_x = state.symbol_table.lookup_sym('x')
+
+if val_x[0] not in ['list','tuple'] :
+  raise ValueError('unsupported types for fsum')
+
+__retval__ = ('real',fsum( to_python_list(val_x) ))
+
+"
+end
+
+------------------------------------------------------------------
+function remainder
+------------------------------------------------------------------
+with (a,b) do return escape
+"
+global __retval__
+from math import remainder
+
+val_a = state.symbol_table.lookup_sym('a')
+val_b = state.symbol_table.lookup_sym('b')
+
+__retval__ = ('real', remainder(val_a[1], val_b[1]))
+"
+end
+
 ------------------------------------------------------------------
 function abs
 ------------------------------------------------------------------
@@ -165,6 +339,21 @@ __retval__ = ('integer', math.floor(val_x[1]))
 "
 end
 
+------------------------------------------------------------------
+function round
+------------------------------------------------------------------
+-- Return x rounded to the nearest integer. If two integers are equally close,
+-- x is rounded to the nearest even integer.
+with (x:%real) do return escape
+"
+global __retval__
+
+val_x = state.symbol_table.lookup_sym('x')
+
+__retval__ = ('integer', round(val_x[1]))
+"
+end
+
 ------------------------------------------------------------------
 function gcd
 ------------------------------------------------------------------
@@ -176,11 +365,74 @@ from math import gcd
 val_a = state.symbol_table.lookup_sym('a')
 val_b = state.symbol_table.lookup_sym('b')
 
-
 __retval__ = ('integer', gcd(val_a[1], val_b[1]))
 "
 end
 
+------------------------------------------------------------------
+function lcm
+------------------------------------------------------------------
+-- Return the least common multiple of the integer arguments. 
+with (a:%integer,b:%integer) do return escape
+"
+global __retval__
+from math import lcm
+
+val_a = state.symbol_table.lookup_sym('a')
+val_b = state.symbol_table.lookup_sym('b')
+
+__retval__ = ('integer', lcm(val_a[1], val_b[1]))
+"
+end
+
+------------------------------------------------------------------
+function copysign
+------------------------------------------------------------------
+-- Return a float with the absolute value of x and the sign of y. 
+with (x,y) do return escape
+"
+global __retval__
+from math import copysign
+
+val_x = state.symbol_table.lookup_sym('x')
+val_y = state.symbol_table.lookup_sym('y')
+
+if val_x[0] not in ['integer','real'] or val_y[0] not in ['integer','real']:
+  raise ValueError('unsupported types for copysign')
+__retval__ = (val_x[0], copysign(val_x[1],val_y[1]))
+"
+end
+
+------------------------------------------------------------------
+function factorial
+------------------------------------------------------------------
+-- Return n factorial as an integer.
+with n:%integer do return escape
+"
+global __retval__
+from math import factorial
+
+val_n = state.symbol_table.lookup_sym('n')
+
+__retval__ = ('integer', factorial(val_n[1]))
+"
+end
+
+------------------------------------------------------------------
+function trunc
+------------------------------------------------------------------
+-- Return n with its fractional component set to 0.
+with n:%real do return escape
+"
+global __retval__
+from math import trunc
+
+val_n = state.symbol_table.lookup_sym('n')
+
+__retval__ = ('integer', trunc(val_n[1]))
+"
+end
+
 ------------------------------------------------------------------
 function isclose
 ------------------------------------------------------------------
@@ -212,26 +464,46 @@ end
 ------------------------------------------------------------------
 function mod
 ------------------------------------------------------------------
-with (v,d) do return escape
+-- only defined as a function over integers for now
+with (v:%integer,d:%integer) do return escape
 "
 global __retval__
-from asteroid.state import state
-from asteroid.support import promote
 
 val_v = state.symbol_table.lookup_sym('v')
 val_d = state.symbol_table.lookup_sym('d')
 
-if val_v[0] not in ['integer','real']:
-  raise ValueError('unsupported type \'{}\' for mod'.format(val_v[0]))
+__retval__ = ('integer',val_v[1] % val_d[1])
+"
+with _ do escape 
+"
+raise ValueError('unsupported type in \'mod\'')
+"
+end
+
+------------------------------------------------------------------
+function fmod
+------------------------------------------------------------------
+-- Return fmod(x, y), as defined by the platform C library. The
+-- intent of the C standard is that fmod(x, y) be exactly 
+-- (mathematically; to infinite precision) equal to x - n*y for
+-- some integer n such that the result has the same sign as x 
+-- and magnitude less than abs(y). 
+with (v:%integer,d:%integer) do return escape
+"
+global __retval__
+from math import fmod
 
-if val_d[0] not in ['integer','real']:
-  raise ValueError('unsupported type \'{}\' for mod'.format(val_d[0]))
+val_v = state.symbol_table.lookup_sym('v')
+val_d = state.symbol_table.lookup_sym('d')
 
-__retval__ = (promote(val_v[0],val_d[0]),val_v[1] % val_d[1])
+__retval__ = ('integer',fmod(val_v[1], val_d[1]))
+"
+with _ do escape 
+"
+raise ValueError('unsupported type in \'fmod\'')
 "
 end
 
-
 ------------------------------------------------------------------
 -- Trigonometric functions
 ------------------------------------------------------------------
@@ -284,6 +556,23 @@ __retval__ = ('real', math.atan(x_val[1]))
 "
 end
 
+------------------------------------------------------------------
+function atan2
+------------------------------------------------------------------
+-- Return atan(y / x), in radians. The result is between -pi and 
+-- pi.
+with (x,y) do return escape
+"
+import math
+global __retval__
+
+x_val = state.symbol_table.lookup_sym('x')
+y_val = state.symbol_table.lookup_sym('y')
+
+__retval__ = ('real', math.atan2(x_val[1],y_val[1]))
+"
+end
+
 ------------------------------------------------------------------
 function cos
 ------------------------------------------------------------------
@@ -419,6 +708,48 @@ __retval__ = ('real', math.tanh(x_val[1]))
 "
 end
 
+------------------------------------------------------------------
+function dist
+------------------------------------------------------------------
+-- Return the Euclidean distance between two points p and q, each
+-- given as a sequence (or iterable) of coordinates.  
+with (x,y) do return escape
+"
+global __retval__
+from math import dist
+
+val_x = state.symbol_table.lookup_sym('x')
+val_y = state.symbol_table.lookup_sym('y')
+
+if val_x[0] not in ['list','tuple'] or val_y[0] not in  ['list','tuple']:
+  raise ValueError('unsupported types for dist')
+if len(val_x[1]) != len(val_y[1]):
+  raise ValueError('points must do of same dimension for dist')
+
+__retval__ = ('real', dist(to_python_list(val_x),to_python_list(val_y)))
+"
+end
+
+------------------------------------------------------------------
+function hypot
+------------------------------------------------------------------
+-- Return the Euclidean norm, sqrt(sum(x**2 for x in coordinates))  
+with (a,b) do return escape
+"
+global __retval__
+from math import hypot
+
+val_a = state.symbol_table.lookup_sym('a')
+val_b = state.symbol_table.lookup_sym('b')
+
+__retval__ = ('real',hypot(val_a[1],val_b[1]))
+"
+end
+
+------------------------------------------------------------------
+-- Conversions
+------------------------------------------------------------------
+
 ------------------------------------------------------------------
 function degrees
 ------------------------------------------------------------------
@@ -449,6 +780,108 @@ __retval__ = ('real', math.radians(x_val[1]))
 "
 end
 
-end -- __MATH_MODULE__
+------------------------------------------------------------------
+-- Combinatoric functions
+------------------------------------------------------------------
+
+------------------------------------------------------------------
+function comb
+------------------------------------------------------------------
+-- Return the number of ways to choose k items from n items 
+-- without repetition and without order. Evaluates to 
+-- n! / (k! * (n - k)!) when k <= n and evaluates to zero when 
+-- k > n.
+with (n:%integer,k:%integer) do return escape
+"
+global __retval__
+from math import comb
+
+val_n = state.symbol_table.lookup_sym('n')
+val_k = state.symbol_table.lookup_sym('k')
+
+__retval__ = ('integer',comb(val_n[1],val_k[1]))
+"
+end
+
+------------------------------------------------------------------
+function perm
+------------------------------------------------------------------
+-- Return the number of ways to choose k items from n items 
+-- without repetition and with order. Evaluates to 
+-- n! / (n - k)! when k <= n and evaluates to zero when k > n.
+with (n:%integer,k:%integer) do return escape
+"
+global __retval__
+from math import perm
+
+val_n = state.symbol_table.lookup_sym('n')
+val_k = state.symbol_table.lookup_sym('k')
+
+__retval__ = ('integer',perm(val_n[1],val_k[1]))
+"
+end
+
+------------------------------------------------------------------
+-- Special functions
+------------------------------------------------------------------
+
+------------------------------------------------------------------
+function erf
+------------------------------------------------------------------
+-- Return the error function at x.
+with x do return escape
+"
+global __retval__
+from math import erf
 
-let math = __MATH_MODULE__()
+val_x = state.symbol_table.lookup_sym('x')
+
+__retval__ = ('real',erf(val_x[1]))
+"
+end
+
+------------------------------------------------------------------
+function erfc
+------------------------------------------------------------------
+-- Return the complementary error function at x.
+with x do return escape
+"
+global __retval__
+from math import erfc
+
+val_x = state.symbol_table.lookup_sym('x')
+
+__retval__ = ('real',erfc(val_x[1]))
+"
+end
+
+------------------------------------------------------------------
+function gamma
+------------------------------------------------------------------
+-- Return the Gamma function at x.
+with x do return escape
+"
+global __retval__
+from math import gamma
+
+val_x = state.symbol_table.lookup_sym('x')
+
+__retval__ = ('real',gamma(val_x[1]))
+"
+end
+
+------------------------------------------------------------------
+function lgamma
+------------------------------------------------------------------
+-- Return the natural logarithm of the absolute value of the Gamma
+-- function at x.
+with x do return escape
+"
+global __retval__
+from math import lgamma
+
+val_x = state.symbol_table.lookup_sym('x')
+
+__retval__ = ('real',lgamma(val_x[1]))
+"
+end
\ No newline at end of file
diff --git a/asteroid/modules/os.ast b/asteroid/modules/os.ast
index 3e5c8106..74a4edc3 100644
--- a/asteroid/modules/os.ast
+++ b/asteroid/modules/os.ast
@@ -9,44 +9,7 @@
 ------------------------------------------------------------------
 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
+function __getargv  with none do return escape
 "
 global __retval__
 import sys
@@ -75,10 +38,7 @@ __retval__ = ('list', out)
 "
 end -- __getargv
 
-------------------------------------------------------------------
-function __getenv
-------------------------------------------------------------------
-with none do return escape
+function __getenv with none do return escape
 "
 global __retval__
 from os import environ
@@ -90,10 +50,7 @@ __retval__ = ('list', outlist_val)
 "
 end -- __getplatform
 
-------------------------------------------------------------------
-function __getplatform
-------------------------------------------------------------------
-with none do return escape
+function __getplatform with none do return escape
 "
 global __retval__
 from sys import platform
@@ -101,6 +58,25 @@ __retval__ = ('string', platform)
 "
 end -- __getplatform
 
+------------------------------------------------------------------
+-- 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.
+let argv = __getargv().
+
+------------------------------------------------------------------
+-- 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.
+let env = hash @hash () @insert (__getenv ()).
+
+------------------------------------------------------------------
+-- This string contains a platform identifier.
+let platform = __getplatform().
+
 ------------------------------------------------------------------
 function basename
 ------------------------------------------------------------------
@@ -165,9 +141,9 @@ 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 
+-- 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 to 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 
@@ -398,7 +374,3 @@ __retval__ = ('integer', status)
 "
 end -- syscmd
 
-end -- __OS_MODULE__
-
-------------------------------------------------------------------
-let os = __OS_MODULE__().
diff --git a/asteroid/modules/patterns.ast b/asteroid/modules/patterns.ast
new file mode 100644
index 00000000..b4f6879b
--- /dev/null
+++ b/asteroid/modules/patterns.ast
@@ -0,0 +1,143 @@
+------------------------------------------------------------------
+-- patterns.ast
+--
+-- this module implements common patterns 
+-- 
+--
+-- (c) University of Rhode Island
+------------------------------------------------------------------
+load system math.
+
+------------------------------------------------------------------
+-- Helper functions
+------------------------------------------------------------------
+-- returns a boolean indicating if the passed in integer is prime.
+function is_prime
+  with (n:%integer) do
+    if n <= 1 do
+      return false.
+    end
+
+    if (n == 2) or (n == 3) do
+      return true.
+    end
+
+    if (math@mod(n,2) == 0) or (math@mod(n,3) == 0) do
+      return false.
+    end
+
+    for i in 5 to math@isqrt(n) step 6 do
+      if (math@mod(n,i) == 0) or (math@mod(n,i+2) == 0) do
+        return false.
+      end
+    end
+
+    return true.
+  with _ do
+    return false.
+end
+------------------------------------------------------------------
+function is_alphabetic
+  with (s:%string) do return escape
+"
+global __retval__
+
+val_s = state.symbol_table.lookup_sym('s')
+
+__retval__ = ('boolean',str.isalpha(val_s[1]))
+"
+  with _ do
+    return false.
+  end
+------------------------------------------------------------------
+function is_numeric
+  with (s:%string) do return escape
+"
+global __retval__
+
+val_s = state.symbol_table.lookup_sym('s')
+
+__retval__ = ('boolean',str.isnumeric(val_s[1]))
+"
+  with _ do
+    return false.
+  end
+------------------------------------------------------------------
+function is_uppercase
+  with (s:%string) do return escape
+"
+global __retval__
+
+val_s = state.symbol_table.lookup_sym('s')
+
+__retval__ = ('boolean',str.isupper(val_s[1]))
+"
+  with _ do
+    return false.
+  end
+------------------------------------------------------------------
+function is_lowercase
+  with (s:%string) do return escape
+"
+global __retval__
+
+val_s = state.symbol_table.lookup_sym('s')
+
+__retval__ = ('boolean',str.islower(val_s[1]))
+"
+  with _ do
+    return false.
+  end
+------------------------------------------------------------------
+function is_alphanumeric
+  with (s:%string) do return escape
+"
+global __retval__
+
+val_s = state.symbol_table.lookup_sym('s')
+
+__retval__ = ('boolean',str.isalnum(val_s[1]))
+"
+  with _ do
+    return false.
+  end
+------------------------------------------------------------------
+-- Note: patterns are evaluated in the user context therefore we 
+-- cannot have module access in patterns, except the patterns module
+function _mod2 with n:%integer do math@mod(n,2) end
+function _isclose with n:%real do math@isclose(n, 0.0) end
+------------------------------------------------------------------
+-- Common number sets
+------------------------------------------------------------------
+let prime = pattern with %[ (n:%integer) if patterns@is_prime(n) ]%.
+let digit = pattern with %[ (n:%integer) if n >=0 and n <= 9 ]%.
+let pos_int = pattern with %[ (n:%integer) if n > 0 ]%.
+let neg_int = pattern with %[ (n:%integer) if n < 0 ]%.
+let pos_real = pattern with %[ (n:%real) if n > 0.0 ]%.
+let neg_real = pattern with %[ (n:%real) if n < 0.0 ]%.
+let positive = pattern with %[ n if (n is *patterns@pos_int) or (n is *patterns@pos_real) ]%.
+let negative = pattern with %[ n if (n is *patterns@neg_int) or (n is *patterns@neg_real) ]%.
+let nat = pattern with %[ (n:%integer) if n >= 0 ]%.
+let zero = pattern with %[ n if ((n is %real) and patterns@_isclose(n))
+                           or ((n is %integer) and (n == 0)) ]%.
+let odd = pattern with %[ (n:%integer) if patterns@_mod2(n) == 1 ]%.
+let even = pattern with %[ (n:%integer) if patterns@_mod2(n) == 0 ]%.
+------------------------------------------------------------------
+-- Containers
+------------------------------------------------------------------
+let int_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %integer) and acc, true)]%.
+let real_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %real) and acc, true)]%.
+let str_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %string) and acc, true)]%.
+let bool_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %boolean) and acc, true)]%.
+let func_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %function) and acc, true)]%.
+let list_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %list) and acc, true)]%.
+let tuple_list = pattern %[(l:%list) if l @reduce (lambda with (acc,i) do (i is %tuple) and acc, true)]%.
+------------------------------------------------------------------
+-- Strings
+------------------------------------------------------------------
+let char = pattern with %[ (s:%string) if (s@length() == 1) ]%.
+let alphabetic = pattern with %[ (s:%string) if patterns@is_alphabetic(s) ]%.
+let numeric = pattern with %[ (s:%string) if patterns@is_numeric(s) ]%.
+let alphanumeric = pattern with %[ (s:%string) if patterns@is_alphanumeric(s) ]%.
+let uppercase = pattern with %[ (s:%string) if patterns@is_uppercase(s) ]%.
+let lowercase = pattern with %[ (s:%string) if patterns@is_lowercase(s) ]%.
\ No newline at end of file
diff --git a/asteroid/modules/pick.ast b/asteroid/modules/pick.ast
index c1f2e79f..1273afc6 100644
--- a/asteroid/modules/pick.ast
+++ b/asteroid/modules/pick.ast
@@ -9,7 +9,7 @@
 load system random.
 
 ------------------------------------------------------------------
-structure __PICK__
+structure Pick
 ------------------------------------------------------------------
 -- A pick object holds a list of items that
 -- we can randomly pick from with the 'pickitems'
@@ -37,18 +37,12 @@ structure __PICK__
       let this @items = l.
   end
 
-end -- __PICK__
+end -- Pick
 
 ------------------------------------------------------------------
-structure __PICK_MODULE__
+function pick 
 ------------------------------------------------------------------
-with
-
-function pick with l:%list do
-   return __PICK__(l).
+with l:%list do
+   return Pick(l).
 end
 
-end -- __PICK_MODULE__
-
-------------------------------------------------------------------
-let pick = __PICK_MODULE__().
diff --git a/asteroid/modules/prologue.ast b/asteroid/modules/prologue.ast
index 8f8ceef1..a1bf737f 100644
--- a/asteroid/modules/prologue.ast
+++ b/asteroid/modules/prologue.ast
@@ -5,6 +5,9 @@
 --
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
+-- Note: this is just a file with definitions that need to wind 
+-- up in the global scope of the interpreter.
+
 
 ------------------------------------------------------------------
 structure Error
@@ -48,6 +51,7 @@ if item_val[0] in ['list','tuple','string']:
 elif item_val[0] == 'object':
     (OBJECT,
         (STRUCT_ID, (ID, name)),
+        (MEMBER_NAMES, (LIST, member_names)),
         (OBJECT_MEMORY, (LIST, object_memory))) = item_val
     l = len(data_only(object_memory))
     __retval__ = ('integer', l)
@@ -147,6 +151,234 @@ with
       end
 end
 
+------------------------------------------------------------------
+let __TP__ = pattern
+------------------------------------------------------------------
+-- pattern for selecting proper formatting body in 'tostring'
+with x if (x is %boolean) or
+         (x is %integer) or
+         (x is %string).
+
+------------------------------------------------------------------
+structure __STRINGFORMAT__
+------------------------------------------------------------------
+-- formatting object for 'tostring'
+with
+  data length.
+  data precision.
+  data scientific.
+  function __init__
+    with (l:%integer,p:%integer,s:%boolean) do
+      let this @length = l.
+      let this @precision = p.
+      let this @scientific = s.
+    with (l:%integer,p:%integer) do
+      let this @length = l.
+      let this @precision = p.
+      let this @scientific = none.
+    with l:%integer do
+      let this @length = l.
+      let this @precision = none.
+      let this @scientific = none.
+    end
+end
+
+------------------------------------------------------------------
+-- TYPE CONVERSION FUNCTIONS --
+------------------------------------------------------------------
+
+------------------------------------------------------------------
+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
+
+-- Note: we no longer support this, it encourages lazy programming
+-- by relying on the fuzzy concept of "truthiness"
+------------------------------------------------------------------
+-- function toboolean
+------------------------------------------------------------------
+-- with item do return escape
+-- "
+-- global __retval__
+--
+-- item_val = state.symbol_table.lookup_sym('item')
+-- __retval__ = map2boolean(item_val)
+-- "
+-- end
+
+------------------------------------------------------------------
+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__ = ('integer', int(item_val[1]))
+"
+end
+
+------------------------------------------------------------------
+function toreal
+------------------------------------------------------------------
+with item do return escape
+"
+global __retval__
+
+item_val = state.symbol_table.lookup_sym('item')
+__retval__ = ('real', float(item_val[1]))
+"
+end
+
+------------------------------------------------------------------
+function tostring
+------------------------------------------------------------------
+-- convert an asteroid object to string.
+-- if format values are given apply the
+-- formatting to the object.
+
+with (v:*__TP__,__STRINGFORMAT__(w:%integer,none,none)) do
+  -- booleans, integers, and strings (see TP pattern) with width spec are
+  -- right justified. if width spec is too narrow it is ignored.
+  let vs = tostring v.
+  let padl = w - vs @length().
+  if padl > 0 do
+    return [1 to padl] @map(lambda with _ do return " ") @join("") + vs.
+  else do
+    return vs.
+  end
+with (v:%real,__STRINGFORMAT__(w:%integer,none,none)) do return escape
+-- floating point values with only a width spec are left justified with
+-- zero padding on the right.
+"
+global __retval__
+(V_TYPE, v_val) = state.symbol_table.lookup_sym('v')
+(W_TYPE, w_val) = state.symbol_table.lookup_sym('w')
+
+fmtstr = '{:'+str(w_val)+'f}'
+__retval__ = ('string', fmtstr.format(v_val))
+"
+-- floating point values with a width and precision specs
+-- are formatted according to Python formatting rules
+with (v:%real,__STRINGFORMAT__(w:%integer,p:%integer,none)) do return escape
+"
+global __retval__
+(V_TYPE, v_val) = state.symbol_table.lookup_sym('v')
+(W_TYPE, w_val) = state.symbol_table.lookup_sym('w')
+(P_TYPE, p_val) = state.symbol_table.lookup_sym('p')
+
+fmtstr = '{:'+str(w_val)+'.'+str(p_val)+'f}'
+__retval__ = ('string', fmtstr.format(v_val))
+"
+-- floating point values with width, precision and scientific notation specs
+-- are formatted according to Python formatting rules
+with (v:%real,__STRINGFORMAT__(w:%integer,p:%integer,s:%boolean)) do return escape
+"
+global __retval__
+(V_TYPE, v_val) = state.symbol_table.lookup_sym('v')
+(W_TYPE, w_val) = state.symbol_table.lookup_sym('w')
+(P_TYPE, p_val) = state.symbol_table.lookup_sym('p')
+(S_TYPE, s_val) = state.symbol_table.lookup_sym('s')
+
+fmtstr = '{:'+str(w_val)+'.'+str(p_val)+('e}' if s_val else 'f}')
+__retval__ = ('string', fmtstr.format(v_val))
+"
+with item do return escape
+-- default clause
+"
+global __retval__
+from asteroid.support import term2string
+
+item_val = state.symbol_table.lookup_sym('item')
+__retval__ = ('string', term2string(item_val))
+"
+end
+
+------------------------------------------------------------------
+function stringformat
+------------------------------------------------------------------
+-- a wrapper around our __STRINGFORMAT__ object as a member
+-- of our module.
+with (l:%integer,p:%integer,s:%boolean) do
+  return __STRINGFORMAT__(l,p,s).
+with (l:%integer,p:%integer) do
+  return __STRINGFORMAT__(l,p).
+with l:%integer do
+  return __STRINGFORMAT__(l).
+end
+
+------------------------------------------------------------------
+-- TYPE QUERY FUNCTIONS --
+------------------------------------------------------------------
+
+------------------------------------------------------------------
+function islist
+------------------------------------------------------------------
+with item do
+  return item is %list
+end
+
+------------------------------------------------------------------
+function isnone
+------------------------------------------------------------------
+with x do
+  return x is %none.
+end
+
+------------------------------------------------------------------
+function isscalar
+------------------------------------------------------------------
+with item do
+  return (item is %integer) or (item is %real).
+end
+
+------------------------------------------------------------------
+function gettype
+------------------------------------------------------------------
+-- 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)), MEMBER_LIST, 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)
+"
+end
+
 ------------------------------------------------------------------
 -- List member functions
 ------------------------------------------------------------------
@@ -467,7 +699,11 @@ function __list_filter__
 with f:%function do
     let out = [].
     for e in this do
-        let out = out+([e] if f(e) else []).
+        let r = f e.
+        if gettype r =/= "boolean" do 
+          escape "raise ValueError('list filter function has to return a Boolean')"
+        end
+        let out = out+([e] if r else []).
     end
     return out.
 end
@@ -704,10 +940,7 @@ startix_val = state.symbol_table.lookup_sym('startix')
 endix_val = state.symbol_table.lookup_sym('endix')
 
 val = this_val[1].find(item_val[1], startix_val[1], endix_val[1])
-if val == -1:
-    __retval__ = ('none', None)
-else:
-    __retval__ = ('integer', val)
+__retval__ = ('integer', val)
 "
 with (item:%string,loc(startix:%integer,none)) do return escape
 "
@@ -718,10 +951,7 @@ item_val = state.symbol_table.lookup_sym('item')
 startix_val = state.symbol_table.lookup_sym('startix')
 
 val = this_val[1].find(item_val[1], startix_val[1])
-if val == -1:
-    __retval__ = ('none', None)
-else:
-    __retval__ = ('integer',val)
+__retval__ = ('integer',val)
 "
 with item:%string do return escape
 "
@@ -731,10 +961,7 @@ this_val = state.symbol_table.lookup_sym('this')
 item_val = state.symbol_table.lookup_sym('item')
 
 val = this_val[1].find(item_val[1])
-if val == -1:
-    __retval__ = ('none', None)
-else:
-    __retval__ = ('integer',val)
+__retval__ = ('integer',val)
 "
 end
 
diff --git a/asteroid/modules/random.ast b/asteroid/modules/random.ast
index 6deaedbf..806dccaa 100644
--- a/asteroid/modules/random.ast
+++ b/asteroid/modules/random.ast
@@ -6,11 +6,6 @@
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
-------------------------------------------------------------------
-structure __RANDOM_MODULE__
-------------------------------------------------------------------
-with
-
 ------------------------------------------------------------------
 function random
 ------------------------------------------------------------------
@@ -70,7 +65,3 @@ random.seed(sd_val[1])
 "
 end
 
-end -- __RANDOM_MODULE__
-
-------------------------------------------------------------------
-let random = __RANDOM_MODULE__().
diff --git a/asteroid/modules/set.ast b/asteroid/modules/set.ast
index af69f9a5..314b29be 100644
--- a/asteroid/modules/set.ast
+++ b/asteroid/modules/set.ast
@@ -8,11 +8,6 @@
 -- (c) Lutz Hamel, University of Rhode Island
 ------------------------------------------------------------------
 
-------------------------------------------------------------------
-structure __SET_MODULE__
-------------------------------------------------------------------
-with
-
 ------------------------------------------------------------------
 function diff
 ------------------------------------------------------------------
@@ -73,7 +68,3 @@ __retval__ = ('list', list(set(a_val[1]) ^ set(b_val[1])))
 "
 end
 
-end -- __SET_MODULE__
-
-------------------------------------------------------------------
-let set = __SET_MODULE__().
diff --git a/asteroid/modules/sort.ast b/asteroid/modules/sort.ast
index 33c04bd2..97b222a1 100644
--- a/asteroid/modules/sort.ast
+++ b/asteroid/modules/sort.ast
@@ -14,11 +14,8 @@
 ------------------------------------------------------------------
 
 ------------------------------------------------------------------
-structure __SORT_MODULE__
-------------------------------------------------------------------
-with
-
 function sort
+------------------------------------------------------------------
     with (_,[]) do
         return [].
     with (_,[a]) do
@@ -35,9 +32,6 @@ function sort
             end
         end
 
-        return this @sort(p,less) + [pivot] + this @sort(p,more).
-    end
-end -- __SORT_MODULE__
+        return sort(p,less) + [pivot] + sort(p,more).
+end
 
-------------------------------------------------------------------
-let sort = __SORT_MODULE__().
diff --git a/asteroid/modules/stream.ast b/asteroid/modules/stream.ast
index 020c3f0e..43c696ea 100644
--- a/asteroid/modules/stream.ast
+++ b/asteroid/modules/stream.ast
@@ -11,7 +11,7 @@
 load system util.
 
 ------------------------------------------------------------------
-structure __STREAM__
+structure Stream
 ------------------------------------------------------------------
 -- Asteroid stream implementation based on lists
 with
@@ -71,7 +71,7 @@ function rewind
     let this @curr_ix = 0.
   end
 
-function __string__
+function __str__
 with none do return
 escape
 "
@@ -83,25 +83,20 @@ this_val = state.symbol_table.lookup_sym('this')
 # destructure object
 (OBJECT,
  (STRUCT_ID, (ID, struct_id)),
+ (MEMBER_NAMES, (LIST, member_names)),
  (OBJECT_MEMORY, (LIST, memory))) = this_val
 
 __retval__ = ('string', term2string(memory[0]))
 "
 end
 
-end -- __STREAM__
+end -- Stream structure
 
 
 ------------------------------------------------------------------
-structure __STREAM_MODULE__
+function stream 
 ------------------------------------------------------------------
-with
-
-function stream with l:%list do
-   return __STREAM__(l).
+with l:%list do
+   return Stream(l).
 end
 
-end -- __STREAM_MODULE__
-
-------------------------------------------------------------------
-let stream = __STREAM_MODULE__().
diff --git a/asteroid/modules/type.ast b/asteroid/modules/type.ast
deleted file mode 100644
index a943504c..00000000
--- a/asteroid/modules/type.ast
+++ /dev/null
@@ -1,242 +0,0 @@
-------------------------------------------------------------------
--- type.ast
---
--- type related functions and structures
---
--- (c) University of Rhode Island
-------------------------------------------------------------------
-
-------------------------------------------------------------------
-let __TP__ = pattern
-------------------------------------------------------------------
--- pattern for selecting proper formatting body in 'tostring'
-with x if (x is %boolean) or
-         (x is %integer) or
-         (x is %string).
-
-------------------------------------------------------------------
-structure __STRINGFORMAT__
-------------------------------------------------------------------
--- formatting object for 'tostring'
-with
-  data length.
-  data precision.
-  data scientific.
-  function __init__
-    with (l:%integer,p:%integer,s:%boolean) do
-      let this @length = l.
-      let this @precision = p.
-      let this @scientific = s.
-    with (l:%integer,p:%integer) do
-      let this @length = l.
-      let this @precision = p.
-      let this @scientific = none.
-    with l:%integer do
-      let this @length = l.
-      let this @precision = none.
-      let this @scientific = none.
-    end
-end
-
-
-------------------------------------------------------------------
-structure __TYPE_MODULE__ with
-
-------------------------------------------------------------------
--- TYPE CONVERSION FUNCTIONS --
-------------------------------------------------------------------
-
-------------------------------------------------------------------
-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
-
-------------------------------------------------------------------
-function toboolean
-------------------------------------------------------------------
-with item do return escape
-"
-global __retval__
-
-item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('boolean', bool(item_val[1]))
-"
-end
-
-------------------------------------------------------------------
-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__ = ('integer', int(item_val[1]))
-"
-end
-
-------------------------------------------------------------------
-function toreal
-------------------------------------------------------------------
-with item do return escape
-"
-global __retval__
-
-item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('real', float(item_val[1]))
-"
-end
-
-------------------------------------------------------------------
-function tostring
-------------------------------------------------------------------
--- convert an asteroid object to string.
--- if format values are given apply the
--- formatting to the object.
-
-with (v:*__TP__,__STRINGFORMAT__(w:%integer,none,none)) do
-  -- booleans, integers, and strings (see TP pattern) with width spec are
-  -- right justified. if width spec is too narrow it is ignored.
-  let vs = this @tostring(v).
-  let padl = w - vs @length().
-  if padl > 0 do
-    return [1 to padl] @map(lambda with _ do return " ") @join("") + vs.
-  else do
-    return vs.
-  end
-with (v:%real,__STRINGFORMAT__(w:%integer,none,none)) do return escape
--- floating point values with only a width spec are left justified with
--- zero padding on the right.
-"
-global __retval__
-(V_TYPE, v_val) = state.symbol_table.lookup_sym('v')
-(W_TYPE, w_val) = state.symbol_table.lookup_sym('w')
-
-fmtstr = '{:'+str(w_val)+'f}'
-__retval__ = ('string', fmtstr.format(v_val))
-"
--- floating point values with a width and precision specs
--- are formatted according to Python formatting rules
-with (v:%real,__STRINGFORMAT__(w:%integer,p:%integer,none)) do return escape
-"
-global __retval__
-(V_TYPE, v_val) = state.symbol_table.lookup_sym('v')
-(W_TYPE, w_val) = state.symbol_table.lookup_sym('w')
-(P_TYPE, p_val) = state.symbol_table.lookup_sym('p')
-
-fmtstr = '{:'+str(w_val)+'.'+str(p_val)+'f}'
-__retval__ = ('string', fmtstr.format(v_val))
-"
--- floating point values with width, precision and scientific notation specs
--- are formatted according to Python formatting rules
-with (v:%real,__STRINGFORMAT__(w:%integer,p:%integer,s:%boolean)) do return escape
-"
-global __retval__
-(V_TYPE, v_val) = state.symbol_table.lookup_sym('v')
-(W_TYPE, w_val) = state.symbol_table.lookup_sym('w')
-(P_TYPE, p_val) = state.symbol_table.lookup_sym('p')
-(S_TYPE, s_val) = state.symbol_table.lookup_sym('s')
-
-fmtstr = '{:'+str(w_val)+'.'+str(p_val)+('e}' if s_val else 'f}')
-__retval__ = ('string', fmtstr.format(v_val))
-"
-with item do return escape
--- default clause
-"
-global __retval__
-from asteroid.support import term2string
-
-item_val = state.symbol_table.lookup_sym('item')
-__retval__ = ('string', term2string(item_val))
-"
-end
-
-------------------------------------------------------------------
-function stringformat
-------------------------------------------------------------------
--- a wrapper around our __STRINGFORMAT__ object as a member
--- of our module.
-with (l:%integer,p:%integer,s:%boolean) do
-  return __STRINGFORMAT__(l,p,s).
-with (l:%integer,p:%integer) do
-  return __STRINGFORMAT__(l,p).
-with l:%integer do
-  return __STRINGFORMAT__(l).
-end
-
-------------------------------------------------------------------
--- TYPE QUERY FUNCTIONS --
-------------------------------------------------------------------
-
-------------------------------------------------------------------
-function islist
-------------------------------------------------------------------
-with item do
-  return item is %list
-end
-
-------------------------------------------------------------------
-function isnone
-------------------------------------------------------------------
-with x do
-  return x is %none.
-end
-
-------------------------------------------------------------------
-function isscalar
-------------------------------------------------------------------
-with item do
-  return (item is %integer) or (item is %real).
-end
-
-------------------------------------------------------------------
-function gettype
-------------------------------------------------------------------
--- 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)
-"
-end
-
-end -- __TYPE_MODULE__
-
-------------------------------------------------------------------
-let type = __TYPE_MODULE__().
diff --git a/asteroid/modules/util.ast b/asteroid/modules/util.ast
index 7698a8ff..72cac777 100644
--- a/asteroid/modules/util.ast
+++ b/asteroid/modules/util.ast
@@ -6,13 +6,6 @@
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
-load system type.
-
-------------------------------------------------------------------
-structure __UTIL_MODULE__ 
-------------------------------------------------------------------
-with
-
 ------------------------------------------------------------------
 function achar
 ------------------------------------------------------------------
@@ -85,7 +78,7 @@ end
 function sleep
 ------------------------------------------------------------------
 -- program sleep for secs seconds
-with secs if type @isscalar(secs) do escape
+with secs if isscalar secs do escape
 "
 from time import sleep
 secs_val = state.symbol_table.lookup_sym('secs')
@@ -150,7 +143,3 @@ __retval__ = ('list', out_list)
 "
 end
 
-end -- __UTIL_MODULE__
-
-------------------------------------------------------------------
-let util = __UTIL_MODULE__().
diff --git a/asteroid/modules/vector.ast b/asteroid/modules/vector.ast
index 4d00802a..29062512 100644
--- a/asteroid/modules/vector.ast
+++ b/asteroid/modules/vector.ast
@@ -7,16 +7,12 @@
 ------------------------------------------------------------------
 
 load system util.
-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).
+  return op(lambda with (x,y) do x+y,a,b).
 end
 
 ------------------------------------------------------------------
@@ -24,14 +20,14 @@ 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).
+  return mult(a,b) @reduce(lambda with (x,y) do x+y).
 end
 
 ------------------------------------------------------------------
 function mult
 ------------------------------------------------------------------
 with (a,b) do
-  return this @op(lambda with (x,y) do return x*y,a,b).
+  return op(lambda with (x,y) do x*y,a,b).
 end
 
 ------------------------------------------------------------------
@@ -41,18 +37,18 @@ function op
 -- Note: it also implements vector/scalar arithmetic
 with (f:%function,a:%list,b:%list) do
   if a @length() =/= b @length() do
-      throw Error("vops only defined on lists of the same length").
+      throw Error("vector operations only defined on lists of the same length").
   end
   let v = util @zip(a,b).
   return v @map(f).
-with (f:%function,a:%list,b if type @isscalar(b)) do
+with (f:%function,a:%list,b if isscalar b) do
   -- promote b to a vector
-  let bv = [1 to a @length()] @map(lambda with _ do return b).
+  let bv = [1 to a @length()] @map(lambda with _ do b).
   let v = util @zip(a,bv).
   return v @map(f).
-with (f:%function,a if type @isscalar(a),b:%list) do
+with (f:%function,a if isscalar a,b:%list) do
   -- promote a to a vector
-  let av = [1 to b @length()] @map(lambda with _ do return a).
+  let av = [1 to b @length()] @map(lambda with _ do a).
   let v = util @zip(av,b).
   return v @map(f).
 end
@@ -61,10 +57,7 @@ end
 function sub
 ------------------------------------------------------------------
 with (a,b) do
-  return this @op(lambda with (x,y) do return x-y,a,b).
+  return op(lambda with (x,y) do x-y,a,b).
 end
 
 
-end -- __VECTOR_MODULE__
-
-let vector = __VECTOR_MODULE__().
diff --git a/asteroid/programs/cls.ast b/asteroid/programs/cls.ast
deleted file mode 100755
index 65db2f63..00000000
--- a/asteroid/programs/cls.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/usr/bin/env asteroid
-load system io.
-load system util.
-load system random.
-
-util @cls().
-
-for i in 1 to 5 do
-    io @println ("Random value " + random @random()).
-    util @sleep(0.5)
-end
diff --git a/asteroid/programs/df.ast b/asteroid/programs/df.ast
deleted file mode 100644
index d1bbb44d..00000000
--- a/asteroid/programs/df.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-load system dataframe.
-load system io.
-
-let df = dataframe @dataframe().
-df@read_csv("tennis.csv",true).
-
-let r = df@row(3).
-io @println(r).
-
-let c = df@col(3).
-io @println(c).
diff --git a/asteroid/programs/family.ast b/asteroid/programs/family.ast
deleted file mode 100644
index 51c450b9..00000000
--- a/asteroid/programs/family.ast
+++ /dev/null
@@ -1,75 +0,0 @@
--- a small program that demonstrates that patterns can be used both
--- for constructing as well as destructuring of object networks.
-
-load system io.
-
------------------------------
-structure Family
------------------------------
-  with
-    data parent1.
-    data parent2.
-    data children.
-
-    function __init__
-      with (p1:%Parent,p2:%Parent,c:%Children) do
-        let this @parent1 = p1.
-        let this @parent2 = p2.
-        let this @children = c.
-      end
-  end
-
------------------------------
-structure Parent
------------------------------
-  with
-    data name.
-    function __init__
-      with name:%string do
-        let this @name = name
-      end
-  end
-
------------------------------
-structure Children
------------------------------
-  with
-    data list.
-
-    function __init__
-      with list:%list do
-        let this @list = list.
-      end
-  end
-
------------------------------
-let FP = pattern
------------------------------
-  with Family(Parent(p1),Parent(p2),Children(c)).
-
------------------------------
-function construct_family
------------------------------
-  with (P,p1,p2,c) do
-    return eval(P).  -- run pattern in reverse, construct object network.
-  end
-
------------------------------
-function destructure_family
------------------------------
-  with (P,term) do
-    let *P = term.   -- pattern match, destructure object network.
-    return [p1,p2]+c.
-  end
-
------------------------------
--- construct families
------------------------------
-let f1 = construct_family(FP,"Harry","Bridget",["Sue","Peter"]).
-let f2 = construct_family(FP,"Margot","Selma",["Latisha","Rudolf"]).
-
------------------------------
--- destructure families
------------------------------
-io @println(destructure_family(FP,f1)).
-io @println(destructure_family(FP,f2)).
diff --git a/asteroid/programs/run-all.py b/asteroid/programs/run-all.py
deleted file mode 100755
index 748b78df..00000000
--- a/asteroid/programs/run-all.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/env python
-# coding: utf-8
-
-# run all program
-
-
-import sys
-import os
-import glob
-
-# Get the path of this run-tests.py file
-file_path = os.path.dirname(os.path.abspath( __file__ ))
-
-# Temporarly change the working directory to that path
-os.chdir(file_path)
-
-# Set the path to the code directory
-sys.path[0] = "../"
-
-from asteroid.interp import interp
-
-programs = glob.glob("*.ast")
-programs.sort()
-
-for pname in programs:
-    f = open(pname,"r")
-    p = f.read()
-    print("**********"+pname+"************")
-    print(p)
-    print("**********output***********")
-    interp(p)
-    f.close()
diff --git a/asteroid/programs/tennis.csv b/asteroid/programs/tennis.csv
deleted file mode 100644
index f83b6b83..00000000
--- a/asteroid/programs/tennis.csv
+++ /dev/null
@@ -1,15 +0,0 @@
-outlook,temp,humidity,windy,play
-sunny,hot,high,false,no
-sunny,hot,high,true,no
-overcast,hot,high,false,yes
-rainy,mild,high,false,yes
-rainy,cool,normal,false,yes
-rainy,cool,normal,true,no
-overcast,cool,normal,true,yes
-sunny,mild,high,false,no
-sunny,cool,normal,false,yes
-rainy,mild,normal,false,yes
-sunny,mild,normal,true,yes
-overcast,mild,high,true,yes
-overcast,hot,normal,false,yes
-rainy,mild,high,true,no
diff --git a/asteroid/repl.py b/asteroid/repl.py
index 96939fff..ef96941a 100644
--- a/asteroid/repl.py
+++ b/asteroid/repl.py
@@ -11,7 +11,7 @@
 from asteroid.walk import function_return_value
 from asteroid.support import term2string
 
-from sys import stdin
+from sys import stdin,exit
 import platform
 
 if platform.system() == 'Windows':
@@ -23,24 +23,21 @@ def repl(new=True, redundancy=False, prologue=False, functional_mode=False):
 
     if new:
         state.initialize()
-        load_prologue()
+        if prologue:
+            load_prologue()
         print_repl_menu()
     try:
-        run_repl(redundancy, prologue, functional_mode)
+        run_repl(redundancy, functional_mode)
     except EOFError:
         print()
         pass
 
 def print_repl_menu():
-    print("Asteroid Version", VERSION)
+    print("Asteroid", VERSION)
     print("(c) University of Rhode Island")
-    print("Type \"asteroid -h\" for help")
-    if platform.system() == 'Windows':
-        print("Press CTRL-Z + Return to exit")
-    else:
-        print("Press CTRL-D to exit")
+    print("Type \"help\" for additional information")
 
-def run_repl(redundancy, prologue, functional_mode):
+def run_repl(redundancy, functional_mode):
 
     # The two different prompt types either > for a new statement
     # or . for continuing one
@@ -51,9 +48,7 @@ def run_repl(redundancy, prologue, functional_mode):
     # Our line to be interpreted
     line = ""
     while True:
-        """
-        Line input, breaking, and exiting
-        """
+        ### Line input, breaking, and exiting
         try:
             # Get the new input and append it to the previous line (Possibly empty)
             # with a newline in between
@@ -66,6 +61,22 @@ def run_repl(redundancy, prologue, functional_mode):
             else:
                 line += "\n" + input(current_prompt)
 
+            # see if we are looking at native repl commands
+            if line in ["help","quit"]:
+                match line:
+                    case "help":
+                        print()
+                        print("help          -- this message")
+                        print("quit          -- leave the Asteroid interpreter")
+                        print("load \"<file>\" --  load and run the program in <file>")
+                        print()
+                        print("or type any valid Asteroid statement at the prompt")
+                        print()
+                        line = ""
+                    case "quit":
+                        exit(0)
+                continue
+
         except KeyboardInterrupt:
             line = ""
             current_prompt = arrow_prompt
@@ -76,15 +87,13 @@ def run_repl(redundancy, prologue, functional_mode):
             print()
             break
 
-        """
-        Interpretation, multiline input, and exception handling
-        """
+        ### Interpretation, multiline input, and exception handling
         try:
             # Try to interpret the new statement
             interp(line,
                    initialize_state=False,
                    redundancy=redundancy,
-                   prologue=prologue,
+                   prologue=False, # prologue is managed by repl above
                    functional_mode=functional_mode,
                    exceptions=True)
 
@@ -95,11 +104,9 @@ def run_repl(redundancy, prologue, functional_mode):
             if function_return_value[-1]:
                 # Get the last return value (type, value)
                 retval = function_return_value[-1]
-
                 # If it isn't none, print out the value
                 if retval[1] != None:
                     print(term2string(function_return_value[-1]))
-
                     # Reset the return value
                     function_return_value[0] = None
 
diff --git a/asteroid/state.py b/asteroid/state.py
index f32a7157..7b89e664 100644
--- a/asteroid/state.py
+++ b/asteroid/state.py
@@ -11,13 +11,11 @@ def __init__(self):
         self.initialize()
 
     def initialize(self,module="<input>"):
+        self.mainmodule = None
         self.symbol_table = SymTab()
-        self.modules = [] # loaded modules
         self.AST = None
-        self.ignore_pattern = 0 # used to evaluate pattern expressions
-        self.cond_warning = False # used to indicate if conditional subsumption
-                                  # warning has been displayed
         self.eval_redundancy = True
+        self.warning = True # switch for general warnings
         self.lineinfo = (module, 1) # tuple: module, lineno
         # stack of 3-tuples for stack trace of function
         # calls: (module,lineno,function name)
@@ -26,12 +24,14 @@ def initialize(self,module="<input>"):
         # it.  an exception handler is responsible for clearing
         # this.
         self.error_trace = None
+        self.debugger = None
 
 state = State()
 
 def warning(str):
-    module, lineno = state.lineinfo
-    print("Warning: {}: {}: {}".format(module, lineno, str))
+    if state.warning:
+        module, lineno = state.lineinfo
+        print("Warning: {}: {}: {}".format(module, lineno, str))
 
 def dump_trace():
     if state.error_trace:
diff --git a/asteroid/support.py b/asteroid/support.py
index 687bcb62..7401c6c3 100644
--- a/asteroid/support.py
+++ b/asteroid/support.py
@@ -5,6 +5,7 @@
 ###########################################################################################
 
 import re
+import sys
 
 from asteroid.state import state
 
@@ -20,6 +21,11 @@ def gettemp():
     return new_name
 
 ###########################################################################################
+__dump_level = sys.maxsize  # during debugging you can set this to limit tree dump size
+
+def set_AST_dump_level(n):
+    __dump_level = n
+
 def dump_AST(node):
     '''
     this function will print any AST that follows the
@@ -32,7 +38,8 @@ def dump_AST(node):
     print('')
 
 def _dump_AST(node, level=0):
-
+    if level > __dump_level:
+        return
     if isinstance(node, tuple):
         _indent(level)
         nchildren = len(node) - 1
@@ -119,13 +126,8 @@ def promote(type1, type2):
         return 'list'
     elif type1 == 'tuple' and type2 == 'tuple':
         return 'tuple'
-    elif type1 == 'none' and type2 == 'none':
-        return 'none'
     else:
-        if type1 == type2:
-            raise ValueError("binary operation on type '{}' not supported".format(type1))
-        else:
-            raise ValueError("type '{}' and type '{}' are incompatible".format(type1, type2))
+        return 'none'
 
 ###########################################################################################
 # Asteroid uses truth values similar to Python's Pythonic truth values:
@@ -187,8 +189,23 @@ def data_ix_list(memory):
     return ix_list
 
 ###########################################################################################
-# term2string is an unparsing function mapping AST into a string
-# it supports as much unparsing as is currently needed.
+def to_python_list(asteroid_list):
+    '''
+    convert a list from Asteroid list or tuple AST format into a standard Python list.
+    ex. ('list',[('integer',1),('integer',2)])   =>   [1,2]
+    '''
+    output = []
+    
+    for (_type,val) in asteroid_list[1]:
+        output.append(val)
+        
+    return output
+
+###########################################################################################
+# term2string is an unparsing function mapping AST snippets representing **values** into 
+# a Python string
+#
+# DO NOT attempt to make this into a general AST unparser!
 
 # the following two tables are used in format processing of strings
 # in term2string to support "\\", "\n", "\t", and "\"" characters.
@@ -203,7 +220,8 @@ def data_ix_list(memory):
 
 def term2string(term):
     TYPE = term[0]
-
+    #lhh
+    #print(term)
     if TYPE == 'string':
         val = term[1]
         output_str = ""
@@ -211,8 +229,6 @@ def term2string(term):
         for mo in match_object_list:
             type = mo.lastgroup
             value = mo.group()
-            #lhh
-            #print(type)
             if type == 'BS2':
                 output_str += "\\"
             elif type == 'NL':
@@ -228,7 +244,7 @@ def term2string(term):
                                  .format(type))
         return output_str
 
-    elif TYPE in ['id', 'integer', 'real']:
+    elif TYPE in ['integer', 'real']:
         val = term[1]
         return str(val)
 
@@ -252,25 +268,15 @@ def term2string(term):
     elif TYPE == 'object':
         (OBJECT,
          (STRUCT_ID, (ID, struct_id)),
+         (MEMBER_NAMES, (LIST, member_names)),
          (OBJECT_MEMORY, (LIST, object_memory))) = term
 
-        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 asteroid.walk
-            # for some reason we have to reinitialize unify again
-            if asteroid.walk.debugging:
-                asteroid.walk.unify = asteroid.walk.debug_unify
-            else:
-                asteroid.walk.unify = asteroid.walk.__unify
             (STRING, obj_str) = asteroid.walk.handle_call(term, # object reference
                                     str_fval,
                                     ('none', None),
@@ -288,161 +294,6 @@ def term2string(term):
     elif TYPE in ['function-val', 'member-function-val']:
         return '(function ...)'
 
-    elif TYPE == 'apply':
-        (APPLY, f, args) = term
-        operator_table = {
-            '__uminus__'    : ("-", True),
-            '__uplus__'     : ("+", True),
-            '__not__'       : ("not ", True),
-            '__plus__'      : ("+", False),
-            '__minus__'     : ("-", False),
-            '__times__'     : ("*", False),
-            '__divide__'    : ("/", False),
-            '__or__'        : (" or ", False),
-            '__and__'       : (" and ", False),
-            '__eq__'        : (" == ", False),
-            '__ne__'        : (" != ", False),
-            '__le__'        : (" <= ", False),
-            '__lt__'        : (" < ", False),
-            '__ge__'        : (" >= ", False),
-            '__gt__'        : (" > ", False)
-        }
-        if isinstance(f[1], str) and f[1] in operator_table:
-            (op_symbol, is_unary) = operator_table[f[1]]
-            if is_unary:
-                term_string = "{}({})".format(
-                    op_symbol, term2string(args)
-                )
-            else:
-                (_, arglist) = args
-                term_string = "{}{}{}".format(
-                    term2string(arglist[0]), op_symbol, term2string(arglist[1])
-                )
-        else:
-            term_string = term2string(f)
-            term_string += term2string(args)
-
-        return term_string
-
-    elif TYPE == 'pattern':
-        # we are printing out a term - just ignore the pattern operator
-        val = term[1]
-        return term2string(val)
-
-    elif TYPE == 'nil':
-        return ''
-
-    elif TYPE == 'head-tail':           # Handle a head-tail pattern
-        length = head_tail_length(term)
-        term_string = "["
-        for ix in range(1,length):
-
-            #update output text with each entry in head-tail list
-            term_string += term2string(term[1])
-
-            #step down the head-tail tree
-            term = term[2]
-
-            #Insert head-tail entry delimiter
-            term_string+= "|"
-
-            #Catch the last entry
-            if (ix == (length-1)):
-                term_string += term2string(term)
-
-        #Put the head-tail list delimiter on the end and then return
-        term_string += "]"
-        return term_string
-
-    elif TYPE == 'raw-head-tail':
-        (RHT, e1, e2) = term
-        walked_e1 = term2string(e1)
-        walked_e2 = term2string(e2)
-
-        return walked_e1 + "|" + walked_e2
-
-    elif TYPE == 'typematch':           # Handle a type pattern
-        (TYPECLASS,cType) = term
-        term_string = '%'
-        term_string += cType
-        return term_string
-
-    elif TYPE == 'constraint':          # Handle a constraint-only pattern
-        (CONSTRAINT,ptrn,bl) = term
-        term_string = '%['
-        term_string += term2string(ptrn)
-        term_string += ']%'
-        if bl[0] != 'nil':
-            term_string += '(binding list...)'
-        return term_string
-
-    elif TYPE == 'deref':               # Handle a first-class pattern
-        (DEREF, d_exp, binding_list) = term
-        term_string = "*" + term2string(d_exp)
-
-        #Get the actual pattern from the symbol table
-        # NOTE: THIS BREAKS WHEN A PATTERN IS NOT DEFINED IN SCOPE
-        # TODO: FIX THIS
-        # NOTE: this is NOT possible in the general case because the 
-        # pattern could be produced by a function call: *foo()
-        # \/\/\/\/\/\/\/\/\/
-        #term_string += term2string(state.symbol_table.lookup_sym(pName))
-
-        if binding_list[0] != 'nil':
-            term_string += '(binding list...)'
-
-        return term_string
-
-    elif TYPE == 'if-exp':              # Handle a conditional pattern
-        (IF_EXP,EXPRESSION,value,NULL) = term
-        # conditions can be arbitrary computations not structural terms
-        # therefore we don't print the whole tree.
-        return term2string(value)+' if (condition...)'
-
-    elif TYPE == 'index':
-        (INDEX, base, ix) = term
-        return term2string(base) + "@ " + term2string(ix)
-
-    elif TYPE == 'foreign':
-        return "(foreign ...)"
-
-    elif TYPE == 'is':
-        (IS, e1, e2) = term
-
-        return term2string(e1) + " is " + term2string(e2)
-
-    elif TYPE == 'in':
-        (IN, e1, e2) = term
-
-        return term2string(e1) + " in " + term2string(e2)
-
-    elif TYPE == 'to-list':
-        (TO_LIST, (START, start), (STOP, stop), (STRIDE, stride)) = term
-        return "[" + term2string(start) + " to " + term2string(stop) + ", stride: " + term2string(stride) + "]"
-
     else:
         return '('+TYPE+'...)'
 
-##############################################################################################
-# Function head_tail_length determines the lenth of a head-tail node by walking to the end.
-# The length is then returned from this function as in integer.
-# Example Input : [h1|h2|h3|tail]
-#         Output: 3
-# The output is 3 because the input heal-tail pattern has 3 heads.
-#
-def head_tail_length( node ):
-
-    # Counter to hold length of head-tail node
-    ctr = 1
-
-    # Try to walk down the tree, incrementing the counter
-    # return the counter when we fail
-    while(1):
-        try:
-            node = node[2]
-        except:
-            return ctr
-        else:
-            ctr += 1
-
-##############################################################################################
diff --git a/asteroid/symtab.py b/asteroid/symtab.py
index 71e70797..440c9c20 100644
--- a/asteroid/symtab.py
+++ b/asteroid/symtab.py
@@ -57,18 +57,18 @@ def pop_scope(self):
             self.globals.pop(CURR_SCOPE)
             return scope
 
-    def get_curr_scope(self, option="items"):
+    def get_curr_scope(self, scope=CURR_SCOPE, option="items"):
         if option == "items":
-            return list(self.scoped_symtab[CURR_SCOPE].items())
+            return list(self.scoped_symtab[scope].items())
         elif option == "unifiers":
             unifiers = []
-            for (sym,val) in self.scoped_symtab[CURR_SCOPE].items():
+            for (sym,val) in self.scoped_symtab[scope].items():
                 unifiers += [(('id',sym),val)]
             return unifiers
         elif option == "keys":
-            return list(self.scoped_symtab[CURR_SCOPE].keys())
+            return list(self.scoped_symtab[scope].keys())
         elif option == "values":
-            return list(self.scoped_symtab[CURR_SCOPE].values())
+            return list(self.scoped_symtab[scope].values())
         else:
             raise ValueError("unknown option")
 
diff --git a/asteroid/version.py b/asteroid/version.py
index 4480a7ef..46a499de 100644
--- a/asteroid/version.py
+++ b/asteroid/version.py
@@ -5,4 +5,6 @@
 # (c) University of Rhode Island
 ##########################################################################################
 
-VERSION = "2.0.0"
+VERSION = "2.0.1"
+MAD_VERSION = "0.0.1"
+
diff --git a/asteroid/walk.py b/asteroid/walk.py
index 7df88bd1..188ea3a4 100644
--- a/asteroid/walk.py
+++ b/asteroid/walk.py
@@ -6,20 +6,12 @@
 
 from copy import deepcopy,copy
 from re import match as re_match
+from math import isclose
 
 from asteroid.globals import *
 from asteroid.support import *
 from asteroid.state import state, warning
 
-#########################################################################
-# These two variables are used by the debugger. "Debugging" is a flag
-# to tell if we're currently in debugging mode and "Debugger" is a
-# debugger object. For more information on the debugger's helper
-# functions. See the function definitions in this file.
-#########################################################################
-debugging = False
-debugger = None
-
 #########################################################################
 # this dictionary maps list member function names to function
 # implementations given in the Asteroid prologue.
@@ -42,54 +34,47 @@
 function_return_value = [None]
 
 ###########################################################################################
-def __unify(term, pattern, unifying = True ):
+def unify(term, pattern, unifying = True ):
     '''
     unify term and pattern recursively and return the unifier.
-    this unification allows for the same variable to appear
-    multiple times in the unifier.  the user of this
-    function must take appropriate actions if this happens.
 
-    we assume that both the term and the pattern are made up of tuple
+    we assume that both the term and the pattern are made up of AST tuple
     nodes:
 
              (<type>, children*)
 
-    leaf nodes must be nullary constructors.
-
     NOTE: if the pattern looks like an lval then it is treated like an lval, e.g.
-            let a@[0] = 'a@[0].
-          stores the term 'a@[0] into lval a@[0].
+            let a@[0] = a@[0].
+          stores the value stored at a@[0] into lval a@[0].
     NOTE: Default argument unifying is set to be true. If we are unifying, then we are
-          evaluating unification between a pattern and a term. If we are not
+          evaluating unification/matching between a pattern and a term. If we are not
           unifying, then we are evaluating subsumption between two patterns for the
           purpose of detecting redundant/useless pattern clauses in functions.
+    NOTE: The tests (if/elif clauses) are ordered:
+            1. Python instance level matching
+            2. Special match cases for terms and patterns
+            3. AST structural matching
     '''
 
-    ### Python value level matching
+    ################################
+    ### 1. Python instance level matching
     # NOTE: in the first rules where we test instances we are comparing
     # Python level values, if they don't match exactly then we have
     # a pattern match fail.
-    if isinstance(term, str): # apply regular expression match
-        if debugging: message_explicit("Regex match: {} and {}", [pattern, term], level="secondary")
-
+    if isinstance(term, str): 
+        # apply regular expression match
+        # Note: a pattern needs to match the whole term.
         if isinstance(pattern, str) and re_match("^"+pattern+"$", term):
-            # Note: a pattern needs to match the whole term.
-            if debugging: message_explicit("Matched!", level="tertiary")
             return [] # return empty unifier
         else:
-            if debugging: message_explicit("Failed!", level="tertiary")
             raise PatternMatchFailed(
                 "regular expression '{}' did not match '{}'"
                 .format(pattern, term))
-
+                
     elif isinstance(term, (int, float, bool)):
-        if debugging: message_explicit("Literal match: {} and {}", [pattern, term], level="primary")
-
         if term == pattern:
-            if debugging: message_explicit("Matched!", level="secondary")
             return [] # return an empty unifier
         else:
-            if debugging: message_explicit("Failed! {} != {}", [pattern, term], level="secondary")
             raise PatternMatchFailed(
                 "'{}' is not the same as '{}'"
                 .format(term, pattern))
@@ -102,467 +87,213 @@ def __unify(term, pattern, unifying = True ):
             raise PatternMatchFailed(
                 "term and pattern lists/tuples are not the same length")
         else:
-            if debugging: message_explicit("Matching lists: {} and {}",
-                [term2string( ('list', pattern) ), term2string( ('list', term) )],
-                increase=True, notify=True)
-
             # Make our unifier(s)
             unifier = []
             for i in range(len(term)):
                 unifier += unify(term[i], pattern[i], unifying)
-
-            if debugging: message_explicit("Matched!", decrease=True)
-
             # Ensure we have no non-linear patterns
             check_repeated_symbols(unifier)
-
             return unifier
     
-    elif ((not unifying) and (term[0] == 'deref')):
-
-        # Unpack a term-side first-class pattern if evaluating redundant clauses
-        term_pattern = walk(term[1])
-        return unify(term_pattern, pattern, unifying)
-
-    ### Asteroid value level matching
-    elif pattern[0] == 'object' and term[0] == 'object':
-        # this can happen when we dereference a variable pointing
-        # to an object as a pattern, e.g.
-        #    let o = A(1,2). -- A is a structure with 2 data members
-        #    let *o = o.
-        (OBJECT, (STRUCT_ID, (ID, pid)), (OBJECT_MEMORY, (LIST, pl))) = pattern
-        (OBJECT, (STRUCT_ID, (ID, tid)), (OBJECT_MEMORY, (LIST, tl))) = term
-        if pid != tid:
-            raise PatternMatchFailed(
-                "pattern type '{}' and term type '{}' do not agree"
-                .format(pid,tid))
-
-        if debugging: message_explicit("Matching objects {}{} and {}{}",
-            [pid, term2string( ('tuple', pl) ), tid, term2string( ('tuple', tl) )],
-            increase=True
-        )
+    #################################
+    ### 2. Special match cases for terms and patterns
+    # Asteroid value level matching
+    elif (not unifying) and (pattern[0] == 'deref' or term[0] == 'deref'):
+        # since first-class patterns are almost always conditional
+        # patterns and conditional patterns are not supported by
+        # the redundancy test we punt here and save computation time.
+        raise PatternMatchFailed(
+            "first-class patterns not supported.")
 
-        unifiers = []
+    elif (not unifying) and (pattern[0] == 'typematch' or term[0] == 'typematch'):
+        raise PatternMatchFailed(
+                "typematch patterns not supported")
 
-        for i in range(len(pl)):
-            # OWM: We can't actually unify function-vals. If we know the type is
-            # the same, can we just assume the function-val is the same?
-            notify_explicit()
+    elif (not unifying) and (pattern[0] == 'if-exp' or term[0] == 'if-exp'):
+        # conditional patterns are not supported in redundancy
+        # test because they can involved arbitraty computations
+        # which cannot be tested.
+        raise PatternMatchFailed(
+            "conditional patterns not supported.")
 
-            if tl[i][0] != 'function-val':
-                unifiers += unify(tl[i], pl[i])
-        
-        if debugging: message_explicit("Objects matched", decrease=True)
-        return unifiers
+    elif (not unifying) and (pattern[0] in ['head-tail', 'raw-head-tail'] or 
+             term[0] in ['head-tail', 'raw-head-tail']):
+        raise PatternMatchFailed(
+            "head-tail operator not supported")
 
-    # 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 {}",
-    #        [term2string(pattern), term2string(term)],
-    #        notify=True
-    #    )
-    #
-    #    return unify(term2string(term), pattern[1])
+    elif (not unifying) and pattern[0] == 'apply' and term[0] == 'apply':
+        fp = pattern[1]
+        ft = term[1]
+        if fp[0] != 'id' or ft[0] != 'id':
+            raise ValueError("pattern subsumption not supported")
+        # unpack the apply structures
+        (APPLY, (ID, t_id), t_arg) = term
+        (APPLY, (ID, p_id), p_arg) = pattern
+        # only constructors are allowed in patterns
+        type = state.symbol_table.lookup_sym(t_id,strict=False)
+        if not type or type[0] != 'struct':
+            raise ValueError(
+                    "illegal pattern: function or operator '{}' not supported"
+                    .format(t_id))
+        type = state.symbol_table.lookup_sym(p_id,strict=False)
+        if not type or type[0] != 'struct':
+            raise ValueError(
+                    "illegal pattern: function or operator '{}' not supported"
+                    .format(p_id))
+        # make sure apply id's match
+        if t_id != p_id:
+            raise PatternMatchFailed(
+                "term '{}' does not match pattern '{}'"
+                .format(t_id, p_id))
+        # unify the args
+        return unify(t_arg, p_arg, unifying)
 
-    elif pattern[0] == 'if-exp':
+    elif term[0] in (unify_not_allowed - {'function-val', 'foreign'}):
+        # NOTE: functions/foreign are allowed in terms as long as they are matched
+        # by a variable in the pattern - anything else will fail
+        raise PatternMatchFailed(
+            "term of type '{}' not allowed in pattern matching"
+            .format(term[0]))
 
-        # If we are evaluating subsumtion
-        if not unifying:
+    elif pattern[0] in unify_not_allowed:
+        raise PatternMatchFailed(
+            "pattern of type '{}' not allowed in pattern matching"
+            .format(pattern[0]))
 
-            # If we are evaluating subsumption between two different conditional patterns
-            # we want to 'punt' and print a warning message.
-            if term[0] == 'if-exp':
+    elif pattern[0] == 'id': # variable in pattern add to unifier
+        if pattern[1] == '_': # anonymous variable - ignore unifier
+            return []
+        else:
+            id_val = state.symbol_table.lookup_sym(pattern[1],strict=False)
+            if id_val and id_val[0] == 'pattern':
+                warning("you are overwriting a pattern stored in '{}'".format(pattern[1]))
+            unifier = (pattern, term)
+            return [unifier]
 
-                if not state.cond_warning:
-                    warning("Redundant pattern detection is not supported for conditional pattern expressions.")
-                    state.cond_warning = True
+    elif pattern[0] == 'index': # index act like a var
+        unifier = (pattern, term)
+        return [unifier]
 
-            # Otherwise if the term is not another cmatch the clauses are correctly ordered.
+    elif pattern[0] == 'none':
+        if term[0] == 'none':
+            return []
+        else:
             raise PatternMatchFailed(
-                "Subsumption relatioship broken, pattern will not be rendered redundant.")
-
-        (IF_EXP, cond_exp, pexp, else_exp) = pattern
+                    "expected 'none' got '{}'"
+                    .format(term[0]))
 
+    elif pattern[0] == 'if-exp':
+        (IF_EXP, cond_exp, patexp, else_exp) = pattern
         if else_exp[0] != 'null':
-            raise PatternMatchFailed("conditional patterns do not support 'else' clauses")
-
-        # Explicit messaging
-        if debugging: message_explicit("Conditional match: if ({})",
-            [term2string(cond_exp)],
-            notify=True, increase=True
-        )
-
-
+            raise PatternMatchFailed(
+                    "conditional patterns do not support 'else' clauses")
         # evaluate the conditional expression in the
-        # context of the unifiers and only expose all
+        # context of the unifiers of the pattern before the 
+        # if clause and only expose all
         # unifiers if conditional was successful
         state.symbol_table.push_scope({})
-        declare_unifiers(unify(term, pexp, unifying))
-        bool_val = map2boolean(walk(cond_exp))
+        declare_unifiers(unify(term, patexp, unifying))
+        bool_val = walk(cond_exp)
+        if bool_val[0] != 'boolean':
+            raise ValueError("found '{}' expected 'boolean' in conditional pattern"
+                             .format(bool_val[0]))
         # copy unifiers out of the temporary scope of the
         # if expression.
-        unifiers = state.symbol_table.get_curr_scope("unifiers")
+        unifiers = state.symbol_table.get_curr_scope(option="unifiers")
         state.symbol_table.pop_scope()
-
         if bool_val[1]:
-            if debugging: message_explicit("Condition met, {}",
-                [term2string(cond_exp)], decrease=True
-            )
             return unifiers
         else:
-            if debugging: message_explicit("Condition ({}) failed",
-                [term2string(cond_exp)], decrease=True
-            )
             raise PatternMatchFailed(
-                "conditional pattern match failed")
-
-    elif term[0] == 'if-exp':
-        # We will only get here when evaluating subsumption
-
-        # If we get here, a conditional pattern clause is placed after a non-conditonal
-        # pattern clause. Therefore, we need to check if the subsume because if they do
-        # the conditonal clause is redundant.
-        (IF_EXP, cond_exp, pexp, else_exp) = term
-
-        if else_exp[0] != 'null':
-            raise PatternMatchFailed("conditional patterns do not support 'else' clauses")
-
-        #return unify(pexp,pattern,False)
-        # Otherwise if the term is not another cmatch the clauses are correctly ordered.
-        raise PatternMatchFailed(
-            "conditional patterns not supported.")
+                    "conditional pattern match failed")
 
     elif pattern[0] == 'typematch':
-        typematch = pattern[1]
-        nextIndex = 0 #indicates index of where we will 'look' next
-        
-        if debugging: message_explicit("Typematch {} to type {}", [term2string(term), typematch])
-
-        if typematch in ['string','real','integer','list','tuple','boolean','none']:
-
-            if (not unifying):
-
-                #walk a different path for this node
-                if (term[0] == 'typematch'):
-                    nextIndex = 1
-
-                #handle lists/head-tails subsuming each other
-                if (term[0] in ["list","head-tail"]):
-                    if ((typematch == 'list')):
-                        return []
-
-            if typematch == term[nextIndex]:
-                if debugging: message_explicit("Success!", level="secondary")
+        typematch_kind = pattern[1]
+        if typematch_kind in ['string','real','integer','list','tuple','boolean','none']:
+            if typematch_kind == term[0]:
                 return []
             else:
-                if debugging: message_explicit("Failure", level="secondary")
                 raise PatternMatchFailed(
-                    "expected type '{}' got a term of type '{}'"
-                    .format(typematch, term[nextIndex]))
-
-        elif typematch == 'function':
+                    "expected a value of type '{}' got a value of type '{}'"
+                    .format(typematch_kind, term[0]))
+        elif typematch_kind == 'function':
             # matching function and member function values
             if term[0] in ['function-val','member-function-val']:
-                if debugging: message_explicit("Success!", level="secondary")
                 return []
             else:
-                if debugging: message_explicit("Failure", level="secondary")
                 raise PatternMatchFailed(
-                    "expected type '{}' got a term of type '{}'"
-                    .format(typematch, term[0]))
-
-        elif typematch == 'pattern':
-            if unifying:
-
-                # any kind of structure can be a pattern, and variables
-                # see globals.py for a definition of 'patterns'
-                if term[nextIndex] in patterns:
-                    if debugging: message_explicit("Success!", level="secondary")
-                    return []
-                else:
-                    if debugging: message_explicit("Failure", level="secondary")
-                    raise PatternMatchFailed(
-                            "expected type '{}' got a term of type '{}'"
-                            .format(typematch, term[0]))
-
-            else: # Evaluating typematch-pattern subsumption
-                #walk a different path for this one node
-                if (term[0] == 'typematch'):
-                    nextIndex = 1
-
-                #handle lists/head-tails subsuming each other
-                if (term[0] in ["list","head-tail"]):
-                    if ((typematch == 'list')):
-                        if debugging: message_explicit("Success!", level="secondary")
-                        return []
-
-                if term[nextIndex] in pattern_subsumes:
-                    if debugging: message_explicit("Success!", level="secondary")
-                    return []
-                else:
-                    if debugging: message_explicit("Failure", level="secondary")
-                    raise PatternMatchFailed(
-                        "expected type '{}' got a term of type '{}'"
-                        .format(typematch, term[nextIndex]))
-
-        elif term[0] == 'object':
-            if state.symbol_table.lookup_sym(typematch)[0] != 'struct':
-                raise PatternMatchFailed( "'{}' is not a type".format(typematch) )
-
+                    "expected a value of type '{}' got a value of type '{}'"
+                    .format(typematch_kind, term[0]))
+        elif typematch_kind == 'pattern':
+            # any kind of structure can be a pattern, and variables
+            # see globals.py for a definition of 'patterns'
+            if term[0] in patterns:
+                return []
+            else:
+                raise PatternMatchFailed(
+                        "expected a value of type '{}' got a value of type '{}'"
+                        .format(typematch_kind, term[0]))
+        elif term[0] == 'object': # then typematch_kind has to be a structure type
+            if state.symbol_table.lookup_sym(typematch_kind)[0] != 'struct':
+                raise PatternMatchFailed( 
+                        "'{}' is not a type"
+                        .format(typematch_kind) )
             (OBJECT,
                 (STRUCT_ID, (ID, struct_id)),
+                (MEMBER_NAMES, LIST),
                 (OBJECT_MEMORY, LIST)) = term
-            if struct_id == typematch:
-                if debugging: message_explicit("Success!", level="secondary")
+            if struct_id == typematch_kind:
                 return []
             else:
-                if debugging: message_explicit("Failure", level="secondary", increase=True)
                 raise PatternMatchFailed(
-                    "expected type '{}' got an object of type '{}'"
-                    .format(typematch, struct_id))
-
+                    "expected a value of type '{}' got a value of type '{}'"
+                    .format(typematch_kind, struct_id))
         else:
-            if state.symbol_table.lookup_sym(typematch)[0] != 'struct':
-                if debugging: message_explicit("Failure", level="secondary", increase=True)
-
-                raise PatternMatchFailed( "'{}' is not a type".format(typematch) )
+            if state.symbol_table.lookup_sym(typematch_kind)[0] != 'struct':
+                raise PatternMatchFailed( "'{}' is not a type".format(typematch_kind) )
             else:
-                if debugging: message_explicit("Failure", level="secondary", increase=True)
-
                 raise PatternMatchFailed(
-                    "expected type '{}' got an object of type '{}'"
-                    .format(typematch, term[0]))
-
-
-    elif pattern[0] == 'none':
-        if term[0] != 'none':
-            if debugging: message_explicit("{} and none do not match",
-                [term2string(term)]
-            )
-            raise PatternMatchFailed("expected 'none' got '{}'"
-                    .format(term[0]))
-        else:
-            if debugging: message_explicit("None and None match", level="secondary")
-            return []
-
-    # NOTE: functions/foreign are allowed in terms as long as they are matched
-    # by a variable in the pattern - anything else will fail
-    elif term[0] in (unify_not_allowed - {'function-val', 'foreign'}):
-        raise PatternMatchFailed(
-            "term of type '{}' not allowed in pattern matching"
-            .format(term[0]))
-
-    elif pattern[0] in unify_not_allowed:
-        raise PatternMatchFailed(
-            "pattern of type '{}' not allowed in pattern matching"
-            .format(pattern[0]))
+                    "expected a value of type '{}' got a value of type '{}'"
+                    .format(typematch_kind, term[0]))
 
     elif pattern[0] == 'pattern':
-        # pattern operator on the pattern side can always be ignored
-        # --TODO double check - ttc
         if term[0] == 'pattern':
-            return unify(term[1], pattern[1], unifying)
+            # term is a first-class pattern, ie, a pattern value
+            # we are not allowed to match on that.
+            raise PatternMatchFailed(
+                "cannot pattern-match patterns")
         else:
+            # treat the pattern value as a pattern and continue matching.
             return unify(term, pattern[1], unifying)
 
-    elif term[0] == 'pattern' and pattern[0] not in ['id', 'index']:
-        # ignore pattern operator on the term if we are not trying to unify term with
-        # a variable or other kind of lval
-        return unify(term[1], pattern, unifying)
-
-    elif term[0] == 'object' and pattern[0] == 'apply':
-        # unpack term
-        (OBJECT,
-         (STRUCT_ID, (ID, struct_id)),
-         (OBJECT_MEMORY, (LIST, obj_memory))) = term
-        # unpack pattern
-        (APPLY,
-         (ID, apply_id),
-         arg) = pattern
-        type = state.symbol_table.lookup_sym(apply_id)
-        if type[0] != 'struct':
-            raise PatternMatchFailed("'{}' is not a type".format(apply_id))
-
-        if struct_id != apply_id:
-            raise PatternMatchFailed("expected type '{}' got type '{}'"
-                .format(apply_id, struct_id))
-        # we are comparing raw lists here
-        if arg[0] == 'tuple':
-            pattern_list = arg[1]
-        else:
-            pattern_list = [arg]
-
-        # only pattern match on object data members
-        if debugging: message_explicit("Matching object {}{} and pattern {}{}",
-            [apply_id,  term2string( ('tuple', data_only(obj_memory)) ),
-            struct_id, term2string( ('tuple', pattern_list) )],
-            notify=True
-        )
-        # Running through the list elements indivuidually allows for
-        # better debugging information
-        unifiers = []
-        data = data_only(obj_memory)
-
-        for i in range(len(data)):
-            unifiers += unify(data[i], pattern_list[i], unifying)
-
-        return unifiers
-
-    elif pattern[0] == 'index': # list element lval access
-        unifier = (pattern, term)
-        return [unifier]
-
-# lhh: looking at patterns as values we are now allowed to match
-# against patterns as terms where the terms now include variables.
-#    elif term[0] == 'id' and unifying: # variable in term not allowed
-#        raise PatternMatchFailed(      # when unifying
-#            "variable '{}' in term not allowed"
-#            .format(term[1]))
-
-    elif pattern[0] == 'id': # variable in pattern add to unifier
-        sym = pattern[1]
-        if sym == '_': # anonymous variable - ignore unifier
-            return []
-        else:
-            unifier = (pattern, term)
-            return [unifier]
-
-    elif pattern[0] in ['head-tail', 'raw-head-tail']:
-        if debugging: message_explicit("Matching {} to {}",
-            [term2string(term), term2string(pattern)],
-            notify=True
-        )
-        # if we are unifying or we are not evaluating subsumption
-        #  to another head-tail
-        if unifying or term[0] not in ['head-tail', 'raw-head-tail']:
-            (HEAD_TAIL, pattern_head, pattern_tail) = pattern
-            (LIST, list_val) = term
-
-            if LIST != 'list':
-                if debugging: message_explicit("Failed", level="secondary")
-                raise PatternMatchFailed(
-                    "head-tail operator expected type 'list' got type '{}'"
-                    .format(LIST))
-
-            if not len(list_val):
-                if debugging: message_explicit("Failed", level="secondary")
-
-                raise PatternMatchFailed(
-                    "head-tail operator expected a non-empty list")
-
-            list_head = list_val[0]
-            list_tail = ('list', list_val[1:])
-            unifier = []
-
-            unifier += unify(list_head, pattern_head, unifying)
-            unifier += unify(list_tail, pattern_tail, unifying)
-
-            check_repeated_symbols(unifier) #Ensure we have no non-linear patterns
-            if debugging: message_explicit("Success!", level="secondary")
-
-            return unifier
-
-        else: #Else we are evaluating subsumption to another head-tail
-
-            lengthH = head_tail_length(pattern) #H->higher order of predcence pattern
-            lengthL = head_tail_length(term)    #L->lower order of predcence pattern
-
-            if lengthH == 2 and lengthL != 2:
-                return unify(pattern[1],term[1],unifying)
-
-            if (lengthH > lengthL): # If the length of the higher presedence pattern is greater
-                                    # then length of the lower precedence pattern, it is not redundant
-                if debugging: message_explicit("Failed", level="secondary")
-                raise PatternMatchFailed(
-                    "Subsumption relatioship broken, pattern will not be rendered redundant.")
-
-            else: #Else we continue evaluating the different terms in the head-tail pattern
-                (HEAD_TAIL, patternH_head, patternH_tail) = pattern
-                (HEAD_TAIL, patternL_head, patternL_tail) = term
-
-                unifier = []
-                for i in range(lengthH):
-                    unifier += unify(patternL_head,patternH_head,unifying)
-                    try:
-                        (RAW_HEAD_TAIL, patternH_head, patternH_tail) = patternH_tail
-                        (RAW_HEAD_TAIL, patternL_head, patternL_tail) = patternL_tail
-                    except:
-                        break
-
-                check_repeated_symbols(unifier) #Ensure we have no non-linear patterns
-                if debugging: message_explicit("Success!", level="secondary")
-                return unifier
-
     elif pattern[0] == 'deref':  # ('deref', v, bl)
         # v can be an AST representing any computation
         # that produces a pattern.
-
-        if debugging: message_explicit("Dereferencing {}", [term2string(pattern[1])])
-
         p = walk(pattern[1])
-
         if pattern[2][0] != 'nil': # we have a binding term list
-            if p[1][0] != 'constraint':
+            if p[1][0] != 'scope':
                 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',
+                        ('scope',
                             p[1][1],
                             pattern[2]))
-
-
-        if debugging: message_explicit("{} -> {}", [term2string(pattern), term2string(p)], 
-            level="secondary")
-
-        notify_explicit()
-
         return unify(term,p,unifying)
 
-    # builtin operators look like apply lists with operator names
-    elif pattern[0] == 'apply':
-        if term[0] != pattern[0]: # make sure both are applys
-            raise PatternMatchFailed(
-                "term and pattern disagree on structure")
-
-        # unpack the apply structures
-        (APPLY, (ID, t_id), t_arg) = term
-        (APPLY, (ID, p_id), p_arg) = pattern
-
-        # make sure apply id's match
-        if t_id != p_id:
-            raise PatternMatchFailed(
-                "term '{}' does not match pattern '{}'"
-                .format(t_id, p_id))
-
-        # unify the args
-        return unify(t_arg, p_arg, unifying)
-
-    elif pattern[0] == 'constraint':
-        if debugging: message_explicit("[Begin] constraint pattern: {}",
-            [term2string(pattern[1])],
-            notify=True, increase=True
-        )
-
+    elif pattern[0] == 'scope':
         p = pattern[1]
         bl = pattern[2] # binding term list
-
         # constraint patterns are evaluated in their own scope
         try:
             state.symbol_table.push_scope({})
             unifier = unify(term,p)
             state.symbol_table.pop_scope()
-            if debugging: message_explicit("[End] constraint pattern", decrease=True)
         except PatternMatchFailed as e:
             state.symbol_table.pop_scope()
-            if debugging: message_explicit("[End] constraint pattern", decrease=True)
             # rethrow exception so that pattern match failure is properly propagated
             raise e 
-
         # process binding list
         if bl[0] == 'nil':
             return [] #Return an empty unifier
@@ -579,33 +310,105 @@ def __unify(term, pattern, unifying = True ):
                         new_unifier += [(new_id,exp)]
             return new_unifier
 
-    elif term[0] != pattern[0]:  # nodes are not the same
-        if debugging: message_explicit("Fail: {} and {} are not the same",
-            [term[0], pattern[0]], level="secondary")
-        
+    elif pattern[0] == 'object' and term[0] == 'object':
+        # this can happen when we dereference a variable pointing
+        # to an object as a pattern, e.g.
+        #    let o = A(1,2). -- A is a structure with 2 data members
+        #    let *o = o.
+        (OBJECT, (STRUCT_ID, (ID, pid)), pml, (OBJECT_MEMORY, (LIST, pl))) = pattern
+        (OBJECT, (STRUCT_ID, (ID, tid)), tml, (OBJECT_MEMORY, (LIST, tl))) = term
+        if pid != tid:
+            raise PatternMatchFailed(
+                "pattern type '{}' and term type '{}' do not agree"
+                .format(pid,tid))
+        unifiers = []
+        # we only pattern match on data members
+        tl_data_members = data_only(tl)
+        pl_data_members = data_only(pl)
+        if len(tl_data_members) != len(pl_data_members):
+            raise ValueError("internal error: not the same number of data members for objects")
+        for i in range(len(pl_data_members)):
+            unifiers += unify(tl_data_members[i], pl_data_members[i])
+        return unifiers
+
+    elif pattern[0] == 'apply' and term[0] == 'object':
+        # in patterns constructor functions match objects, e.g.
+        #   let A(x,y) = A(1,2)
+        # only constructors are allowed in patterns
+        f = pattern[1]
+        if f[0] == 'index':
+            # scope qualified pattern name
+            (APPLY,
+              (INDEX,
+                (ID, modname),
+                (ID, apply_id)),
+              arg) = pattern
+        else:
+            modname = None
+            (APPLY,
+              (ID, apply_id),
+              arg) = pattern
+        # unpack term
+        (OBJECT,
+         (STRUCT_ID, (ID, struct_id)),
+         (MEMBER_NAMES, (LIST, member_names)),
+         (OBJECT_MEMORY, (LIST, obj_memory))) = term
+        if modname:
+            orig_config = set_module_env(modname)        
+        type = state.symbol_table.lookup_sym(apply_id,strict=False)
+        if modname:
+            set_config(orig_config)
+        if not type or type[0] != 'struct':
+            raise ValueError("illegal pattern, '{}' is not a type".format(apply_id))
+        if struct_id != apply_id:
+            raise PatternMatchFailed("expected type '{}' got type '{}'"
+                .format(apply_id, struct_id))
+        # retrieve argument list to constructor
+        # Note: we want it to be a list so we can compare it to the object memory
+        if arg[0] == 'tuple':
+            arg_list = arg[1]
+        else:
+            arg_list = [arg]
+        # only pattern match on object data members
+        data_list = data_only(obj_memory)
+        return unify(data_list, arg_list, unifying)
+
+    elif pattern[0] in ['head-tail', 'raw-head-tail']:
+        (HEAD_TAIL, pattern_head, pattern_tail) = pattern
+        if term[0] != 'list':
+            raise PatternMatchFailed(
+                "head-tail operator expected a list got a value of type '{}'"
+                .format(term[0]))
+        (LIST, list_val) = term
+        if not len(list_val):
+            raise PatternMatchFailed(
+                "head-tail operator expected a non-empty list")
+        list_head = list_val[0]
+        list_tail = ('list', list_val[1:])
+        unifier = []
+        unifier += unify(list_head, pattern_head, unifying)
+        unifier += unify(list_tail, pattern_tail, unifying)
+        check_repeated_symbols(unifier) #Ensure we have no non-linear patterns
+        return unifier
+ 
+    #################################
+    ### 3. AST structural matching
+    elif pattern[0] != term[0]:  # node types are not the same
         raise PatternMatchFailed(
             "nodes '{}' and '{}' are not the same"
             .format(term[0], pattern[0]))
 
-    elif len(term) != len(pattern): # nodes are not of same the arity
-        if debugging: message_explicit("Fail: {} and {} are not the same arity",
-            [term[0], pattern[0]], level="secondary")
-
+    elif len(pattern) != len(term): # nodes are not of same the arity
         raise PatternMatchFailed(
             "nodes '{}' and '{}'' are not of the same arity"
             .format(term[0], pattern[0]))
 
-    else:
-        #lhh
-        #print("unifying {}".format(pattern[0]))
+    else: # unify AST children nodes
         unifier = []
         for i in range(1,len(term)):
             unifier += unify(term[i], pattern[i], unifying)
-        #lhh
-        #print("returning unifier: {}".format(unifier))
         return unifier
 
-
 #########################################################################
 def eval_actual_args(args):
 
@@ -706,19 +509,22 @@ def read_at_ix(structure_val, ix):
     elif structure_val[0] == 'object':
         (OBJECT,
          (STRUCT_ID, (ID, struct_id)),
-         (OBJECT_MEMORY, (LIST, memory))) = structure_val
-        # compute the index -- for objects this has to be done
-        # in the context of the struct scope
-        struct_val = state.symbol_table.lookup_sym(struct_id)
-        # unpack the struct value
-        (STRUCT,
          (MEMBER_NAMES, (LIST, member_names)),
-         (STRUCT_MEMORY, (LIST, struct_memory))) = struct_val
-
+         (OBJECT_MEMORY, (LIST, memory))) = structure_val
         if ix[0] == 'id' and ix[1] in member_names:
             ix_val = ('integer', member_names.index(ix[1]))
         else:
-            ix_val = walk(ix)
+            raise ValueError("{} is not a member of type {}"
+                .format(term2string(ix),struct_id))
+            #ix_val = walk(ix)
+
+    elif structure_val[0] == 'module':
+        (MODULE, id, (CLOSURE, closure)) = structure_val
+        config = state.symbol_table.get_config()
+        state.symbol_table.set_config(closure)
+        val = walk(ix)
+        state.symbol_table.set_config(config)
+        return val
 
     elif structure_val[0] == 'pattern':
         # simple patterns are just structures - skip the pattern operator
@@ -777,23 +583,26 @@ def store_at_ix(structure_val, ix, value):
     elif structure_val[0] == 'object':
         (OBJECT,
          (STRUCT_ID, (ID, struct_id)),
-         (OBJECT_MEMORY, (LIST, memory))) = structure_val
-        # compute the index -- for objects this has to be done
-        # in the context of the struct scope
-        struct_val = state.symbol_table.lookup_sym(struct_id)
-        # unpack the struct value
-        (STRUCT,
          (MEMBER_NAMES, (LIST, member_names)),
-         (STRUCT_MEMORY, (LIST, struct_memory))) = struct_val
-
+         (OBJECT_MEMORY, (LIST, memory))) = structure_val
         if ix[0] == 'id' and ix[1] in member_names:
             ix_val = ('integer', member_names.index(ix[1]))
         else:
             ix_val = walk(ix)
 
+    elif structure_val[0] == 'module':
+        (MODULE, id, (CLOSURE, closure)) = structure_val
+        config = state.symbol_table.get_config()
+        state.symbol_table.set_config(closure)
+        # execute an assignment in the context of the module
+        walk(('unify', ix, value))
+        state.symbol_table.set_config(config)
+        return
+
     elif structure_val[0] == 'pattern':
         # simple patterns are just structures - skip the pattern operator
-        return store_at_ix(structure_val[1], ix, value)
+        store_at_ix(structure_val[1], ix, value)
+        return
 
     else:
         raise ValueError("term '{}' is not a mutable structure"
@@ -826,7 +635,6 @@ def store_at_ix(structure_val, ix, value):
             # corresponding rval value
             (INTEGER, location) = lval[i]
             memory[location] = rval[i]
-
         return
 
     else:
@@ -834,110 +642,310 @@ def store_at_ix(structure_val, ix, value):
                          .format(ix_val[0]))
 
 #########################################################################
+# set module environment
+def set_module_env(modname):
+    module_val = state.symbol_table.lookup_sym(modname)
+    if module_val[0] != 'module':
+        raise ValueError("{} is not a module".format(modname))
+    (MODULE, id, (CLOSURE, closure)) = module_val
+    config = state.symbol_table.get_config()
+    state.symbol_table.set_config(closure)
+    return config
+
+#########################################################################
+def set_config(config):
+    state.symbol_table.set_config(config)
+
+#########################################################################
+# implementations for builtin operators and functions. these operators 
+# and functions do not need/are not allowed to have a function 
+# local scope.  therefore they are implemented here as builtins as 
+# part of the interpreter proper.  for other builtins that do 
+# not have this restriction see the prologue.
+
 def handle_builtins(node):
     (APPLY, (ID, opname), args) = node
     assert_match(APPLY, 'apply')
     assert_match(ID, 'id')
 
+    # deal with binary operators
     if opname in binary_operators:
-        (TUPLE, bin_args)= args
-        val_a = walk(bin_args[0])
-        val_b = walk(bin_args[1])
+        (TUPLE, [a,b])= args
 
         if opname == '__plus__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real', 'list', 'boolean']:
-                return (type, val_a[1] + val_b[1])
-            elif type == 'string':
-                return (type, term2string(val_a) + term2string(val_b))
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'list', 'string']:
+                if val_b[0] in ['integer', 'real', 'list', 'string']:
+                    if val_a[0]==val_b[0]:
+                        return (val_a[0], val_a[1] + val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} + {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} + {}' expected '{} + {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '+'".format(val_b[0]))
             else:
-                raise ValueError("unsupported type '{}' in +".format(type))
+                raise ValueError("unsupported type '{}' in '+'".format(val_a[0]))
         elif opname == '__minus__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real']:
-                return (type, val_a[1] - val_b[1])
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real']:
+                if val_b[0] in ['integer', 'real']:
+                    if val_a[0]==val_b[0]:
+                        return (val_a[0], val_a[1] - val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} - {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} - {}' expected '{} - {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '-'".format(val_b[0]))
             else:
-                raise ValueError("unsupported type '{}' in -".format(type))
+                raise ValueError("unsupported type '{}' in '-'".format(val_a[0]))
         elif opname == '__times__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real']:
-                return (type, val_a[1] * val_b[1])
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real']:
+                if val_b[0] in ['integer', 'real']:
+                    if val_a[0]==val_b[0]:
+                        return (val_a[0], val_a[1] * val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} * {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} * {}' expected '{} * {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '*'".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in *')
+                raise ValueError("unsupported type '{}' in '*'".format(val_a[0]))
         elif opname == '__divide__':
-            type = promote(val_a[0], val_b[0])
-            if type == 'integer':
-                return (type, int(val_a[1]) // int(val_b[1]))
-            elif type == 'real':
-                return ('real', float(val_a[1]) / float(val_b[1]))
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real']:
+                if val_b[0] in ['integer', 'real']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'integer':
+                            return ('integer', val_a[1] // val_b[1])
+                        elif val_a[0] == 'real':
+                            return ('real', val_a[1] / val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} / {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} / {}' expected '{} / {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '/'".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in /')
+                raise ValueError("unsupported type '{}' in '/'".format(val_a[0]))
         elif opname == '__or__':
-            # NOTE: do we need to typecheck here?
-            if map2boolean(val_a)[1] == True or map2boolean(val_b)[1] == True:
-               return ('boolean', True)
+            # short circuit evaluation
+            val_a = walk(a)
+            if val_a[0] == 'boolean':
+                if val_a[1] == True:
+                    return ('boolean', True)
+            else:
+                raise ValueError(
+                    "found '{} expected 'boolean and boolean'"
+                    .format(val_a[0]))
+            val_b = walk(b)
+            if val_b[0] == 'boolean':
+                return ('boolean', val_a[1] or val_b[1])
             else:
-               return ('boolean', False)
+                raise ValueError(
+                    "found '{} and {}' expected 'boolean and boolean'"
+                    .format(val_a[0],val_b[0]))
         elif opname == '__and__':
-            # NOTE: do we need to typecheck here?
-            if map2boolean(val_a)[1] == True and map2boolean(val_b)[1] == True:
-               return ('boolean', True)
+            # short circuit evaluation
+            val_a = walk(a)
+            if val_a[0] == 'boolean':
+                if val_a[1] == False:
+                    return ('boolean', False)
+            else:
+                raise ValueError(
+                    "found '{} expected 'boolean and boolean'"
+                    .format(val_a[0]))
+            val_b = walk(b)
+            if val_b[0] == 'boolean':
+                return ('boolean', val_a[1] and val_b[1])
             else:
-               return ('boolean', False)
+                raise ValueError(
+                    "found '{} and {}' expected 'boolean and boolean'"
+                    .format(val_a[0],val_b[0]))
         elif opname == '__eq__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real', 'list', 'tuple', 'boolean', 'none']:
-                return ('boolean', val_a[1] == val_b[1])
-            elif type == 'string':
-                return ('boolean', term2string(val_a) == term2string(val_b))
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'list', 'tuple', 'boolean', 'string', 'none']:
+                if val_b[0] in ['integer', 'real', 'list', 'tuple', 'boolean', 'string', 'none']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'real' and val_a[1] != val_b[1] and isclose(val_a[1],val_b[1]):
+                            warning("possible rounding error issue")
+                        return ('boolean', val_a[1] == val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} == {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} == {}' expected '{} == {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '=='".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in ==')
+                raise ValueError("unsupported type '{}' in '=='".format(val_a[0]))
         elif opname  == '__ne__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real', 'list', 'tuple', 'boolean', 'none']:
-                return ('boolean', val_a[1] != val_b[1])
-            elif type == 'string':
-                return ('boolean', term2string(val_a) != term2string(val_b))
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'list', 'tuple', 'boolean', 'string', 'none']:
+                if val_b[0] in ['integer', 'real', 'list', 'tuple', 'boolean', 'string', 'none']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'real' and val_a[1] != val_b[1] and isclose(val_a[1],val_b[1]):
+                            warning("possible rounding error issue")
+                        return ('boolean', val_a[1] != val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} =/= {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} =/= {}' expected '{} =/= {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '=/='".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in =/=')
+                raise ValueError("unsupported type '{}' in '=/='".format(val_a[0]))
         elif opname == '__le__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real']:
-                return ('boolean', val_a[1] <= val_b[1])
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'string']:
+                if val_b[0] in ['integer', 'real', 'string']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'real' and val_a[1] != val_b[1] and isclose(val_a[1],val_b[1]):
+                            warning("possible rounding error issue")
+                        return ('boolean', val_a[1] <= val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} <= {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} <= {}' expected '{} <= {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '<='".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in <=')
+                raise ValueError("unsupported type '{}' in '<='".format(val_a[0]))
         elif opname == '__lt__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real']:
-                return ('boolean', val_a[1] < val_b[1])
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'string']:
+                if val_b[0] in ['integer', 'real', 'string']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'real' and val_a[1] != val_b[1] and isclose(val_a[1],val_b[1]):
+                            warning("possible rounding error issue")
+                        return ('boolean', val_a[1] < val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} < {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} < {}' expected '{} < {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '<'".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in <')
+                raise ValueError("unsupported type '{}' in '<'".format(val_a[0]))
         elif opname == '__ge__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real']:
-                return ('boolean', val_a[1] >= val_b[1])
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'string']:
+                if val_b[0] in ['integer', 'real', 'string']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'real' and val_a[1] != val_b[1] and isclose(val_a[1],val_b[1]):
+                            warning("possible rounding error issue")
+                        return ('boolean', val_a[1] >= val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} >= {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} >= {}' expected '{} >= {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '>='".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in >=')
+                raise ValueError("unsupported type '{}' in '>='".format(val_a[0])) 
         elif opname == '__gt__':
-            type = promote(val_a[0], val_b[0])
-            if type in ['integer', 'real']:
-                return ('boolean', val_a[1] > val_b[1])
+            val_a = walk(a)
+            val_b = walk(b)
+            if val_a[0] in ['integer', 'real', 'string']:
+                if val_b[0] in ['integer', 'real', 'string']:
+                    if val_a[0]==val_b[0]:
+                        if val_a[0] == 'real' and val_a[1] != val_b[1] and isclose(val_a[1],val_b[1]):
+                            warning("possible rounding error issue")
+                        return ('boolean', val_a[1] > val_b[1])
+                    else:
+                        type = promote(val_a[0], val_b[0])
+                        if type == None:
+                            raise ValueError(
+                                "operation '{} > {}' not supported"
+                                .format(val_a[0],val_b[0]))
+                        else:
+                            raise ValueError(
+                                "found '{} > {}' expected '{} > {}'"
+                                .format(val_a[0],val_b[0],type,type))
+                else:
+                    raise ValueError("unsupported type '{}' in '>'".format(val_b[0]))
             else:
-                raise ValueError('unsupported type in >')
+                raise ValueError("unsupported type '{}' in '>'".format(val_a[0])) 
         else:
-            raise ValueError("unknown builtin binary operation '{}'".format(opname))
+            raise ValueError("unknown builtin binary operator '{}'".format(opname))
 
+    # deal with unary operators
     elif opname in unary_operators:
-        arg_val = walk(args)
-
+        arg_val = walk(args)             
         if opname == '__not__':
-            val = map2boolean(arg_val)
-            if val[1] == False:
-                return ('boolean', True)
-            elif val[1] == True:
-                return ('boolean', False)
+            if arg_val[0] == 'boolean':
+                if arg_val[1] == False:
+                    return ('boolean', True)
+                else:
+                    return ('boolean', False)
             else:
-                raise ValueError("not a boolean value in 'not'")
+                raise ValueError("found 'not {}' expected 'not boolean'"
+                                 .format(arg_val[0]))
         elif opname == '__uminus__':
             if arg_val[0] in ['integer', 'real']:
                 return (arg_val[0], - arg_val[1])
@@ -952,8 +960,43 @@ def handle_builtins(node):
                 raise ValueError(
                     "unsupported type '{}' in unary plus"
                     .format(arg_val[0]))
+        elif opname == 'assert':
+            if arg_val[0] != 'boolean':
+                raise ValueError('the assert operator expected a Boolean value')
+            if not arg_val[1]:
+                raise ValueError('assert failed')
+            else:
+                return ('none', None)
+        elif opname == 'escape':
+            global __retval__
+            __retval__ = ('none', None)
+            if arg_val[0] != 'string':
+                raise ValueError('expected a string as argument to the escape operator')
+            exec(arg_val[1])
+            return __retval__
+        elif opname == 'eval':
+            if arg_val[0] == 'string':
+                import frontend
+                parser = frontend.Parser(filename="<eval>")
+                eval_ast = parser.parse(arg_val[1])
+                walk(eval_ast)
+                return function_return_value[-1]
+            else:
+                raise ValueError('expected a string as argument to the eval operator')
+
         else:
-            raise ValueError("unknown builtin unary operation '{}'".format(opname))
+            raise ValueError("unknown builtin unary operator '{}'".format(opname))
+
+    # deal with nullary operators
+    elif opname in nullary_operators:
+        (type, _) = walk(args)
+        if type != 'none':
+            raise ValueError("{} is a nullary operator".format(opname))
+        if opname == 'toplevel':
+            return ('boolean', state.mainmodule == state.lineinfo[0])
+        else:
+            raise ValueError("unknown builtin nullary operator '{}'".format(opname))
+        
 
 #########################################################################
 def pop_stackframe(error_trace=False): 
@@ -966,8 +1009,6 @@ def pop_stackframe(error_trace=False):
 
 #########################################################################
 def handle_call(obj_ref, fval, actual_val_args, fname):
-    # Needed for later
-    global debugging
 
     # function calls transfer control - save our caller's lineinfo
     # we save the debug information here to preserve lineinfo between
@@ -985,24 +1026,19 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
     # Note: we have to do this here because unifying
     # over the body patterns can introduce variable declarations,
     # think conditional pattern matching.
+    # Note: we are keeping a stack of configs so that
+    # the debugger can look at contents of 
+    # Asteroid stack frames
     state.symbol_table.saved_configs.append(
         state.symbol_table.get_config()
     )
-
     state.symbol_table.set_config(closure)
     state.symbol_table.push_scope({})
 
-    # Explicit message
-    if debugging: message_explicit("Call: {}({})",
-        [fname, term2string(actual_val_args)],
-        increase=True
-    )
-
-    # We want to return back to whatever tab level the function
-    # call started at, so, we grab this here to reset to at
-    # the return. This allows recursive functions to have
-    # the proper formatting
-    if debugging: cur_tab_level = debugger.tab_level
+    # if we have an obj reference bind it to the
+    # variable 'this'
+    if obj_ref:
+        state.symbol_table.enter_sym('this', obj_ref)
 
     # iterate over the bodies to find one that unifies with the actual parameters
     (BODY_LIST, (LIST, body_list_val)) = body_list
@@ -1015,49 +1051,25 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
 
         # Deconstruct function body
         (BODY,
-        (PATTERN, p),
-        (STMT_LIST, stmts)) = body_list_val[ i + 1]
+          (PATTERN, p),
+          stmts) = body_list_val[ i + 1]
 
-        if debugging: message_explicit("Attempting to match {} with pattern {}",
-            [term2string(actual_val_args), term2string(p)], level="primary",
-            notify=True, increase=True
-        )
-        
         try:
             # Attempt to unify the actual args and the pattern
             unifiers = unify(actual_val_args, p)
             unified = True
-
-            # Do our explicit message
-            if debugging: message_explicit("Success! Matched function body", level="primary", decrease=True)
-
         except PatternMatchFailed:
-            # Reset the tab level
-            if explicit_enabled():
-                debugger.tab_level = cur_tab_level + 1
-
-            # Print the explicit messaging
-            if debugging: message_explicit("Failed to match function body", level="tertiary", decrease=True)
-
             unifiers = []
             unified = False
 
         if unified:
             break
 
-    # Reset the tab level back to the function call's level
-    if debugging: debugger.tab_level = cur_tab_level
-
     if not unified:
         raise ValueError("actual argument '{}' not recognized by function '{}'"
                          .format(term2string(actual_val_args),fname))
     declare_formal_args(unifiers)
 
-    # if we have an obj reference bind it to the
-    # variable 'this'
-    if obj_ref:
-        state.symbol_table.enter_sym('this', obj_ref)
-
     # OWM: The following segment is a repeat of the bottom of this function.
     # We need to do this because redundant patterns can break scope and
     # some debugger and state features as they exit computation.
@@ -1065,37 +1077,24 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
     # Check for useless patterns
     try:
         if state.eval_redundancy:
-            old_debugging = debugging
-            debugging = False
             check_redundancy(body_list, fname)
-            debugging = old_debugging
 
     # Reset settings
     except RedundantPatternFound as r:
-        debugging = old_debugging
         # restore caller's env
         state.lineinfo = old_lineinfo
-        # Keep debugger up to date
-        if debugging: debugger.set_lineinfo(state.lineinfo)
         pop_stackframe()
         raise r
 
     # execute the function
+    if state.debugger: state.debugger.enter_function(fname)
     global function_return_value
-
     try:
         function_return_value.append(None)
-
-        walk_stmt_list(stmts)
-
-        # Pop the return value
+        walk(stmts)
         val = function_return_value.pop()
-
-        # If we have one, set it as the retval
         if val:
             return_value = val
-
-        # Otherwhise default the return value to none
         else:
             return_value = ('none', None)
 
@@ -1114,16 +1113,9 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
 
     # all done with function call -- clean up and exit
     # restore caller's env
+    if state.debugger: state.debugger.exit_function(fname)
     state.lineinfo = old_lineinfo
-    # Keep debugger up to date
-    if debugging: debugger.set_lineinfo(state.lineinfo)
     pop_stackframe()
-    if debugging: message_explicit("Return: {} from {}",
-            [("None" if (not return_value[1]) else term2string(return_value)), 
-            fname],
-            decrease=True
-    )
-
     return return_value
 
 #########################################################################
@@ -1157,33 +1149,30 @@ def declare_unifiers(unifiers):
         else:
             raise ValueError("unknown unifier type '{}'".format(lval[0]))
     
-    # Explicit messaging for unifiers
-    if explicit_enabled():
-        # if we've unified anything
-        if unifiers:
-            # Create our format string and list of terms
-            fstring = ""
-            terms = []
-
-            # For each unifier except the last one
-            for (lval, value) in unifiers[:-1]:
-                # Add to our format string and our terms
-                fstring += "{} = {}, "
-                terms += [term2string(lval), term2string(value)]
-
-            # Get the last unifier and add it to the terms and fstring
-            (lval, value) = unifiers[-1]
-            fstring += "{} = {}"
-            terms += [term2string(lval), term2string(value)]
-
-            # Print our message
-            if debugging: message_explicit(fstring, terms)
-
 #########################################################################
 # node functions
+#########################################################################
+def stmt_list(node):
+
+    (STMT_LIST, stmts) = node
+    assert_match(STMT_LIST, 'stmt-list')
+    
+    walk(stmts)
+
+#########################################################################
+def exp_stmt(node):
+    if state.debugger: state.debugger.step()
+
+    (EXP_STMT, exp) = node
+    assert_match(EXP_STMT,'exp-stmt')
+
+    walk(exp)
+    # statements don't return values
+    return
+
 #########################################################################
 def global_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (GLOBAL, (LIST, id_list)) = node
     assert_match(GLOBAL, 'global')
@@ -1198,36 +1187,21 @@ def global_stmt(node):
                              .format(id_val))
         state.symbol_table.enter_global(id_val)
         global_str += "{}, ".format(id_val)
-    
-    if debugging: message_explicit("Global defs: {}", [global_str[:-1]] )
-
-#########################################################################
-def assert_stmt(node):
-    notify_debugger()
-
-    (ASSERT, exp) = node
-    assert_match(ASSERT, 'assert')
-
-    exp_val = walk(exp)
-
-    # mapping asteroid assert into python assert
-    assert exp_val[1], 'assert failed'
+ 
 #########################################################################
 def unify_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (UNIFY, pattern, exp) = node
     assert_match(UNIFY, 'unify')
 
     term = walk(exp)
-
     unifiers = unify(term, pattern)
-
     declare_unifiers(unifiers)
 
 #########################################################################
 def return_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (RETURN, e) = node
     assert_match(RETURN, 'return')
@@ -1238,7 +1212,7 @@ def return_stmt(node):
 
 #########################################################################
 def break_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (BREAK,) = node
     assert_match(BREAK, 'break')
@@ -1247,7 +1221,7 @@ def break_stmt(node):
 
 #########################################################################
 def throw_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (THROW, object) = node
     assert_match(THROW, 'throw')
@@ -1258,15 +1232,14 @@ def throw_stmt(node):
 
 #########################################################################
 def try_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (TRY,
-     (STMT_LIST, try_stmts),
+     try_stmts,
      (CATCH_LIST, (LIST, catch_list))) = node
 
-    stepping = debugger_has_stepped()
     try:
-        walk_stmt_list(try_stmts)
+        walk(try_stmts)
 
     # NOTE: in Python the 'as inst' variable is only local to the catch block???
     # NOTE: we map user visible Python exceptions into standard Asteroid exceptions
@@ -1282,6 +1255,7 @@ def try_stmt(node):
     except PatternMatchFailed as inst:
         except_val = ('object',
                          ('struct-id', ('id', 'Exception')),
+                         ('member-names', ('list',["kind","val","__init__"])),
                          ('object-memory',
                           ('list',
                            [('string', 'PatternMatchFailed'),
@@ -1291,6 +1265,7 @@ def try_stmt(node):
     except RedundantPatternFound as inst:
         except_val = ('object',
                          ('struct-id', ('id', 'Exception')),
+                         ('member-names', ('list',["kind","val","__init__"])),
                          ('object-memory',
                           ('list',
                            [('string', 'RedundantPatternFound'),
@@ -1300,6 +1275,7 @@ def try_stmt(node):
     except NonLinearPatternError as inst:
         except_val = ('object',
                          ('struct-id', ('id', 'Exception')),
+                         ('member-names', ('list',["kind","val","__init__"])),
                          ('object-memory',
                           ('list',
                            [('string', 'NonLinearPatternError'),
@@ -1309,6 +1285,7 @@ def try_stmt(node):
     except ArithmeticError as inst:
         except_val = ('object',
                          ('struct-id', ('id', 'Exception')),
+                         ('member-names', ('list',["kind","val","__init__"])),
                          ('object-memory',
                           ('list',
                            [('string', 'ArithmeticError'),
@@ -1318,6 +1295,7 @@ def try_stmt(node):
     except FileNotFoundError as inst:
         except_val = ('object',
                          ('struct-id', ('id', 'Exception')),
+                         ('member-names', ('list',["kind","val","__init__"])),
                          ('object-memory',
                           ('list',
                            [('string', 'FileNotFound'),
@@ -1328,6 +1306,7 @@ def try_stmt(node):
         # mapping general Python exceptions into Asteroid's SystemError
         except_val = ('object',
                          ('struct-id', ('id', 'Exception')),
+                         ('member-names', ('list',["kind","val","__init__"])),
                          ('object-memory',
                           ('list',
                            [('string', 'SystemError'),
@@ -1343,7 +1322,7 @@ def try_stmt(node):
     for catch_val in catch_list:
         (CATCH,
          (CATCH_PATTERN, catch_pattern),
-         (CATCH_STMTS, catch_stmts)) = catch_val
+         catch_stmts) = catch_val
         try:
             unifiers = unify(except_val, catch_pattern)
         except PatternMatchFailed:
@@ -1352,7 +1331,7 @@ def try_stmt(node):
             # handler found - null out error_trace
             state.error_trace = None
             declare_unifiers(unifiers)
-            walk_stmt_list(catch_stmts, step_state=stepping)
+            walk(catch_stmts)
             return
 
     # no exception handler found - rethrow the exception
@@ -1360,55 +1339,52 @@ def try_stmt(node):
 
 #########################################################################
 def loop_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (LOOP, body_stmts) = node
     assert_match(LOOP, 'loop')
 
-    (STMT_LIST, body) = body_stmts
-
     try:
-        stepping = debugger_has_stepped()
         while True:
-            walk_stmt_list(body, step_state=stepping)
+            walk(body_stmts)
     except Break:
         pass
 
 #########################################################################
 def while_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
-    (WHILE, cond_exp, body_stmts) = node
+    (WHILE, (COND_EXP, cond), body_stmts) = node
     assert_match(WHILE, 'while')
 
-    (COND_EXP, cond) = cond_exp
-    (STMT_LIST, body) = body_stmts
-
     try:
-        stepping = debugger_has_stepped()
-
-        (COND_TYPE, cond_val) = map2boolean(walk(cond))
+        (cond_type, cond_val) = walk(cond)
+        if cond_type != 'boolean':
+            raise ValueError("found '{}' expected 'boolean' in while loop"
+                             .format(cond_type))
         while cond_val:
-            walk_stmt_list(body, step_state=stepping)
-            (COND_TYPE, cond_val) = map2boolean(walk(cond))
+            walk(body_stmts)
+            (cond_type, cond_val) = walk(cond)
+            if cond_type != 'boolean':
+                raise ValueError("found '{}' expected 'boolean' in while loop"
+                                .format(cond_type))
     except Break:
         pass
 
 #########################################################################
 def repeat_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
-    (REPEAT, body_stmts, cond_exp) = node
+    (REPEAT, body_stmts, (COND_EXP, cond)) = node
     assert_match(REPEAT, 'repeat')
 
-    (COND_EXP, cond) = cond_exp
-    (STMT_LIST, body) = body_stmts
-
     try:
-        stepping = debugger_has_stepped()
         while True:
-            walk_stmt_list(body, step_state=stepping)
-            (COND_TYPE, cond_val) = map2boolean(walk(cond))
+            walk(body_stmts)
+            (cond_type, cond_val) = walk(cond)
+            if cond_type != 'boolean':
+                raise ValueError("found '{}' expected 'boolean' in repeat loop"
+                                .format(cond_type))
             if cond_val:
                 break
 
@@ -1417,9 +1393,9 @@ def repeat_stmt(node):
 
 #########################################################################
 def for_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
-    (FOR, (IN_EXP, in_exp), (STMT_LIST, stmt_list)) = node
+    (FOR, (IN_EXP, in_exp), stmt_list) = node
     assert_match(FOR, 'for')
 
     (IN, pattern, list_term) = in_exp
@@ -1445,7 +1421,6 @@ def for_stmt(node):
     #             print y.
     #      end for
     try:
-        stepping = debugger_has_stepped()
         for term in list_val:
             try:
                 unifiers = unify(term,pattern)
@@ -1453,14 +1428,24 @@ def for_stmt(node):
                 pass
             else:
                 declare_unifiers(unifiers)
-                walk_stmt_list(stmt_list, step_state=stepping)
+                walk(stmt_list)
                 
     except Break:
         pass
 
+#########################################################################
+def match_stmt(node):
+    if state.debugger: state.debugger.step()
+
+    (MATCH, val, if_clauses) = node
+    assert_match(MATCH, 'match')
+
+    walk(val)
+    walk(if_clauses)
+    
 #########################################################################
 def if_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (IF, (LIST, if_list)) = node
     assert_match(IF, 'if')
@@ -1473,16 +1458,20 @@ def if_stmt(node):
 
         (IF_CLAUSE,
          (COND, cond),
-         (STMT_LIST, stmts)) = if_list[ i + 1 ]
+         stmts) = if_list[ i + 1 ]
 
-        (BOOLEAN, cond_val) = map2boolean(walk(cond))
+        (cond_type, cond_val) = walk(cond)
+        if cond_type != 'boolean':
+            raise ValueError("found '{}' expected 'boolean' in if clause"
+                            .format(cond_type))
 
         if cond_val:
-            walk_stmt_list(stmts)
+            walk(stmts)
             break
+
 #########################################################################
 def struct_def_stmt(node):
-    notify_debugger()
+    if state.debugger: state.debugger.step()
 
     (STRUCT_DEF, (ID, struct_id), (MEMBER_LIST, (LIST, member_list))) = node
     assert_match(STRUCT_DEF, 'struct-def')
@@ -1522,68 +1511,32 @@ def struct_def_stmt(node):
     state.symbol_table.enter_sym(struct_id, struct_type)
 
 #########################################################################
-def import_stmt(node):
-    notify_debugger()
-
-    global debugging
-    old_debugging = debugging
-    debugging = False
-
-    (LIST, inlist) = node
-    assert_match(LIST, 'import_stmt')
+def module_def_stmt(node):
 
-    for e in inlist:
-        walk(e)
-
-    debugging = old_debugging
-
-    return
-
-#########################################################################
-def top_level_exp_stmt(node):
+    (MODULE_DEF, (ID, modname), stmts) = node
+    assert_match(MODULE_DEF, 'module-def')
 
-    (TOP_LEVEL_EXP, exp) = node
-    assert_match(TOP_LEVEL_EXP, 'top-level-exp')
 
-    notify_debugger()
+    state.symbol_table.push_scope({})
+    if state.debugger: state.debugger.enter_module(modname)
+    walk(stmts)
+    closure = state.symbol_table.get_closure()
+    if state.debugger: state.debugger.exit_module(modname)
+    state.symbol_table.pop_scope()
 
-    return walk(exp)
+    module_type = ('module', ('id', modname), ('scope', closure))
+    state.symbol_table.enter_sym(modname, module_type)
 
 #########################################################################
-def eval_exp(node):
-
-    (EVAL, exp) = node
-    assert_match(EVAL, 'eval')
- 
-    # 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.
-
-    state.trace_stack.append((state.lineinfo[0],
-                              state.lineinfo[1],
-                              "eval"))
+def load_stmt(node):
+    if state.debugger: state.debugger.step()
 
+    (LOAD_STMT, inlist) = node
+    assert_match(LOAD_STMT, 'load-stmt')
 
-    # evaluate actual parameter
-    exp_val_expand = walk(exp)
+    walk(inlist)
 
-    # now walk the actual term
-    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
+    return
 
 #########################################################################
 def apply_exp(node):
@@ -1591,7 +1544,7 @@ def apply_exp(node):
     assert_match(APPLY, 'apply')
 
     # handle builtin operators that look like apply lists.
-    if f[0] == 'id' and f[1] in operator_symbols:
+    if f[0] == 'id' and f[1] in builtins:
         return handle_builtins(node)
 
     # handle function application
@@ -1603,11 +1556,10 @@ def apply_exp(node):
         # computed.
         f_name = 'lambda'
     elif f[0] == 'index':
-        # object member function
+        # member/module function
         (INDEX, ix, (ID, f_name)) = f
-        # 'str' is necessary in case we use an index value
-        # instead of a function name -- see regression test test085.ast
-        f_name = "member function " + str(f_name)
+        if not isinstance(f_name, str):
+            raise ValueError("function names have to be strings")
     else:
         # just a regular function call
         (ID, f_name) = f
@@ -1633,7 +1585,13 @@ def apply_exp(node):
 
     # object constructor call
     elif f_val[0] == 'struct':
-        (ID, struct_id) = f
+        if f[0] == 'index':
+            # constructor name qualified with a module name
+            (INDEX, (ID, modname), (ID, struct_id)) = f
+        else: 
+            # inscope constructor call
+            modname = None
+            (ID, struct_id) = f
         (STRUCT,
          (MEMBER_NAMES, (LIST, member_names)),
          (STRUCT_MEMORY, (LIST, struct_memory))) = f_val
@@ -1644,6 +1602,7 @@ def apply_exp(node):
         # create our object
         obj_ref = ('object',
                    ('struct-id', ('id', struct_id)),
+                   ('member-names', ('list', member_names)),
                    ('object-memory', ('list', object_memory)))
         # if the struct has an __init__ function call it on the object
         # NOTE: constructor functions do not have return values.
@@ -1651,11 +1610,15 @@ def apply_exp(node):
         if '__init__' in member_names:
             slot_ix = member_names.index('__init__')
             init_fval = struct_memory[slot_ix]
-            # calling a member function - push struct scope
+            # calling a member function
+            if modname:
+                orig_config = set_module_env(modname)
             handle_call(obj_ref,
                         init_fval,
                         arg_val,
                         f_name)
+            if modname:
+                set_config(orig_config)
         # the struct does not have an __init__ function but
         # we have a constructor call with args, e.g. Foo(1,2)
         # try to apply a default constructor by copying the
@@ -1729,19 +1692,6 @@ def tuple_exp(node):
 
     return ('tuple', outtuple)
 
-#########################################################################
-def escape_exp(node):
-
-    (ESCAPE, s) = node
-    assert_match(ESCAPE, 'escape')
-
-    global __retval__
-    __retval__ = ('none', None)
-
-    exec(s)
-
-    return __retval__
-
 #########################################################################
 def is_exp(node):
 
@@ -1787,8 +1737,10 @@ def if_exp(node):
     if else_exp[0] == 'null':
         raise ValueError("if expressions need an 'else' clause")
 
-    (BOOLEAN, cond_val) = map2boolean(walk(cond_exp))
-
+    (cond_type, cond_val) = walk(cond_exp)
+    if cond_type != 'boolean':
+        raise ValueError("found '{}' expected 'boolean' in if expression"
+                        .format(cond_type))
     if cond_val:
         return walk(then_exp)
     else:
@@ -1874,30 +1826,13 @@ def process_lineinfo(node):
     (LINEINFO, lineinfo_val) = node
     assert_match(LINEINFO, 'lineinfo')
 
-    if debugging:
-        debugger.set_lineinfo(lineinfo_val)
-
-    #lhh
-    #print("lineinfo: {}".format(lineinfo_val))
-
     state.lineinfo = lineinfo_val
 
 #########################################################################
-def deref_exp(node):
-
-    # deref operators are only meaningful during pattern matching
-    # 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):
-
-    # 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 therefore
-    # we raise an error.
-    raise ValueError("a constraint pattern cannot be used as an expression.")
+def illegal_exp(_):
+    # we got here because we tried to use a non-trivial pattern as 
+    # constructors.
+    raise ValueError("not a valid expression")
 
 #########################################################################
 def set_ret_val(node):
@@ -1909,62 +1844,19 @@ def set_ret_val(node):
     function_return_value.pop()
     function_return_value.append(val)
 
-    # Debugger keeps track of the most recent
-    # return value
-    if debugging and val:
-        debugger.retval = term2string(val)
-
     return
 
 #########################################################################
-def walk_stmt_list(stmts, step_state=None):
-    # step_stae is a flag to tell us if we actually
-    # want to step through to the next line of the stmt
-    # list while debugging
-    
-    # We only want to do this if we're debugging
-    # and we've stepped through to this point or
-    # have continued to this point. Basically, this
-    # flag tells us if we've stepped or continued 
-    # into this function call, effectively telling
-    # the debugger to treat it as the top level
-
-    # This also allows us to keep loop execution
-    # control working with the debugger. Meaning
-    # we can do a "next" on the last line in a 
-    # loop and go back to the top as opposed to the
-    # next line after the loop
-    if step_state:
-        stepping = step_state
-    else:
-        stepping = debugger_has_stepped()
-
-    for s in stmts[1]:
-
-        if debugging:
-            # Set the debugger's info reflect new "top level"
-            if stepping: debugger.set_top_level(True)
-
-            # If we've hit a return and we're in continue-until-return
-            # mode, notify the debugger
-
-            # TODO: (OWM) get this working for implicit returns as well.
-            # This currently doesn't work because you can have an implicit
-            # return before a return statement. In this case, the return
-            # statement consumes the return behavior because it is the
-            # final statement in the stmt_list
-
-            # OWM -- This is still true but I'm not sure the fix for it
-            # nor if it should even be fixed
-
-            # The statement is a return the debugger is executing until return
-            # then notify the debugger
-            if debugging and \
-                debugger.exc['RETURN'] and s[0] == 'return':
-                
-                notify_debugger(at_return=True)
-            
-        walk(s)
+def clear_ret_val(node):
+    (CLEAR_RET_VAL,) = node
+    assert_match(CLEAR_RET_VAL, 'clear-ret-val')
+
+    global function_return_value    
+    # If we have no function return value, then append None    
+    if function_return_value != []:
+        function_return_value.pop()       
+    function_return_value.append(None)
+    return
 
 #########################################################################
 # walk
@@ -1973,69 +1865,23 @@ def walk(node):
     # node format: (TYPE, [child1[, child2[, ...]]])
     type = node[0]
 
-    if type == 'clear-ret-val':
-        # implemented here instead of dictionary for efficiency reasons
-        global function_return_value    
-
-        # If we have no function return value, then append None    
-        if function_return_value != []:
-            function_return_value.pop()
-        
-        function_return_value.append(None)
-        return
-    elif type in dispatch_dict:
+    if type in dispatch_dict:
         node_function = dispatch_dict[type]
         return node_function(node)
     else:
         raise ValueError("feature '{}' not yet implemented".format(type))
 
-#########################################################################
-# walk_program
-#########################################################################
-def walk_program(node):
-    """
-    This function exists mostly as a performance
-    boost to unify. Running the program through
-    this function overrides the debugger wrapping
-    on unify.
-    """
-    global unify
-    unify = __unify
-
-    walk(node)
-
-#########################################################################
-# debug_walk
-#########################################################################
-def debug_walk(node, dbg):
-    """
-    This function allows us to keep the top-level distinction
-    at the program level.
-    """
-    global debugging, debugger, unify
-    debugging, debugger = (True, dbg)
-
-    unify = debug_unify
-
-    (LIST, inlist) = node
-
-    for e in inlist:
-        # We want to differentiate between top level and nested
-        # statements. So, we run the list of statements outright
-        # so we can control when we know we are at the top level
-        debugger.set_top_level(True)
-        walk(e)
-
 #########################################################################
 # 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
+    'load-stmt'     : load_stmt,
+    'stmt-list'     : stmt_list,
     'lineinfo'      : process_lineinfo,
     'set-ret-val'   : set_ret_val,
+    'clear-ret-val' : clear_ret_val,
+    'exp-stmt'      : exp_stmt,
     'noop'          : lambda node : None,
-    'assert'        : assert_stmt,
     'unify'         : unify_stmt,
     'while'         : while_stmt,
     'loop'          : loop_stmt,
@@ -2044,14 +1890,14 @@ def debug_walk(node, dbg):
     'global'        : global_stmt,
     'return'        : return_stmt,
     'break'         : break_stmt,
+    'match'         : match_stmt,
     'if'            : if_stmt,
     'throw'         : throw_stmt,
     'try'           : try_stmt,
     'struct-def'    : struct_def_stmt,
-    'top-level-exp' : top_level_exp_stmt,
+    'module-def'    : module_def_stmt,  # this is part of the load statement
     # expressions - expressions do produce return values
     'list'          : list_exp,
-    'import_stmt'   : import_stmt,
     'tuple'         : tuple_exp,
     'to-list'       : to_list_exp,
     'head-tail'     : head_tail_exp,
@@ -2065,24 +1911,20 @@ def debug_walk(node, dbg):
     'real'          : lambda node : node,
     'boolean'       : lambda node : node,
     'object'        : lambda node : node,
-    'eval'          : eval_exp,
-    # pattern code should be treated like a constant if not ignore_pattern
-    'pattern'         : lambda node : walk(node[1]) if state.ignore_pattern else node,
-    # constraint patterns
-    'constraint'    : constraint_exp,
-    'typematch'     : constraint_exp,
+    'pattern'       : lambda node : node,
+    'scope'         : illegal_exp,
+    'typematch'     : illegal_exp,
     # type tag used in conjunction with escaped code in order to store
     # foreign objects in Asteroid data structures
     'foreign'       : lambda node : node,
     'id'            : lambda node : state.symbol_table.lookup_sym(node[1]),
     'apply'         : apply_exp,
     'index'         : index_exp,
-    'escape'        : escape_exp,
     'is'            : is_exp,
     'in'            : in_exp,
     'if-exp'        : if_exp,
     'member-function-val' : lambda node : node,
-    'deref'         : deref_exp,
+    'deref'         : illegal_exp,
 }
 
 ##############################################################################################
@@ -2130,7 +1972,7 @@ def check_redundancy( body_list, f_name ):
         #get the pattern with the higher level of precedence
         (BODY_H,(PTRN,ptrn_h),stmts_h) = bodies[i + 1]
         assert_match(BODY_H,'body')
-        assert_match(PTRN,'pattern')
+        assert_match(PTRN,'body-pattern')
 
         for j in range(i + 2, len(bodies), 2):
             lineinfo = bodies[ j ]
@@ -2139,7 +1981,7 @@ def check_redundancy( body_list, f_name ):
             #get the pattern with the lower level of precedence
             (BODY_L,(PTRN,ptrn_l),stmts_l) = bodies[j + 1]
             assert_match(BODY_L,'body')
-            assert_match(PTRN,'pattern')
+            assert_match(PTRN,'body-pattern')
 
             #Here we get line numbers in case we throw an error
             # we have to do a little 'tree walking' to get to the
@@ -2164,168 +2006,3 @@ def check_redundancy( body_list, f_name ):
             else:                               #CONFLICTION
                 raise RedundantPatternFound( ptrn_h , ptrn_l , f_name, location_h, location_l )
 
-#######################################################################################
-# *** Asteroid Debugger (ADB) helper functions ***
-# 
-# message_explicit:
-#   The main messaging function for explicit mode. Operates in a similar way the
-#   string.format function does. Read the function's internal docstring for more
-#   information.
-# 
-# notify_debugger:
-#   Notifies the debugger of the current program position. If the debugger is
-#   accepting notifications at the time of call, the debugger will pause and
-#   run the interactive prompt.
-# 
-# notify_explicit:
-#   Similar to notify_debugger but only runs in explicit mode.
-# 
-# explicit_enabled:
-#   A simple helper function. Equivalent to `debugging and debugger.explicit_enabled`
-# 
-# decrease_tab_level:
-#   A simple helper function to manage debugger tab level decrementing.
-#
-# debugger_has_stepped::
-#   Helper function that returns if the debugger has stepped into a function
-#   body or other compound statement
-#
-# term2string:
-#   A generator function used in place of term2string in message_explicit calls.
-#   This allows the computation to be deferred or completely ignored. Much like
-#   a function returning a lambda function
-#
-# debug_unify:
-#   A wrapper for the normal unify function that automatically decreases
-#   the tab level of failed pattern matches.
-#
-#######################################################################################
-def message_explicit(fmt_message, terms=None, level="primary", 
-    increase=False, decrease=False, notify=False):
-
-    """
-    Message explicit expects 1-3 main arguments
-
-    1. A string, which can be a format string or a normal string.
-    2. (Optional) A list of terms to express for a given format string
-    3. The message level (Defaults to primary)
-
-    Format terms can be either plain strings or generators. If a gener-
-    ator is supplied, this function will express it
-
-    fmt_message is a list of terms to be applied in the same
-    way as .format
-
-    --------------------------------------------------------------
-    This function also supports three other options that shorten
-    common development patterns.
-
-    increase: Increases the tab level after the message is written
-    decrease: Decreases the tab level before the message is written
-    notify: Makes a notify_explicit call to stop the debugger within
-            a pattern
-    """
-    if explicit_enabled():
-        if decrease: decrease_tab_level()
-
-        if not terms:
-            debugger.message_explicit(fmt_message, level)
-        else:
-            expressed_terms = []
-            for t in terms:
-                expressed_terms.append(t)
-            
-            expressed_string = fmt_message.format(*expressed_terms)
-            debugger.message_explicit(expressed_string, level)
-        
-        if increase:    debugger.tab_level += 1
-        if notify:      notify_explicit()
-
-#########################################################################
-def notify_debugger(at_return=False):
-    """
-    If the debugger is accepting notifications at the time of call,
-    the debugger will pause and run the interactive prompt.
-    """
-    if debugging:
-        # We need to save the old lineinfo in case we go into a REPL
-        old_lineinfo = state.lineinfo
-
-        debugger.notify(at_return)
-
-        # Reset our lineinfo
-        state.lineinfo = old_lineinfo
-        debugger.set_lineinfo(state.lineinfo)
-
-#########################################################################
-def notify_explicit():
-    """
-    If the debugger is accepting notifications at the time of call and
-    the debugger is in explicit mode, the debugger will pause and run
-    the interactive prompt.
-    """
-    if debugging and explicit_enabled:
-        old_lineinfo = state.lineinfo
-        
-        debugger.notify_explicit()
-
-        # Reset our lineinfo
-        state.lineinfo = old_lineinfo
-        debugger.set_lineinfo(state.lineinfo)
-
-#########################################################################
-def explicit_enabled():
-    """
-    Helper function that returns the state
-    of explicit mode if debugging is enableds
-    """
-    return debugging and debugger.explicit_enabled
-
-#########################################################################
-def debugger_has_stepped():
-    """
-    Returns the step/continue state of the debugger
-    """
-    return debugging and \
-            (debugger.exc['STEP'] or debugger.exc['CONTINUE'])
-
-#########################################################################
-def decrease_tab_level():
-    """
-    Decreases/handles the debugger's tab level
-    """
-    if debugging:
-        debugger.tab_level = debugger.tab_level - 1
-
-        if debugger.tab_level < 0:
-            debugger.tab_level = 0
-
-#########################################################################
-def debug_unify(term, pattern, unifying = True):
-    '''
-    Proxy function for unify to make the debugger's formatting
-    work properly
-
-    OWM - This proxy function allows us to wrap unification
-    in an except block and catch when PatternMatchFailed exceptions
-    occur. In this situation, we need to decrease the tab level
-    and then re-raise the exception. Being able to "unravel"
-    tab levels is essential to making things look good.
-
-    In normal, non-debugging execution, this function is overridden
-    and not used.
-    '''
-
-    # Try to call the actual unify function
-    try:
-        return __unify(term, pattern, unifying)
-
-    # If there's a pattern match failed, decrease
-    # the tab level and reraise the exception
-    except PatternMatchFailed as r:
-        decrease_tab_level()
-        raise r
-
-    # If there's a normal exception, reraise it
-    except Exception as e:
-        raise e
\ No newline at end of file
diff --git a/docs/ADB.rst b/docs/ADB.rst
deleted file mode 100644
index 0fc35f7a..00000000
--- a/docs/ADB.rst
+++ /dev/null
@@ -1,222 +0,0 @@
-..
-    /******************************************************************
-    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
-===================
-The Asteroid Debugger (ADB) is a source code debugger for the Asteroid programming language.
-
-It supports the following:
-
-* Breakpoints
-* Single stepping at the source level
-* Stepping through function calls
-* Stack frame inspection
-* Evaluation of arbitrary Asteroid code
-* Macros
-* REPL Instances
-
-ADB features a unique "explicit" mode which details much of the pattern matching and underlying
-mechanics of Asteroid allow developers to debug pattern matches. Explicit mode
-details many of the steps of pattern matching, function calling, statement execution, and
-return values. Explicit mode is very experimental and is under current research. As a result,
-explicit mode is currently incomplete.
-
-Usage
-=======
-``asteroid --adb <FILENAME>``
-
-``asteroid -g <FILENAME>``
-
-Debugging sessions
-==================
-The debugger's prompt ``(ADB)`` allows the user to enter commands to effect the source environment
-and debugger behavior.
-
-Each debugging session will have a few pieces of information:
-
-**Filename and line number**
-::
-
-	[/home/user/test.ast (1)]
-
-**The current line which will be executed**
-::
-
-    -->> let p = pattern %[(x:%integer) if x > 0 and x < 100]%.
-
-**The command prompt**
-::
-
-  (ADB)
-
-ADB runs like any other debugger, here's a small example session where
-we see running commands, listing the program, and setting and continuing to breakpoints.
-::
-
-  [/home/user/test.ast (1)]
-  -->> let p = pattern %[(x:%integer) if x > 0 and x < 100]%.
-  (ADB) ll
-  ----- Program Listing -----
-  >  1 let p = pattern %[(x:%integer) if x > 0 and x < 100]%.
-     2
-     3 let d = pattern %[(x:*p, y:*p, z:*p)]%.
-     4 let x:*p = 99.
-     5
-     6 let t:*d = (1,2,3).
-     7 [EOF]
-  (ADB) break 6
-  (ADB) continue
-  ----- Breakpoint -----
-  [/home/user/test.ast (6)]
-  -->> let t:\*d = (1,2,3).
-  (ADB)
-
-Commands
-========
-Below is a list of the commands available to the debugger. Most of which can be shortened.
-These shortenings are shown in parenthesis (`c(ommand)`).
-
-List
-----
-``l(ist)`` lists the lines around the currently executing line
-
-Longlist
----------
-``ll (longlist)`` lists the entire program
-
-Step
----------
-``s(tep)`` through to the next statement or through function call.
-
-Continue
----------
-``c(ontinue)`` ``cont(inue)`` continue execution until the next breakpoint.
-
-Next
----------
-``n(ext)`` continue onto the next executing line at the current scope.
-
-Until
----------
-``u(ntil) ?lineno`` By default, continue execution until a line with a greater number
-than the current one is reached.
-
-Given an optional line number, continue execution until a line number greater than
-or equal to that number is reached
-
-Return
----------
-``(r(et))urn`` Continue execution until the return of the current function is reached
-
-Breakpoints
-------------
-``b(reak) number\*`` set a breakpoint at one or more lines. Running without any arguments
-lists your breakpoints.
-
-Example: ``b 1 2 3``, ``break``.
-
-Conditional breakpoints can be set in the same way, just attach ``if eval("condition")``
-after each breakpoint number.
-
-Example:
-::
-
-    -- Set a conditional breakpoint on 10 and normal breakpoints on 11, 15, and 23.
-    b 10 if eval("x == 123") 11 15 23
-
-Delete
----------
-``d(elete) (number)+`` ``del(ete) (number)+`` delete a list of breakpoints.
-
-Example:
-::
-
-    del 1 5 8 9
-
-Macro
----------
-``macro (name) (command list)``. Define a macro. Running just ``macro`` lists your macros.
-
-Example macro that continues to a breakpoint and prints the value of ``x``:
-::
-
-    macro gox = c; eval("io@println(x)");
-
-Eval
----------
-`eval("asteroid code")` Evaluate the asteroid code between quotes. Works exactly like a single-line
-repl.
-
-Example, print out the value of ``x``:
-::
-
-    eval("x")
-
-!
----------
-``!`` Open up a repl in the current context
-
-\_\_retval\_\_
---------------
-``(_)_retval`` Print the most recent return value
-
-Help
----------
-``h(elp) (command)?`` gives help for a given command. Running just ``help`` shows all available commands.
-Example:
-::
-
-    h macro
-    help break
-
-Retval
----------
-``((r)et)val`` Prints the most recent return value
-
-<
----------
-``<`` move up one stack frame
-
->
----------
-``>`` move down one stack frame
-
-Where
----------
-``w(here)`` displays the frame stack and the currently active frame.
-
-Explicit
----------
-``e(xplicit) (on|off)?`` By default, this command run without an argument toggles
-explicit mode. If given a literal ``on`` or ``off``, explicit mode will be switched
-to the corresponding state.
-
-Explicit
-::
-
-    -- Toggle Explicit mode
-    explicit
-    e
-
-    -- Turn on/off
-    explicit on
-    e on
-    explicit off
-    e off
-
-Quit
----------
-``q(uit)`` Quits the current ADB session
diff --git a/docs/ADB.txt b/docs/ADB.txt
deleted file mode 100644
index 2153a9e7..00000000
--- a/docs/ADB.txt
+++ /dev/null
@@ -1,220 +0,0 @@
-..
-    /******************************************************************
-    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"
-
-    ******************************************************************/
-
-#include "header.txt"
-
-===================
-ADB Reference Guide
-===================
-The Asteroid Debugger (ADB) is a source code debugger for the Asteroid programming language.
-
-It supports the following:
-
-* Breakpoints
-* Single stepping at the source level
-* Stepping through function calls
-* Stack frame inspection
-* Evaluation of arbitrary Asteroid code
-* Macros
-* REPL Instances
-
-ADB features a unique "explicit" mode which details much of the pattern matching and underlying
-mechanics of Asteroid allow developers to debug pattern matches. Explicit mode
-details many of the steps of pattern matching, function calling, statement execution, and
-return values. Explicit mode is very experimental and is under current research. As a result,
-explicit mode is currently incomplete.
-
-Usage
-=======
-``asteroid --adb <FILENAME>``
-
-``asteroid -g <FILENAME>``
-
-Debugging sessions
-==================
-The debugger's prompt ``(ADB)`` allows the user to enter commands to effect the source environment
-and debugger behavior.
-
-Each debugging session will have a few pieces of information:
-
-**Filename and line number**
-::
-
-	[/home/user/test.ast (1)]
-
-**The current line which will be executed**
-::
-
-    -->> let p = pattern %[(x:%integer) if x > 0 and x < 100]%.
-
-**The command prompt**
-::
-
-  (ADB)
-
-ADB runs like any other debugger, here's a small example session where
-we see running commands, listing the program, and setting and continuing to breakpoints.
-::
-
-  [/home/user/test.ast (1)]
-  -->> let p = pattern %[(x:%integer) if x > 0 and x < 100]%.
-  (ADB) ll
-  ----- Program Listing -----
-  >  1 let p = pattern %[(x:%integer) if x > 0 and x < 100]%.
-     2
-     3 let d = pattern %[(x:*p, y:*p, z:*p)]%.
-     4 let x:*p = 99.
-     5
-     6 let t:*d = (1,2,3).
-     7 [EOF]
-  (ADB) break 6
-  (ADB) continue
-  ----- Breakpoint -----
-  [/home/user/test.ast (6)]
-  -->> let t:\*d = (1,2,3).
-  (ADB)
-
-Commands
-========
-Below is a list of the commands available to the debugger. Most of which can be shortened.
-These shortenings are shown in parenthesis (`c(ommand)`).
-
-List
-----
-``l(ist)`` lists the lines around the currently executing line
-
-Longlist
----------
-``ll (longlist)`` lists the entire program
-
-Step
----------
-``s(tep)`` through to the next statement or through function call.
-
-Continue
----------
-``c(ontinue)`` ``cont(inue)`` continue execution until the next breakpoint.
-
-Next
----------
-``n(ext)`` continue onto the next executing line at the current scope.
-
-Until
----------
-``u(ntil) ?lineno`` By default, continue execution until a line with a greater number
-than the current one is reached.
-
-Given an optional line number, continue execution until a line number greater than
-or equal to that number is reached
-
-Return
----------
-``(r(et))urn`` Continue execution until the return of the current function is reached
-
-Breakpoints
-------------
-``b(reak) number\*`` set a breakpoint at one or more lines. Running without any arguments
-lists your breakpoints.
-
-Example: ``b 1 2 3``, ``break``.
-
-Conditional breakpoints can be set in the same way, just attach ``if eval("condition")``
-after each breakpoint number.
-
-Example:
-::
-
-    -- Set a conditional breakpoint on 10 and normal breakpoints on 11, 15, and 23.
-    b 10 if eval("x == 123") 11 15 23
-
-Delete
----------
-``d(elete) (number)+`` ``del(ete) (number)+`` delete a list of breakpoints.
-
-Example:
-::
-
-    del 1 5 8 9
-
-Macro
----------
-``macro (name) (command list)``. Define a macro. Running just ``macro`` lists your macros.
-
-Example macro that continues to a breakpoint and prints the value of ``x``:
-::
-
-    macro gox = c; eval("io@println(x)");
-
-Eval
----------
-`eval("asteroid code")` Evaluate the asteroid code between quotes. Works exactly like a single-line
-repl.
-
-Example, print out the value of ``x``:
-::
-
-    eval("x")
-
-!
----------
-``!`` Open up a repl in the current context
-
-\_\_retval\_\_
---------------
-``(_)_retval`` Print the most recent return value
-
-Help
----------
-``h(elp) (command)?`` gives help for a given command. Running just ``help`` shows all available commands.
-Example:
-::
-
-    h macro
-    help break
-
-Retval
----------
-``((r)et)val`` Prints the most recent return value
-
-<
----------
-``<`` move up one stack frame
-
->
----------
-``>`` move down one stack frame
-
-Where
----------
-``w(here)`` displays the frame stack and the currently active frame.
-
-Explicit
----------
-``e(xplicit) (on|off)?`` By default, this command run without an argument toggles
-explicit mode. If given a literal ``on`` or ``off``, explicit mode will be switched
-to the corresponding state.
-
-Explicit
-::
-
-    -- Toggle Explicit mode
-    explicit
-    e
-
-    -- Turn on/off
-    explicit on
-    e on
-    explicit off
-    e off
-
-Quit
----------
-``q(uit)`` Quits the current ADB session
diff --git a/docs/Asteroid in Action.rst b/docs/Asteroid in Action.rst
index 24152c0e..caaa390b 100644
--- a/docs/Asteroid in Action.rst
+++ b/docs/Asteroid in Action.rst
@@ -201,7 +201,7 @@ Challenge: Incrementing filenames
   let ext = ".txt".
 
   for i in 1 to 5 do
-      io @println (root+i+ext).
+      io @println (root + tostring i + ext).
   end
 Output::
 
@@ -220,7 +220,6 @@ Challenge: Random passwords
 In our solution we take advantage of Asteroid's ``Pick`` object.  The ``Pick`` object maintains a list of items that we can randomly select from using the ``pick`` member function.  As input to the ``Pick`` object, we compute a bunch of lists of characters that are useful for password construction.  The function ``achar`` converts a decimal ASCII code to a single character string.
 ::
   load system io.
-  load system type.
   load system util.
   load system pick.
   load system random.
@@ -228,7 +227,7 @@ In our solution we take advantage of Asteroid's ``Pick`` object.  The ``Pick`` o
   random @seed(42).
 
   -- make up lists of symbols useful for password construction
-  let int_list = [0 to 9] @map(type @tostring).
+  let int_list = [0 to 9] @map(tostring).
   let lc_list = [97 to 122] @map(util @achar). -- lower case characters
   let uc_list = [65 to 90] @map(util @achar). --upper case characters
   let sp_list = ["!","_","#","$","%","*"].
@@ -366,7 +365,7 @@ If there is only one file, then the phrase should be ``1 file found`` instead.
   load system io.
 
   for n in 0 to 5 do
-      io @println (n+" file"+("s " if n>1 or n==0 else " ")+"found").
+      io @println (tostring n + " file" + ("s " if n>1 or n==0 else " ") + "found").
   end
 Output::
 
@@ -427,7 +426,7 @@ In our solution we use a hash table to count the number of word occurences.
   -- put the words into a hash table, the value is the count of the words
   let ht = hash @hash().
   for w in wl do
-      if not ht @get(w) do
+      if ht @get(w) is none do
           ht @insert(w,1).
       else do
           ht @insert(w,ht @get(w)+1).
@@ -467,13 +466,13 @@ second string (``strb``).
   for startix in 0 to stra @length()-1 do
       for endix in startix to stra @length()-1 do
           let s = stra @[startix to endix].
-          if strb @index(s) and s @length() > common @length() do
+          if strb @index(s) =/= -1 and s @length() > common @length() do
               let common = s.
           end
       end
   end
 
-  if common do
+  if common =/= "" do
       io @println ("The longest common substring is '"+common+"'.").
   else do
       io @println ("There are no common substrings.").
@@ -711,7 +710,7 @@ We do this by finding and hashing N-grams after the appropriate preprocessing.
       -- Note: make this code more general
       let n_gram = [word_list@i, word_list@(i+1), word_list @(i+2)] @join(" ").
       -- put the N-gram into a hash table, the value is the count of the N-gram in the text.
-      if not ht @get(n_gram) do
+      if ht @get(n_gram) is none do
           ht @insert(n_gram,1).
       else do
           ht @insert(n_gram,ht @get(n_gram)+1).
@@ -719,7 +718,7 @@ We do this by finding and hashing N-grams after the appropriate preprocessing.
   end
 
   for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
-      io @println (n_gram+": "+cnt).
+      io @println (n_gram+": "+ tostring cnt).
   end
 Output::
 
@@ -759,7 +758,7 @@ Other constants are also available.
   load system io.
   load system math.
 
-  let tau = 2 * math @pi.
+  let tau = 2.0 * math @pi.
 
   io @println (math @e).
   io @println tau.
@@ -812,7 +811,7 @@ the predicate applied to the input is true.  The last case is of some interest b
           throw Error("factorial is not defined for "+n).
       end
 
-  io @println ("The factorial of 3 is: " + fact (3)).
+  io @println ("The factorial of 3 is: " + tostring(fact 3)).
   assert (fact(3) == 6).
 Output::
 
@@ -956,7 +955,7 @@ Prime numbers are those that can be divided only by 1, and by themselves.
   function isprime with x do
       if x >= 2 do
           for y in range(2,x) do
-              if not math @mod(x,y) do
+              if math @mod(x,y) == 0 do
                   return false.
               end
           end
@@ -989,7 +988,7 @@ Challenge: List of prime numbers
   function isprime with x do
       if x >= 2 do
           for y in range(2,x) do
-              if not math @mod(x,y) do
+              if math @mod(x,y) == 0 do
                   return false.
               end
           end
@@ -1035,7 +1034,7 @@ Prime factors are the prime numbers that divide the given integer number exactly
   function isprime with x do
       if x >= 2 do
           for y in range(2,x) do
-              if not math @mod(x,y) do
+              if math @mod(x,y) == 0 do
                   return false.
               end
           end
@@ -1061,7 +1060,7 @@ Prime factors are the prime numbers that divide the given integer number exactly
   while n > 1 do
       let factor = primes_list @ix.
       let ix = ix+1.
-      if not math @mod(n,factor) do
+      if math @mod(n,factor) == 0 do
           let ix = 0.
           let n = n/factor.
           let factors = factors+[factor].
@@ -1141,7 +1140,6 @@ Asteroid has two random number generation functions: ``random()`` generates a ra
   load system io.
   load system random.
   load system util.
-  load system type.
 
   let randint = random @randint.
 
@@ -1153,7 +1151,7 @@ Asteroid has two random number generation functions: ``random()`` generates a ra
 
   -- generating a random number in the appropriate interval
   let n = 10.
-  io @println (randint(0.0,type @toreal(n))).
+  io @println (randint(0.0, toreal n)).
   io @println (randint(0,n)).
 Output:
 ::
@@ -1182,18 +1180,17 @@ To illustrate it with an example, let’s take the number 1234 as the seed. On s
 ::
   load system io.
   load system util.
-  load system type.
 
   let n = 1234.
   let sq = n*n.
-  let sq_str = type @tostring(sq).
+  let sq_str = tostring sq.
   if sq_str @length() < 8 do
       let prefix = [1 to 8-sq_str@length()] @map(lambda with _ do return "0")
                                             @join("").
       let sq_str = prefix + sq_str.
   end
   let rstr = sq_str @[2 to 5].
-  let rval = type @tointeger(rstr).
+  let rval = tointeger rstr.
   io @println rval.
 
   assert (rval == 5227)
@@ -1300,11 +1297,11 @@ where :math:`n` is the number of elements in the array :math:`x`; :math:`\bar{x}
 
   let values = [727.7, 1086.5, 1091.0, 1361.3, 1490.5, 1956.1].
 
-  let avg = values @reduce(lambda with (x,y) do return x+y) / values @length().
+  let avg = values @reduce(lambda with (x,y) do return x+y) / toreal(values @length()).
   let diff_sq = values @map(lambda with x do return math @pow(x-avg,2)).
   let numerator = diff_sq @reduce(lambda with (x,y) do return x+y).
   let denominator = values @length() -1.
-  let sigma = math @sqrt(numerator/denominator).
+  let sigma = math @sqrt(numerator/toreal denominator).
   io @println sigma.
 
   assert (sigma == 420.96248961952256)
@@ -1372,7 +1369,6 @@ All these variants can be implemented by using ``with`` clauses and conditional
   load system io.
   load system math.
   load system util.
-  load system type.
 
   -- define common math functions locally so the
   -- formulas are easy to read
@@ -1382,7 +1378,6 @@ All these variants can be implemented by using ``with`` clauses and conditional
   let pow = math @pow.
   let atan = math @atan.
   let pi = math @pi.
-  let toreal = type @toreal.
 
   function polar_to_cartesian with (r,psi) do
       -- return a tuple: (x,y)
@@ -1395,11 +1390,11 @@ All these variants can be implemented by using ``with`` clauses and conditional
 
   function cartesian_to_psi
       with (x,y) if x > 0  do
-          return atan(toreal(y)/x).
+          return atan(toreal y/toreal x).
       with (x,y) if x < 0 and y >= 0 do
-          return atan(toreal(y)/x)+pi.
+          return atan(toreal y/toreal x)+pi.
       with (x,y) if x < 0 and y < 0 do
-          return atan(toreal(y)/x)-pi.
+          return atan(toreal y/toreal x)-pi.
       with (x,y) if x == 0 and y > 0 do
           return pi/2.
       with (x,y) if x == 0 and y < 0 do
@@ -1449,7 +1444,7 @@ To calculate the area of a circle with a radius of 1, pairs of random numbers be
           let inside = inside+1.
       end
   end
-  let area = 4.0 * inside / n.
+  let area = 4.0 * toreal inside / toreal n.
   io @println area.
 
   assert (area == 3.1392).
@@ -1470,19 +1465,18 @@ ask for the initial guess and enter the loop, which compares the guess with the
   load system io.
   load system random.
   load system util.
-  load system type.
 
   random @seed(42).
 
   let n = random @randint(0,10).
-  let guess = type @tointeger(io @input("Guess my number between 0 and 10: ")).
+  let guess = tointeger(io @input("Guess my number between 0 and 10: ")).
   while guess =/= n do
       if guess < n do
           io @println "Too small.".
       elif guess > n  do
            io @println "Too big.".
       end
-      let guess = type @tointeger(io @input("Try again: ")).
+      let guess = tointeger(io @input("Try again: ")).
   end
   io @println "Yes, this is it!".
 Challenge: Binary to integer
@@ -1493,10 +1487,9 @@ Challenge: Binary to integer
 In Asteroid this is straightforward using the built-in ``tointeger`` function, passing it a string representation of the binary number and the base.
 ::
   load system io.
-  load system type.
 
   let bin = "101101".
-  let int = type @tointeger(bin,2).
+  let int = tointeger(bin,2).
   io @println int.
 
   assert (int == 45).
@@ -1514,10 +1507,6 @@ Challenge: Integer as binary, octal, and hex
 In Asteroid this is easily done with the ``tobase`` function.
 ::
   load system io.
-  load system type.
-
-  let tobase = type @tobase.
-  let tointeger = type @tointeger.
 
   let val = 42.
 
@@ -1545,14 +1534,13 @@ Challenge: Sum of digits
 Pretty straightforward using string and list manipulation.
 ::
   load system io.
-  load system type.
 
   let number = 139487854.
 
 
-  let s = type @tostring number @explode()
-                                @map(type @tointeger)
-                                @reduce(lambda with (x,y) do return x+y).
+  let s = tostring number @explode()
+                          @map tointeger
+                          @reduce (lambda with (x,y) do x+y).
   io @println s.
 
   assert (s == 49).
@@ -1590,9 +1578,8 @@ Challenge: Compose the largest number
 The easiest way to achieve that is to treat the numbers as strings, sort them alphabetically in descending order, concatenate the pieces to a single string, and get the resulting integer.
 ::
   load system io.
-  load system type.
 
-  let a = type @tointeger([67, 8, 1, 5, 45] @map(type @tostring) @sort(true) @join("")).
+  let a = tointeger ([67, 8, 1, 5, 45] @map tostring @sort true @join "").
   io @println a.
 
   assert (a == 8675451).
@@ -1617,7 +1604,6 @@ In the program below, there are four such sequences: for thousands, hundreds, te
   load system math.
   load system util.
   load system hash.
-  load system type.
 
   let roman_hash = hash @hash().
   roman_hash @insert(1000,["","M","MM","MMM"]).
@@ -1626,11 +1612,11 @@ In the program below, there are four such sequences: for thousands, hundreds, te
   roman_hash @insert(1,["","I","II","III","IV","V","VI","VII","VIII","IX"]).
 
   let n = 2018.
-  let p10 = range(type @tostring n @length()) @map(lambda with x do return math @pow(10,x))
-                                              @reverse().
-  let digits = type @tostring n @explode()
-                                @map(type @tointeger).
-  let z = util @zip(digits, p10).
+  let p10 = range(tostring n @length()) @map(lambda with x do math @pow (10,x))
+                                        @reverse().
+  let digits = tostring n @explode ()
+                          @map tointeger.
+  let z = util @zip (digits, p10).
   io @println z.
   let roman = "".
   for (d,p) in z do
@@ -1680,7 +1666,7 @@ The zero name appears only in the case when the given number is zero.
           return names @n.
       with (n:%integer) if n < 100 do
           let r = names @(n / 10 + 18).
-          let r = r + ("-" + names @(mod(n,10))) if mod(n,10) else "".
+          let r = r + ("-" + names @(mod(n,10))) if mod(n,10) =/= 0 else "".
           return r.
       with (n:%integer) if n < 1000 do
           return spell_part(n,100,"hundred").
@@ -1691,7 +1677,7 @@ The zero name appears only in the case when the given number is zero.
   function spell_part
       with (n:%integer,base:%integer,name:%string) do
           let r = spell_number(n/base) + " " + name.
-          return r + " " + spell_number(mod(n,base)) if mod(n,base) else r.
+          return r + " " + spell_number(mod(n,base)) if mod(n,base) =/= 0 else r.
       end
 
   io @println (spell_number 15).
@@ -1726,7 +1712,7 @@ Consider the complete program:
 
   let (a,b) = (10,20).
   let (b,a) = (a,b).
-  io @println ("a = "+a,"b = "+b).
+  io @println ("a = "+ tostring a,"b = "+ tostring b).
 
   assert ((a,b) is (20,10)).
 Output:
@@ -1993,7 +1979,9 @@ 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")).
+  io @println ((tostring x +" is in the list")
+          if array @member x
+          else (tostring x + " is not in the list")).
 Output:
 ::
 
@@ -2007,10 +1995,10 @@ We can also use a reduction function to solve this,
   let array = [10, 14, 0, 15, 17, 20, 30, 35].
   let x = 17.
 
-  if array @reduce(lambda with (acc,i) do return true if i==x else acc,false) do
-      io @println (x+" is in the list").
+  if array @reduce(lambda with (acc,i) do true if i==x else acc,false) do
+      io @println (tostring x + " is in the list").
   else
-      io @println (x+" is not in the list").
+      io @println (tostring x + " is not in the list").
   end
 Output:
 ::
@@ -2028,12 +2016,11 @@ The easiest way to do this is with a reduction,
   load system io.
   load system math.
   load system util.
-  load system type.
 
   let mod = math @mod.
 
   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).
+  let odd = array @reduce (lambda with (acc,i) do i if isnone acc and mod(i,2) =/= 0 else acc,none).
   io @println odd.
 Output:
 ::
@@ -2049,7 +2036,7 @@ Challenge: Take every second element
   load system io.
   load system math.
 
-  let array = [20 to 30] @filter(lambda with x do return math @mod(x,2)).
+  let array = [20 to 30] @filter(lambda with x do math @mod(x,2)=/=0).
   io @println array.
 
   assert (array == [21,23,25,27,29]).
@@ -2166,14 +2153,13 @@ Challenge: Increasing sequences
 > Check if the given array contains increasing (or decreasing) numbers.
 ::
   load system io.
-  load system type.
 
   let a = [3, 7, 19, 20, 34].
-  let b = type @toboolean(a @reduce(lambda with (x,y) do return y if x<y else false)).
+  let b = a @reduce(lambda with ((_,x),y) do (true,y) if x<=y else (false,y),(true,a@0)).
 
-  io @println b.
+  io @println (b@0).
 
-  assert (b).
+  assert (b@0).
 Output:
 ::
 
@@ -2242,7 +2228,7 @@ The procedure:
       io @println "".
       for r in m do
           for e in r do
-              io @print (e + " ").
+              io @print (tostring e + " ").
           end
           io @println ("").
       end
@@ -2369,7 +2355,7 @@ For example, a hash is a collection mapping a car’s license plate to the colou
 
   let color_hash = hash @hash().
   for (_,color) in fruit_lst do
-      if not color_hash @get(color) do
+      if color_hash @get(color) is none do
           color_hash @insert(color,1).
       else
           color_hash @insert(color, color_hash @get(color) +1).
@@ -2396,16 +2382,15 @@ Challenge: Product table
 We will do this with an outer loop  and a ``map`` function.
 ::
   load system io.
-  load system type.
 
   function format with v do
       let maxlen = 3.
-      let vstr = type @tostring v.
-      return [1 to maxlen-len(vstr)] @map(lambda with _ do return " ") @join("") + vstr.
+      let vstr = tostring v.
+      return [1 to maxlen-len(vstr)] @map(lambda with _ do " ") @join("") + vstr.
   end
 
   for i in 1 to 10 do
-      io @println ([1 to 10] @map(lambda with x do return format(i*x)) @join(" ")).
+      io @println ([1 to 10] @map(lambda with x do format(i*x)) @join(" ")).
   end
 Output:
 ::
@@ -2472,7 +2457,6 @@ The only thing that is left to do is to iterate appropiately and format the outp
   load system io.
   load system vector.
   load system util.
-  load system type.
 
   let triangle = [[1]].
   let ix = 0.
@@ -2487,7 +2471,7 @@ The only thing that is left to do is to iterate appropiately and format the outp
   end
 
   for r in triangle do
-      io @println (r @map(lambda with v do return type @tostring v) @join(" ")).
+      io @println (r @map(lambda with v do tostring v) @join(" ")).
   end
 Output:
 ::
diff --git a/docs/Installing and Running.rst b/docs/Installing and Running.rst
index 6979313c..605bcec1 100644
--- a/docs/Installing and Running.rst
+++ b/docs/Installing and Running.rst
@@ -9,7 +9,7 @@ and is installed using::
 
     $ pip install asteroid-lang
 
-The should work on Unix-like and Windows systems,
+This should work on Unix-like and Windows systems,
 though you may have to use `pip3` or some other variation.
 
   Don't forget to add the `bin` directory where `pip` installs programs
@@ -62,7 +62,7 @@ Asteroid program by typing::
 at the command prompt.  Asteroid also supports an interactive mode::
 
     $ asteroid
-    Asteroid Version 1.1.3
+    Asteroid Version x.y.z
     Type "asteroid -h" for help
     Press CTRL-D to exit
     ast> load system io.
diff --git a/docs/MAD.rst b/docs/MAD.rst
new file mode 100644
index 00000000..7c8de580
--- /dev/null
+++ b/docs/MAD.rst
@@ -0,0 +1,146 @@
+..
+    /******************************************************************
+    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 "MAD.txt" > "MAD.rst"
+
+    ******************************************************************/
+..
+   /* header for generated .rst files */
+
+..
+   *** DO NOT EDIT; MACHINE GENERATED ***
+=========================================
+Minimal Asteroid Debugger Reference Guide
+=========================================
+The Minimal Asteroid Debugger is a source code debugger for the Asteroid programming language.
+It supports the following:
+
+* Breakpoints
+* Single stepping at the source level
+* Stepping through function calls
+* Examining contents of variables in the current scope
+
+The commandline interface of the debugger is modeled after debuggers such as the GNU debugger gdb.
+
+Usage
+=====
+In order to invoke the debugger type,
+::
+    asteroid -d <FILENAME>
+
+This will start a debugging session of the file ``<FILENAME>``.
+Here is an example where ``<FILENAME>`` is ``list.ast``,
+::
+    $ asteroid -d list.ast
+    Minimal Asteroid Debugger -- Version 0.1
+    (c) University of Rhode Island
+    type 'help' for additional information
+    mad>
+
+Debugging sessions
+==================
+During a debugging session the user is able to step through a program and
+examine its state.  The following is debugging session of a program that prints
+out a sequence of integer values,
+::
+    load system io.
+
+    for i in 1 to 5 do
+        let x = i.
+        io @println x.
+    end
+
+We start the debugger as shown above. We then set a breakpoint at the first statement in the
+``for`` loop then ``continue``
+our computation until it hits the break point. We can then look at the contents of
+memory.  Finally we clear all breakpoints and let the computation finish.  Here we go,
+::
+    $ asteroid -d list.ast
+    Minimal Asteroid Debugger -- Version 0.1
+    (c) University of Rhode Island
+    type 'help' for additional information
+    mad> list
+    >  1 load system io.             <<<< current line
+       2
+       3 for i in 1 to 5 do
+       4   let x = i.
+       5   io @println x.
+    mad> set 4                       <<<< setting a breakpoint
+    mad> breakpoints
+    breakpoints:
+    list.ast:4
+    mad> continue                    <<<< continue execution
+    reached breakpoint (list.ast:4)
+       1 load system io.
+       2
+       3 for i in 1 to 5 do
+    >  4   let x = i.
+       5   io @println x.
+       6 end
+       7
+       8 [EOF]
+    mad> print i                     <<<< examining the value of i
+    i: 1
+    mad> continue
+    1
+    reached breakpoint (list.ast:4)
+       1 load system io.
+       2
+       3 for i in 1 to 5 do
+    >  4   let x = i.
+       5   io @println x.
+       6 end
+       7
+       8 [EOF]
+    mad> print i
+    i: 2
+    mad> clear                       <<<< delete breakpoints
+    mad> continue
+    2
+    3
+    4
+    5
+    stopping MAD
+    mad> print i
+    i: 5
+    mad> print x
+    x: 5
+    mad> quit
+    $
+
+Commands
+========
+Here is a table of the available commands in the the debugger,
+::
+    breakpoints .................... show all breakpoints
+    clear .......................... clear all breakpoints
+    continue ....................... continue execution to next breakpoint
+    down ........................... move down one stack frame
+    frame .......................... display current stack frame number
+    help ........................... display help
+    list ........................... display source code
+    next ........................... step execution across a nested scope
+    print <name>|* ................. print contents of <name>, * lists all vars in scope
+    quit ........................... quit debugger
+    stack .......................... display runtime stack
+    set [<func>|<line#> [<file>]] .. set a breakpoint
+    step ........................... step to next executable statement
+    trace .......................... display runtime stack
+    up ............................. move up one stack frame
+    where .......................... print current program line
+
+The or bar ``|`` means different options as arguments to the commands. Anything between
+square brackets is optional.  Anything appearing in angle brackets are actual values.
+For example, ``print <name>`` means we want to examine the value of an actual variable, e.g.
+::
+    print n
+
+where ``n`` is a variable name.
+
+Most commands are very much self-explanatory with the exception of perhaps ``next``.  The ``next``
+command works just like the ``step`` command except that it will skip stepping into nested scopes
+such as function calls or the execution of module statements.
diff --git a/docs/MAD.txt b/docs/MAD.txt
new file mode 100644
index 00000000..11da0f58
--- /dev/null
+++ b/docs/MAD.txt
@@ -0,0 +1,144 @@
+..
+    /******************************************************************
+    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 "MAD.txt" > "MAD.rst"
+
+    ******************************************************************/
+
+#include "header.txt"
+
+=========================================
+Minimal Asteroid Debugger Reference Guide
+=========================================
+The Minimal Asteroid Debugger is a source code debugger for the Asteroid programming language.
+It supports the following:
+
+* Breakpoints
+* Single stepping at the source level
+* Stepping through function calls
+* Examining contents of variables in the current scope
+
+The commandline interface of the debugger is modeled after debuggers such as the GNU debugger gdb.
+
+Usage
+=====
+In order to invoke the debugger type,
+::
+    asteroid -d <FILENAME>
+
+This will start a debugging session of the file ``<FILENAME>``.
+Here is an example where ``<FILENAME>`` is ``list.ast``,
+::
+    $ asteroid -d list.ast   
+    Minimal Asteroid Debugger -- Version 0.1
+    (c) University of Rhode Island
+    type 'help' for additional information
+    mad>
+
+Debugging sessions
+==================
+During a debugging session the user is able to step through a program and 
+examine its state.  The following is debugging session of a program that prints
+out a sequence of integer values,
+::
+    load system io.
+
+    for i in 1 to 5 do
+        let x = i.
+        io @println x.
+    end
+
+We start the debugger as shown above. We then set a breakpoint at the first statement in the
+``for`` loop then ``continue``
+our computation until it hits the break point. We can then look at the contents of 
+memory.  Finally we clear all breakpoints and let the computation finish.  Here we go,
+::
+    $ asteroid -d list.ast
+    Minimal Asteroid Debugger -- Version 0.1
+    (c) University of Rhode Island
+    type 'help' for additional information
+    mad> list
+    >  1 load system io.             <<<< current line
+       2 
+       3 for i in 1 to 5 do
+       4   let x = i.
+       5   io @println x.
+    mad> set 4                       <<<< setting a breakpoint
+    mad> breakpoints
+    breakpoints:
+    list.ast:4
+    mad> continue                    <<<< continue execution
+    reached breakpoint (list.ast:4)
+       1 load system io.
+       2 
+       3 for i in 1 to 5 do
+    >  4   let x = i.
+       5   io @println x.
+       6 end
+       7 
+       8 [EOF]
+    mad> print i                     <<<< examining the value of i
+    i: 1
+    mad> continue
+    1
+    reached breakpoint (list.ast:4)
+       1 load system io.
+       2 
+       3 for i in 1 to 5 do
+    >  4   let x = i.
+       5   io @println x.
+       6 end
+       7 
+       8 [EOF]
+    mad> print i
+    i: 2
+    mad> clear                       <<<< delete breakpoints
+    mad> continue
+    2
+    3
+    4
+    5
+    stopping MAD
+    mad> print i
+    i: 5
+    mad> print x
+    x: 5
+    mad> quit
+    $
+
+Commands
+========
+Here is a table of the available commands in the the debugger,
+::
+    breakpoints .................... show all breakpoints
+    clear .......................... clear all breakpoints
+    continue ....................... continue execution to next breakpoint
+    down ........................... move down one stack frame
+    frame .......................... display current stack frame number
+    help ........................... display help
+    list ........................... display source code
+    next ........................... step execution across a nested scope
+    print <name>|* ................. print contents of <name>, * lists all vars in scope
+    quit ........................... quit debugger
+    stack .......................... display runtime stack
+    set [<func>|<line#> [<file>]] .. set a breakpoint
+    step ........................... step to next executable statement
+    trace .......................... display runtime stack
+    up ............................. move up one stack frame
+    where .......................... print current program line
+
+The or bar ``|`` means different options as arguments to the commands. Anything between
+square brackets is optional.  Anything appearing in angle brackets are actual values. 
+For example, ``print <name>`` means we want to examine the value of an actual variable, e.g.
+::
+    print n
+
+where ``n`` is a variable name.
+
+Most commands are very much self-explanatory with the exception of perhaps ``next``.  The ``next``
+command works just like the ``step`` command except that it will skip stepping into nested scopes
+such as function calls or the execution of module statements.
\ No newline at end of file
diff --git a/docs/Reference Guide.rst b/docs/Reference Guide.rst
index 7640596c..72a8b2c2 100644
--- a/docs/Reference Guide.rst
+++ b/docs/Reference Guide.rst
@@ -1,12 +1,12 @@
 ..
       /******************************************************************
       This is the source file from which the reference guide is
-      generated.  We use cpp to insert live code snippets into the
+      generated.  We use pcpp 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
+      following command in the directory of
       this doc:
 
-      bash generate_docs
+      python generate_docs.py
 
       ******************************************************************/
 ..
@@ -32,24 +32,6 @@ represents ``end``.
 Statements
 ^^^^^^^^^^
 
-Assert
-%%%%%%
-
-Syntax: ``ASSERT exp '.'?``
-
-If the expression of the assert statement evaluates to a
-value equivalent to the Boolean value
-``false`` an exception is thrown otherwise the statement is ignored.
-
-For example, the statement,
-::
-      assert (1+1 == 3).
-
-will generate a runtime error but the statement,
-::
-      assert (1+1 == 2).
-
-will be ignored once the expression has been evaluated.
 
 
 Break
@@ -73,7 +55,6 @@ As an example we break out of the indefinite loop below when ``i`` is equal to 1
       end
 
       assert (i==10).
-
 Expressions at the Statement Level
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
@@ -84,11 +65,9 @@ evaluated in a function body is considered the return value of the function.
 
 An example,
 ::
-      function inc
-         with i do
-            i+1.
-         end
-
+      function inc with i do
+         i+1.
+      end
 Notice that because the expression ``i+1`` is the last statement evaluated in the
 function body its value becomes the return value of the function.
 
@@ -113,8 +92,6 @@ the pattern matches the tuple ``(1,"chicken")``,
       for (1,bird) in tuple_list do
          assert(bird is "chicken").
       end
-
-
 Function-Definition
 %%%%%%%%%%%%%%%%%%%
 
@@ -136,7 +113,6 @@ The following is a definition of the ``sign`` function,
          with x if x < 0 do
             return -1.
       end
-
 Here the first function body returns ``1`` if the actual argument is greater or equal to zero.
 The second function body return ``-1`` if the actual argument is less than zero.
 
@@ -153,16 +129,14 @@ Consider the following code snippet,
 ::
       let x = 0.
 
-      function foo
-         with none do
-            global x.
-            let x = 1.
+      function foo with none do
+         global x.
+         let x = 1.
       end
 
       assert(x==0).
       foo().
       assert(x==1).
-
 The ``global`` statement within the function ``foo`` indicates that the ``let`` statement
 on the following line should assign a value to the global variable ``x``.
 
@@ -185,9 +159,8 @@ As an example consider the following ``if`` statement that determines
 what kind of integer value the user supplied,
 ::
       load system io.
-      load system type.
 
-      let x = type @tointeger (io @input "Please enter an integer: ").
+      let x = tointeger (io @input "Please enter an integer: ").
 
       if x < 0 do
           io @println "Negative".
@@ -198,8 +171,6 @@ what kind of integer value the user supplied,
       else do
           io @println "Positive".
       end
-
-
 Let
 %%%
 
@@ -215,7 +186,7 @@ Here, the variable ``x`` will match the value stored in ``val``.  However, becau
 can write something like this,
 ::
   load system math.
-  let x:%[(k:%integer) if math @mod(k,2)==0]% = val.
+  let x: %[ (k:%integer) if math @mod (k,2) == 0 ]% = val.
 
 where ``x`` will only match the value of ``val`` if that value is an even integer value.  The fact that the left side of the ``=`` is a pattern allows
 us to write things like this,
@@ -229,6 +200,30 @@ on literals is convenient for statements like these,
 
 This ``let`` statement is only successful for values of ``p`` which are pairs where the first component of the pair is the value ``1``.
 
+Load
+%%%%
+
+Syntax: ``LOAD SYSTEM? (STRING | ID) (AS ID)? '.'?``
+
+The ``load`` statement allows you to load Asteroid modules either by filename or by module name.
+The ``system`` flag tells the interpreter only to search in the system modules for the desired
+module.  Probably the most often loaded module is the system IO module,
+::
+      load system io.
+      io @println "Hello World!".
+
+The ``as`` modifier allows you to rename a module in the current context in order to avoid name clashes.
+Consider for example that you had loaded your own IO module but also would like to load the
+system IO module.  In order to avoid a name clash you can use the ``as`` modifier to rename one
+of the modules,
+::
+      load io. -- load my IO module
+      load system io as systemio. -- load the system IO module and rename it to systemio
+      io @output "Foobar".
+      systemio @println "Hello World!".
+When loading a module with an explicit filename the basename of the filename becomes the module name.
+The ``ASTEROIDPATH`` environment variable allows you to specify additional directories the ``load`` command
+will search for modules.  The contents of ``ASTEROIDPATH`` is a colon separated list of directories.
 
 Loop
 %%%%
@@ -238,6 +233,23 @@ Syntax: ``LOOP DO? stmt_list END``
 The ``loop`` statement executes the statements in the loop body indefinitely
 unless a ``break`` statement is encountered.
 
+Match
+%%%%%
+
+Syntax: ``MATCH expression (WITH pattern DO stmt_list)* END``
+
+The ``match`` statement matches a value given by expression against a list of patterns
+in the ``with`` clauses.  If a pattern matches the associated statements will be executed,
+::
+      match (1,2)
+         with (x,y) if x > y do
+            let x = "GT".
+         with (x,y) if x < y do
+            let x = "LT".
+         with _ do
+            throw Error("not a valid tuple").
+      end
+      assert(x == "LT").
 Repeat-Until
 %%%%%%%%%%%%
 
@@ -257,8 +269,6 @@ of a list,
          let [element|l] = l.
          io @println element.
       until l is [].
-
-
 Return
 %%%%%%
 
@@ -283,9 +293,8 @@ are accessed using the access operator ``@``. Here is a simple example,
       end
 
       let obj = A(1,2).       -- call default constructor
-      assert( obj @a == 1 ).  -- access first data member
-      assert( obj @b == 2 ).  -- access second data member
-
+      assert( obj@a == 1 ).  -- access first data member
+      assert( obj@b == 2 ).  -- access second data member
 We can use custom constructors to enforce that only certain types of values
 can be copied into an object,
 ::
@@ -294,21 +303,19 @@ can be copied into an object,
           data name.
           data age.
           function __init__ with (name:%string,age:%integer) do -- constructor
-             let this @name = name.
-             let this @age = age.
+             let this@name = name.
+             let this@age = age.
           end
           function __str__ with none do
-            return this@name+" is "+this@age+" years old".
+            return this @name+" is "+ tostring(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").
+      assert( betty@name == "Betty" ).
+      assert( betty@age == 21 ).
 
+      assert(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
@@ -341,7 +348,6 @@ by the associated handler,
       catch Exception("ArithmeticError", s) do
           io @println s.
       end
-
 For more details on exceptions please see the User Guide.
 
 Throw
@@ -368,14 +374,10 @@ Here is an example that prints out a sequence of integer values in reverse order
 
       let i = 10.
 
-      while i do
+      while i >= 0 do
          io @println i.
          let i = i-1.
       end
-
-The loop terminates once ``i`` becomes zero which is the equivalent to a Boolean
-value ``false``.
-
 Expressions
 ^^^^^^^^^^^
 
@@ -397,7 +399,7 @@ Asteroid provides the uniform substructure access operator ``@`` for all structu
 which includes lists, tuples, and objects. For example, accessing the first
 element of a list is accomplished by the expression,
 ::
-      [1,2,3] @0
+      [1,2,3]@0
 
 Similarly, given an object constructed from structure ``A``, member values
 are accessed by name via the ``@`` operator,
@@ -408,9 +410,7 @@ are accessed by name via the ``@`` operator,
       end
 
       let obj = A(1,2).
-      assert( obj @a == 1 ).  -- access member a
-
-
+      assert( obj@a == 1 ).  -- access member a
 Head-Tail Operator
 %%%%%%%%%%%%%%%%%%
 
@@ -450,16 +450,17 @@ apply such as instantiating appropriate variable bindings in the current scope.
 
 Example,
 ::
-      if v is (x,y) do
-         io @println "success".
-         assert(isdefined "x").
-         assert(isdefined "y").
-      else
-         io @println "not matched".
-         assert(not isdefined "x").
-         assert(not isdefined "y").
-      end
+   load system io.
 
+   if (1,2) is (x,y) do
+      io @println "success".
+      assert(isdefined "x").
+      assert(isdefined "y").
+   else
+      io @println "not matched".
+      assert(not isdefined "x").
+      assert(not isdefined "y").
+   end
 The In Predicate
 %%%%%%%%%%%%%%%%%%%%
 
@@ -473,26 +474,6 @@ 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
 %%%%%%%%%%%%%%%%%%%
@@ -573,19 +554,19 @@ Here the pair ``(1,2)`` is matched against the pattern stored in the variable ``
 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
+allows the user to selectively project variable bindings from patterns that have been
+constructed using the ``%[...]%`` scope operator.
 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.
+At the second  ``let`` statement we bind the ``x`` as ``a`` and ``y`` from the scope
+of the  pattern into our current scope.
 
 Type Patterns
 %%%%%%%%%%%%%
@@ -600,14 +581,12 @@ Example,
 ::
       let true = 1 is %integer.
 
-Named Patterns
-%%%%%%%%%%%%%%
+Conditional Patterns (1)
+%%%%%%%%%%%%%%%%%%%%%%%%
 
-Syntax: ``name_exp ':' pattern``
+Syntax: ``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 either a variable,
-object member variable, or list location.
+These patterns allow you to express constraints on exp based on the pattern.
 
 Example,
 ::
@@ -616,17 +595,17 @@ 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,
+These patterns are a syntactic short hand for the equivalent conditional pattern,
 ::
-      name_exp if name_exp is pattern
+      exp if 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
-%%%%%%%%%%%%%%%%%%%%
+Conditional Patterns (2)
+%%%%%%%%%%%%%%%%%%%%%%%%
 
 Syntax: ``pattern IF cond_exp``
 
@@ -636,17 +615,17 @@ evaluates to true.
 Example,
 ::
       load system math.
-      let k if (math @mod(k,2) == 0) = val.
+      let k if (math@mod(k,2) == 0) = val.
 
 Here ``k`` only matches the value of ``val`` if that value is an even number.
 
-Pure Constraint Patterns
-%%%%%%%%%%%%%%%%%%%%%%%%
+Patterns with Scope
+%%%%%%%%%%%%%%%%%%%
 
 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
+A pattern with scope is a pattern that does not create any bindings
+in the current scope.  Any pattern can be turned into a scoped pattern
 by placing it between the ``%[`` and ``]%`` operators.
 
 Example,
@@ -654,13 +633,13 @@ Example,
       let pos_int = pattern %[(x:%integer) if x > 0]%
       let i:*pos_int = val.
 
-The first line defines a pure constraint pattern for the positive integers.
+The first line defines a scoped pattern for the positive integers.
 Notice that the pattern internally uses the variable ``x`` in order to evaluate
 the conditional pattern but because it has been declared as a pure constraint
 pattern this value binding is not exported to the current scope during pattern matching.
 On the second line we constrain the pattern ``i`` to only the positive integer values using
-the pure constraint pattern stored in ``p``.  This pattern match will only succeed if ``val``
-evaluates to a postive integer.
+the scoped pattern stored in ``p``.  This pattern match will only succeed if ``val``
+is a postive integer.
 
 Asteroid Grammar
 ^^^^^^^^^^^^^^^^
@@ -684,15 +663,15 @@ are written in quotes.
 
   stmt
     : '.' // NOOP
-    | LOAD SYSTEM? (STRING | ID) '.'?
+    | LOAD SYSTEM? (STRING | ID) (AS ID)? '.'?
     | GLOBAL id_list '.'?
-    | ASSERT exp '.'?
     | STRUCTURE ID WITH struct_stmts END
     | LET pattern '=' exp '.'?
     | LOOP DO? stmt_list END
     | FOR pattern IN exp DO stmt_list END
     | WHILE exp DO stmt_list END
     | REPEAT DO? stmt_list UNTIL exp '.'?
+    | MATCH exp (WITH pattern DO stmt_list)* END
     | IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE DO? stmt_list)? END
     | TRY DO? stmt_list (CATCH pattern DO stmt_list)+ END
     | THROW exp '.'?
@@ -724,6 +703,10 @@ are written in quotes.
   ////////////////////////////////////////////////////////////////////////////////////////
   // expressions/patterns
 
+
+
+
+
   exp
     : pattern
 
@@ -736,6 +719,10 @@ are written in quotes.
     : conditional ('|' exp)?
 
 
+
+
+
+
   conditional
     : compound (IF exp (ELSE exp)?)?
 
@@ -783,8 +770,6 @@ are written in quotes.
     | NOT call_or_index
     | MINUS call_or_index
     | PLUS call_or_index
-    | ESCAPE STRING
-    | EVAL primary
     | '(' tuple_stuff ')'
     | '[' list_stuff ']'
     | function_const
@@ -829,9 +814,26 @@ single integer value.
 Builtin Functions
 -----------------
 
+**assert** x
+      Throws an exception if x evaluates to false; otherwise it returns a none value.
+
+**eval** x:%string
+      Evaluate x as a piece of Asteroid code and return the computed value.  The following is a
+      simple example,
+      ::
+            let a = eval "1+1".
+            assert(a == 2).
+
+**escape** x:%string
+      Evaluate x as a piece of Python code and return the computed value.  For more details please
+      see the section on embedding Python code in this reference guide.
+
 **getid** x
       Returns a unique id of any Asteroid object as an integer.
 
+**gettype** x
+      Returns the type of x as a string.
+
 **hd** x:%list
       Returns the first element of a list. It is an error to apply this
       function to an empty list.
@@ -839,6 +841,16 @@ Builtin Functions
 **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.
+
+**islist** x
+      Returns true if x is a list otherwise it will return false.
+
+**isnone** x
+      Returns true if x is equal to the value none.
+
+**isscalar** x
+      Returns true if x is either an integer or a real value.
+
 **len** x
       Returns the length of x. The
       function can only be applied to lists, strings, tuples, or structures.
@@ -854,6 +866,23 @@ Builtin Functions
       Returns the rest of the list without the first element.  It is an
       error to apply this function to an empty list.
 
+**tobase** (x:%integer,base:%integer)
+      Represents the given integer x as a numeral string in different bases.
+
+**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.
+
+**toplevel** ()
+      Returns true if flow of control is in the "toplevel" module, that is, the module with which the
+      the interpreter was called; otherwise it will return false.
+
+**toreal** x
+      Returns the input as a real number.
+
+**tostring** x | (x,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.
 
 
 List and String Objects
@@ -971,7 +1000,7 @@ 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.
+      Returns an integer index of the item in the string or -1 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.
@@ -1144,8 +1173,8 @@ An example:
     load system io.
     load system math.
 
-    let x = math @sin( math @pi / 2 ).
-    io @println("The sine of pi / 2 is " + x + ".").
+    let x = math @sin( math @pi / 2.0 ).
+    io @println("The sine of pi / 2 is " + tostring x + ".").
 Constants
 %%%%%%%%%
 
@@ -1155,6 +1184,8 @@ math **@pi**
 math **@e**
       The mathematical constant e = 2.718281…, to available precision.
 
+math **@tau**
+      The mathematical constant τ = 6.283185…, to available precision.
 
 Power and logarithmic functions
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1162,31 +1193,66 @@ 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 **@expm1** x
+      Returns e raised to the power x minus 1. This function maintains a higher level of precision then the standard operation.
+
+math **@isqrt** x:%real
+      Returns the floor of the square root of x as a integer.
+
+math **@ldexp** (x,i)
+      Returns x * (2^i).
+
 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 **@log1p** x
+      Returns the natural logarithm of 1 + x.
+
+math **@log2** x
+      Returns the base 2 logarithm of x.
+
+math **@log10** x
+      Returns the base 10 logarithm of x.
+
 math **@pow** (b, p:%integer)
-      Return b raised to the power p.  The return type depends on the type
+      Returns 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.
-
+      Returns 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.
+      Returns 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 **@comb** (n:%integer,k:%integer)
+      Returns the numbers of ways to choose k items from n total items without repetition and without order. This is equal to n! / k!(n - k)!.
+
+math **@copysign** (x,y)
+      Returns a real with the absolute value of x and the sign of y.
+
+math **@dist** (x,y)
+      Return the Euclidean distance as a float between two points x and y, each given as a tuple or list of coordinates.
+
+math **@factorial** (n:%integer)
+      Returns the factorial of the integer n.
+
 math **@floor** x:%real
       Returns the floor of x: the largest integer less than or equal to x.
 
+math **@fmod** (v,d)
+      Implements the modulus operation as defined by the platform C library. This is equal to v - n*d for some integer n such that the result has the same sign as v and magnitude less than abs(d).
+
+math **@fsum** x:%list | x:%tuple
+      Calculate the sum of all the elements of a list or tuple. This function carries a higher floating point precison level than the standard sum() function by tracking multiple intermediate partial sums.
+
 math **@gcd** (a:%integer, b:%integer)
       Returns the greatest common denominator that both integers share.
 
@@ -1195,9 +1261,30 @@ math **@isclose** (a:%real, b:%real) | (a:%real, b:%real, t:%real)
       Default tolerance is 1e-09.  An alternative tolerance can be specified with
       the t argument.
 
+math **@lcm** (a:%integer,b:%integer)
+      Returns the least common multiple of the integers a and b.
+
 math **@mod** (v,d)
       Implements the modulus operation. Returns the remainder of the quotient v/d.
 
+math **@perm** (n:%integer, k:%integer)
+      Returns the numbers of ways to choose k items from n total items without repetition and with order. This is equal to n! / (n - k)!.
+
+math **@prod** x:%list | x:%tuple
+      Calculate and return the product of all the elements of a list or tuple x.
+
+math **@remainder** (x,y)
+      Returns the IEEE 754-style remainder of x with respect to y.
+
+math **@round** x:%real
+      Returns x rounded to the nearest integer. If two integers are equally
+      close, x is rounded to the nearest even integer.
+
+math **@sum** x:%list | x:%tuple
+      Calculate and return the sum of all the elements of a list or tuple x.
+
+math **@trunc** x:%real
+      Returns x with its fractional component set to 0.
 
 Trigonometric functions
 %%%%%%%%%%%%%%%%%%%%%%%
@@ -1211,9 +1298,15 @@ math **@asin** x
 math **@atan** x
       Returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
 
+math **@atan2** (x,y)
+      Returns the arc tangent of y / x in radians. The result is between -pi and pi.
+
 math **@cos** x
       Returns the cosine of x radians.
 
+math **@hypot** (x,y)
+      Returns the Euclidean norm as a real of x and y. This is equivalent to sqrt(x^2 + y^2).
+
 math **@sin** x
       Returns the sine of x radians.
 
@@ -1250,6 +1343,20 @@ math **@degrees** x
 math **@radians** x
       Converts angle x from degrees to radians.
 
+Special functions
+%%%%%%%%%%%%%%%%%
+
+math **@erf** x
+      Returns the error function (also called the Gauss error function) at x.
+
+math **@erfc** x
+      Returns the complement of the error function at x. The is defined as 1 - erf(x)
+
+math **@gamma** x
+      Returns the Gamma function at x.
+
+math **@lgamma** x
+      Returns the natural logarithm of the absolute value of the Gamma function at x.
 
 os
 ^^
@@ -1302,8 +1409,8 @@ 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
+      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,
@@ -1394,6 +1501,109 @@ os **@syscmd** cmd:%string
 
 
 
+patterns
+^^^^^^^^
+
+The patterns module implements common patterns.
+An example:
+::
+   load system patterns.
+
+   let evens = [].
+   for num in 1 to 10 do
+      if num is *patterns@even do
+         let evens = evens@append(num).
+      end
+   end
+   assert(evens is [2,4,6,8,10]).
+If a pattern only applies to a certain datatype then a constraint expression of the form ``:%<datatype>`` appears
+right after the pattern in the documentation.  If the pattern applies to multiple datatypes then the
+different datatypes are separated by or-bars, e.g. ``:%<datatype1>|%<datatype2>``.
+
+Common number sets
+%%%%%%%%%%%%%%%%%%
+
+patterns **@digit** \: %integer
+      Matches single digit integers.
+
+patterns **@even** \: %integer
+      Matches integers which are even numbers.
+
+patterns **@nat** \: %integer
+      Matches integers which are natural numbers.
+
+patterns **@negative** \: %integer | %real
+      Matches negative reals and integers.
+
+patterns **@neg_int** \: %integer
+      Matches negative integers.
+
+patterns **@neg_int** \: %integer
+      Matches negative integers.
+
+patterns **@odd** \: %integer
+      Matches integers which are odd numbers.
+
+patterns **@positive** \: %integer | %real
+      Matches positive reals and integers.
+
+patterns **@pos_int** \: %integer
+      Matches positive integers.
+
+patterns **@pos_real** \: %real
+      Matches postive reals.
+
+patterns **@prime** \: %integer
+      Matches prime numbers.
+
+patterns **@zero** \: %integer | %real
+      Matches the value 0, either as an integer or a real.
+
+Containers
+%%%%%%%%%%
+
+patterns **@bool_list** \: %list
+      Matches lists which only contain booleans.
+
+patterns **@func_list** \: %list
+      Matches lists which only contain functions.
+
+patterns **@int_list** \: %list
+      Matches lists which only contain integers.
+
+patterns **@list_list** \: %list
+      Matches lists which only contain lists.
+
+patterns **@real_list** \: %list
+      Matches lists which only contain reals.
+
+patterns **@str_list** \: %list
+      Matches lists which only contain strings.
+
+patterns **@tuple_list** \: %list
+      Matches lists which only contain tuples.
+
+Strings
+%%%%%%%
+
+patterns **@alphabetic** \: %string
+      Matches strings which only contain alphabetic characters.
+
+patterns **@alphanumeric** \: %string
+      Matches strings which only contain alphanumeric characters.
+
+patterns **@lowercase** \: %string
+      Matches strings which only contain lowercase alphabetic characters.
+
+patterns **@numeric** \: %string
+      Matches strings which only contain numeric characters.
+
+patterns **@uppercase** \: %string
+      Matches strings which only contain uppercase alphabetic characters.
+
+
+
+
 pick
 ^^^^
 
@@ -1404,7 +1614,7 @@ An example:
    load system io.
    load system pick.
 
-   let po = pick @pick([1 to 10]).
+   let po = pick @pick [1 to 10].
    let objects = po @pickitems 3.
    io @println objects.
 pick **@pick** l:%list
@@ -1496,7 +1706,7 @@ A simple use case:
 
    let s = stream @stream [1 to 10].
    while not s @eof() do
-      io @print (s @get() + " ").
+      io @print (tostring (s @get()) + " ").
    end
    io @println "".
 which outputs::
@@ -1528,85 +1738,7 @@ __STREAM__ **@rewind** ()
       Resets the stream pointer to the first element of the stream.
 
 
-type
-^^^^
-
-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.
-    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.
-
-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  **@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,
-::
-   load system type.
 
-   let i = 1.
-   assert(type @gettype(i) == "integer").
 util
 ^^^^
 
@@ -1766,7 +1898,7 @@ The program prints out,
 Embedding Python into an Asteroid Program
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Using Asteroid's ``escape`` expression allows us to embed arbitray Python
+Using Asteroid's ``escape`` function allows us to embed arbitray Python
 code into an Asteroid program,
 ::
       -- Printing hello once from each environment
@@ -1785,7 +1917,7 @@ Please note that the format of the Python code in the escaped string should foll
 same guidelines as the Python code embedded in strings handed to the Python `exec
 function <https://docs.python.org/3/library/functions.html#exec>`_.
 
-Not only does the ``escape`` expression give you access to the Python environment but
+Not only does the ``escape`` function give you access to the Python environment but
 it also gives you access to the current Asteroid interpreter state including its
 symbol table.  That means we can access any variable defined in the Asteroid
 environment from Python,
@@ -1808,7 +1940,7 @@ is the actual value stored.  In this case our program prints out,
 
 That is the type of the value is a string and the value is the actual string ``Hello World!``.
 
-Since ``escape`` represents an expression we can also return values from the
+Since ``escape`` is a function we can also return values from the
 Python code using a special ``__retval__`` variable.  The only trick is that
 we have to remember that values in Asteroid are pairs consisting of type information
 and values.  Here is a very simple program that exercises that part of the Python API,
diff --git a/docs/Reference Guide.txt b/docs/Reference Guide.txt
index 05994053..f687132e 100644
--- a/docs/Reference Guide.txt
+++ b/docs/Reference Guide.txt
@@ -1,12 +1,12 @@
 ..
       /******************************************************************
       This is the source file from which the reference guide is
-      generated.  We use cpp to insert live code snippets into the
+      generated.  We use pcpp 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
+      following command in the directory of
       this doc:
 
-      bash generate_docs
+      python generate_docs.py
 
       ******************************************************************/
 #include "header.txt"
@@ -29,24 +29,6 @@ represents ``end``.
 Statements
 ^^^^^^^^^^
 
-Assert
-%%%%%%
-
-Syntax: ``ASSERT exp '.'?``
-
-If the expression of the assert statement evaluates to a
-value equivalent to the Boolean value
-``false`` an exception is thrown otherwise the statement is ignored.
-
-For example, the statement,
-::
-      assert (1+1 == 3).
-
-will generate a runtime error but the statement,
-::
-      assert (1+1 == 2).
-
-will be ignored once the expression has been evaluated.
 
 
 Break
@@ -60,16 +42,7 @@ outside of a looping structure will lead to a runtime error.
 
 As an example we break out of the indefinite loop below when ``i`` is equal to 10,
 ::
-      let i = 0.
-
-      loop
-         let i = i+1.
-         if i==10 do
-            break.
-         end
-      end
-
-      assert (i==10).
+#include "../asteroid/test-suites/ref-programs/prgm-001.ast"
 
 Expressions at the Statement Level
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -81,10 +54,7 @@ evaluated in a function body is considered the return value of the function.
 
 An example,
 ::
-      function inc
-         with i do
-            i+1.
-         end
+#include "../asteroid/test-suites/ref-programs/prgm-002.ast"
 
 Notice that because the expression ``i+1`` is the last statement evaluated in the
 function body its value becomes the return value of the function.
@@ -101,15 +71,7 @@ The loop body is executed for each successful match.
 In the following program the body of the loop is executed exactly once when
 the pattern matches the tuple ``(1,"chicken")``,
 ::
-      let tuple_list = [
-              (0,"duck"),
-              (1,"chicken"),
-              (2,"turkey")
-              ].
-
-      for (1,bird) in tuple_list do
-         assert(bird is "chicken").
-      end
+#include "../asteroid/test-suites/ref-programs/prgm-003.ast"
 
 
 Function-Definition
@@ -127,12 +89,7 @@ Patterns are tried in the order they appear in the function definition.
 
 The following is a definition of the ``sign`` function,
 ::
-      function sign
-         with x if x >= 0 do
-            return 1.
-         with x if x < 0 do
-            return -1.
-      end
+#include "../asteroid/test-suites/ref-programs/prgm-004.ast"
 
 Here the first function body returns ``1`` if the actual argument is greater or equal to zero.
 The second function body return ``-1`` if the actual argument is less than zero.
@@ -148,17 +105,7 @@ from within functions.
 
 Consider the following code snippet,
 ::
-      let x = 0.
-
-      function foo
-         with none do
-            global x.
-            let x = 1.
-      end
-
-      assert(x==0).
-      foo().
-      assert(x==1).
+#include "../asteroid/test-suites/ref-programs/prgm-005.ast"
 
 The ``global`` statement within the function ``foo`` indicates that the ``let`` statement
 on the following line should assign a value to the global variable ``x``.
@@ -181,21 +128,7 @@ flow of control is transferred to the statements following the if-statement.
 As an example consider the following ``if`` statement that determines
 what kind of integer value the user supplied,
 ::
-      load system io.
-      load system type.
-
-      let x = type @tointeger (io @input "Please enter an integer: ").
-
-      if x < 0 do
-          io @println "Negative".
-      elif x == 0 do
-          io @println "Zero".
-      elif x == 1 do
-          io @println "One".
-      else do
-          io @println "Positive".
-      end
-
+#include "../asteroid/test-suites/ref-programs/prgm-006.ast"
 
 Let
 %%%
@@ -212,7 +145,7 @@ Here, the variable ``x`` will match the value stored in ``val``.  However, becau
 can write something like this,
 ::
   load system math.
-  let x:%[(k:%integer) if math @mod(k,2)==0]% = val.
+  let x: %[ (k:%integer) if math @mod (k,2) == 0 ]% = val.
 
 where ``x`` will only match the value of ``val`` if that value is an even integer value.  The fact that the left side of the ``=`` is a pattern allows
 us to write things like this,
@@ -226,6 +159,28 @@ on literals is convenient for statements like these,
 
 This ``let`` statement is only successful for values of ``p`` which are pairs where the first component of the pair is the value ``1``.
 
+Load
+%%%%
+
+Syntax: ``LOAD SYSTEM? (STRING | ID) (AS ID)? '.'?``
+
+The ``load`` statement allows you to load Asteroid modules either by filename or by module name.
+The ``system`` flag tells the interpreter only to search in the system modules for the desired 
+module.  Probably the most often loaded module is the system IO module,
+::
+      load system io.
+      io @println "Hello World!".
+
+The ``as`` modifier allows you to rename a module in the current context in order to avoid name clashes.
+Consider for example that you had loaded your own IO module but also would like to load the
+system IO module.  In order to avoid a name clash you can use the ``as`` modifier to rename one 
+of the modules,
+::
+#include "../asteroid/test-suites/ref-programs/prgm-007.ast"
+
+When loading a module with an explicit filename the basename of the filename becomes the module name. 
+The ``ASTEROIDPATH`` environment variable allows you to specify additional directories the ``load`` command 
+will search for modules.  The contents of ``ASTEROIDPATH`` is a colon separated list of directories.
 
 Loop
 %%%%
@@ -235,6 +190,17 @@ Syntax: ``LOOP DO? stmt_list END``
 The ``loop`` statement executes the statements in the loop body indefinitely
 unless a ``break`` statement is encountered.
 
+Match
+%%%%%
+
+Syntax: ``MATCH expression (WITH pattern DO stmt_list)* END``
+
+The ``match`` statement matches a value given by expression against a list of patterns
+in the ``with`` clauses.  If a pattern matches the associated statements will be executed,
+::
+#include "../asteroid/test-suites/ref-programs/prgm-008.ast"
+
+
 Repeat-Until
 %%%%%%%%%%%%
 
@@ -246,14 +212,7 @@ expression evaluates to the equivalent of a Boolean ``true`` value.
 Here is an example of a program that prints out the elements
 of a list,
 ::
-      load system io.
-
-      let l = ["bmw", "volkswagen", "mercedes"].
-
-      repeat
-         let [element|l] = l.
-         io @println element.
-      until l is [].
+#include "../asteroid/test-suites/ref-programs/prgm-009.ast"
 
 
 Return
@@ -273,38 +232,12 @@ Unless a member function was declared as a constructor (an ``__init__`` function
 instantiated using a default constructor. The 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.  We often refer to instantiated structures as objects.  Member values of objects
 are accessed using the access operator ``@``. Here is a simple example,
 ::
-      -- define a structure of type A
-      structure A with
-          data a.
-          data b.
-      end
-
-      let obj = A(1,2).       -- call default constructor
-      assert( obj @a == 1 ).  -- access first data member
-      assert( obj @b == 2 ).  -- access second data member
+#include "../asteroid/test-suites/ref-programs/prgm-010.ast"
 
 We can use custom constructors to enforce that only certain types of values
 can be copied into an object,
 ::
-      -- 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").
+#include "../asteroid/test-suites/ref-programs/prgm-011.ast"
 
 Note that object identity is expressed using the ``this`` keyword.
 Here we also supplied an instantiation of the ``__str__`` function that allows
@@ -331,13 +264,7 @@ in the ``try`` part generates a division-by-zero exception.  The
 exception object is pattern-matched in the ``catch`` clause and processed
 by the associated handler,
 ::
-      load system io.
-
-      try
-          let x = 1/0.
-      catch Exception("ArithmeticError", s) do
-          io @println s.
-      end
+#include "../asteroid/test-suites/ref-programs/prgm-012.ast"
 
 For more details on exceptions please see the User Guide.
 
@@ -361,17 +288,8 @@ after each loop iteration.
 
 Here is an example that prints out a sequence of integer values in reverse order,
 ::
-      load system io.
-
-      let i = 10.
+#include "../asteroid/test-suites/ref-programs/prgm-013.ast"
 
-      while i do
-         io @println i.
-         let i = i-1.
-      end
-
-The loop terminates once ``i`` becomes zero which is the equivalent to a Boolean
-value ``false``.
 
 Expressions
 ^^^^^^^^^^^
@@ -394,18 +312,12 @@ Asteroid provides the uniform substructure access operator ``@`` for all structu
 which includes lists, tuples, and objects. For example, accessing the first
 element of a list is accomplished by the expression,
 ::
-      [1,2,3] @0
+      [1,2,3]@0
 
 Similarly, given an object constructed from structure ``A``, member values
 are accessed by name via the ``@`` operator,
 ::
-      structure A with
-         data a.
-         data b.
-      end
-
-      let obj = A(1,2).
-      assert( obj @a == 1 ).  -- access member a
+#include "../asteroid/test-suites/ref-programs/prgm-014.ast"
 
 
 Head-Tail Operator
@@ -447,15 +359,7 @@ apply such as instantiating appropriate variable bindings in the current scope.
 
 Example,
 ::
-      if v is (x,y) do
-         io @println "success".
-         assert(isdefined "x").
-         assert(isdefined "y").
-      else
-         io @println "not matched".
-         assert(not isdefined "x").
-         assert(not isdefined "y").
-      end
+#include "../asteroid/test-suites/ref-programs/prgm-015.ast"
 
 The In Predicate
 %%%%%%%%%%%%%%%%%%%%
@@ -470,26 +374,6 @@ 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
 %%%%%%%%%%%%%%%%%%%
@@ -570,19 +454,19 @@ Here the pair ``(1,2)`` is matched against the pattern stored in the variable ``
 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 
+allows the user to selectively project variable bindings from patterns that have been 
+constructed using the ``%[...]%`` scope operator. 
 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.
+At the second  ``let`` statement we bind the ``x`` as ``a`` and ``y`` from the scope 
+of the  pattern into our current scope.
 
 Type Patterns
 %%%%%%%%%%%%%
@@ -597,14 +481,12 @@ Example,
 ::
       let true = 1 is %integer.
 
-Named Patterns
-%%%%%%%%%%%%%%
+Conditional Patterns (1)
+%%%%%%%%%%%%%%%%%%%%%%%%
 
-Syntax: ``name_exp ':' pattern``
+Syntax: ``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 either a variable,
-object member variable, or list location.
+These patterns allow you to express constraints on exp based on the pattern.
 
 Example,
 ::
@@ -613,17 +495,17 @@ 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,
+These patterns are a syntactic short hand for the equivalent conditional pattern,
 ::
-      name_exp if name_exp is pattern
+      exp if 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
-%%%%%%%%%%%%%%%%%%%%
+Conditional Patterns (2)
+%%%%%%%%%%%%%%%%%%%%%%%%
 
 Syntax: ``pattern IF cond_exp``
 
@@ -633,17 +515,17 @@ evaluates to true.
 Example,
 ::
       load system math.
-      let k if (math @mod(k,2) == 0) = val.
+      let k if (math@mod(k,2) == 0) = val.
 
 Here ``k`` only matches the value of ``val`` if that value is an even number.
 
-Pure Constraint Patterns
-%%%%%%%%%%%%%%%%%%%%%%%%
+Patterns with Scope
+%%%%%%%%%%%%%%%%%%%
 
 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
+A pattern with scope is a pattern that does not create any bindings
+in the current scope.  Any pattern can be turned into a scoped pattern
 by placing it between the ``%[`` and ``]%`` operators.
 
 Example,
@@ -651,13 +533,13 @@ Example,
       let pos_int = pattern %[(x:%integer) if x > 0]%
       let i:*pos_int = val.
 
-The first line defines a pure constraint pattern for the positive integers.
+The first line defines a scoped pattern for the positive integers.
 Notice that the pattern internally uses the variable ``x`` in order to evaluate
 the conditional pattern but because it has been declared as a pure constraint
 pattern this value binding is not exported to the current scope during pattern matching.
 On the second line we constrain the pattern ``i`` to only the positive integer values using
-the pure constraint pattern stored in ``p``.  This pattern match will only succeed if ``val``
-evaluates to a postive integer.
+the scoped pattern stored in ``p``.  This pattern match will only succeed if ``val``
+is a postive integer.
 
 Asteroid Grammar
 ^^^^^^^^^^^^^^^^
@@ -670,7 +552,7 @@ 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.
 ::
-#include "/tmp/grammar.tmp"
+#include "../asteroid/grammar.txt"
 
 Notes on Function Argument Notation
 -----------------------------------
@@ -689,9 +571,26 @@ single integer value.
 Builtin Functions
 -----------------
 
+**assert** x
+      Throws an exception if x evaluates to false; otherwise it returns a none value.
+
+**eval** x:%string
+      Evaluate x as a piece of Asteroid code and return the computed value.  The following is a 
+      simple example,
+      ::
+            let a = eval "1+1".
+            assert(a == 2).
+
+**escape** x:%string
+      Evaluate x as a piece of Python code and return the computed value.  For more details please
+      see the section on embedding Python code in this reference guide.
+
 **getid** x
       Returns a unique id of any Asteroid object as an integer.
 
+**gettype** x
+      Returns the type of x as a string.
+
 **hd** x:%list
       Returns the first element of a list. It is an error to apply this 
       function to an empty list.
@@ -699,6 +598,16 @@ Builtin Functions
 **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.
+
+**islist** x 
+      Returns true if x is a list otherwise it will return false.
+
+**isnone** x
+      Returns true if x is equal to the value none.
+
+**isscalar** x
+      Returns true if x is either an integer or a real value.
+
 **len** x
       Returns the length of x. The
       function can only be applied to lists, strings, tuples, or structures.
@@ -714,6 +623,23 @@ Builtin Functions
       Returns the rest of the list without the first element.  It is an 
       error to apply this function to an empty list.
 
+**tobase** (x:%integer,base:%integer)
+      Represents the given integer x as a numeral string in different bases.
+
+**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.
+
+**toplevel** ()
+      Returns true if flow of control is in the "toplevel" module, that is, the module with which the 
+      the interpreter was called; otherwise it will return false.
+
+**toreal** x
+      Returns the input as a real number.
+
+**tostring** x | (x,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. 
 
 
 List and String Objects
@@ -831,7 +757,7 @@ 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.  
+      Returns an integer index of the item in the string or -1 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.  
@@ -1012,6 +938,8 @@ math **@pi**
 math **@e**
       The mathematical constant e = 2.718281…, to available precision.
 
+math **@tau**
+      The mathematical constant τ = 6.283185…, to available precision.
 
 Power and logarithmic functions
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1019,31 +947,66 @@ 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 **@expm1** x
+      Returns e raised to the power x minus 1. This function maintains a higher level of precision then the standard operation.
+
+math **@isqrt** x:%real
+      Returns the floor of the square root of x as a integer.
+
+math **@ldexp** (x,i)
+      Returns x * (2^i).
+
 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 **@log1p** x
+      Returns the natural logarithm of 1 + x.
+
+math **@log2** x
+      Returns the base 2 logarithm of x.
+
+math **@log10** x
+      Returns the base 10 logarithm of x.
+
 math **@pow** (b, p:%integer)
-      Return b raised to the power p.  The return type depends on the type
+      Returns 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.
-
+      Returns 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.
+      Returns 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 **@comb** (n:%integer,k:%integer)
+      Returns the numbers of ways to choose k items from n total items without repetition and without order. This is equal to n! / k!(n - k)!.
+
+math **@copysign** (x,y)
+      Returns a real with the absolute value of x and the sign of y.
+
+math **@dist** (x,y)
+      Return the Euclidean distance as a float between two points x and y, each given as a tuple or list of coordinates.
+
+math **@factorial** (n:%integer)
+      Returns the factorial of the integer n.
+
 math **@floor** x:%real
       Returns the floor of x: the largest integer less than or equal to x.
 
+math **@fmod** (v,d)
+      Implements the modulus operation as defined by the platform C library. This is equal to v - n*d for some integer n such that the result has the same sign as v and magnitude less than abs(d).
+
+math **@fsum** x:%list | x:%tuple
+      Calculate the sum of all the elements of a list or tuple. This function carries a higher floating point precison level than the standard sum() function by tracking multiple intermediate partial sums.
+
 math **@gcd** (a:%integer, b:%integer)
       Returns the greatest common denominator that both integers share.
 
@@ -1052,9 +1015,30 @@ math **@isclose** (a:%real, b:%real) | (a:%real, b:%real, t:%real)
       Default tolerance is 1e-09.  An alternative tolerance can be specified with 
       the t argument.
 
+math **@lcm** (a:%integer,b:%integer)
+      Returns the least common multiple of the integers a and b.
+
 math **@mod** (v,d)
       Implements the modulus operation. Returns the remainder of the quotient v/d.
 
+math **@perm** (n:%integer, k:%integer)
+      Returns the numbers of ways to choose k items from n total items without repetition and with order. This is equal to n! / (n - k)!.
+
+math **@prod** x:%list | x:%tuple
+      Calculate and return the product of all the elements of a list or tuple x.
+
+math **@remainder** (x,y)
+      Returns the IEEE 754-style remainder of x with respect to y.
+
+math **@round** x:%real
+      Returns x rounded to the nearest integer. If two integers are equally
+      close, x is rounded to the nearest even integer.
+
+math **@sum** x:%list | x:%tuple
+      Calculate and return the sum of all the elements of a list or tuple x.
+
+math **@trunc** x:%real
+      Returns x with its fractional component set to 0.
 
 Trigonometric functions
 %%%%%%%%%%%%%%%%%%%%%%%
@@ -1068,9 +1052,15 @@ math **@asin** x
 math **@atan** x
       Returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
 
+math **@atan2** (x,y)
+      Returns the arc tangent of y / x in radians. The result is between -pi and pi.
+
 math **@cos** x
       Returns the cosine of x radians.
 
+math **@hypot** (x,y)
+      Returns the Euclidean norm as a real of x and y. This is equivalent to sqrt(x^2 + y^2).
+
 math **@sin** x
       Returns the sine of x radians.
 
@@ -1107,6 +1097,20 @@ math **@degrees** x
 math **@radians** x
       Converts angle x from degrees to radians.
 
+Special functions
+%%%%%%%%%%%%%%%%%
+
+math **@erf** x
+      Returns the error function (also called the Gauss error function) at x.
+
+math **@erfc** x
+      Returns the complement of the error function at x. The is defined as 1 - erf(x)
+
+math **@gamma** x
+      Returns the Gamma function at x.
+
+math **@lgamma** x
+      Returns the natural logarithm of the absolute value of the Gamma function at x.
 
 os
 ^^
@@ -1159,8 +1163,8 @@ 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 
+      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, 
@@ -1251,6 +1255,102 @@ os **@syscmd** cmd:%string
 
 
 
+patterns
+^^^^^^^^
+
+The patterns module implements common patterns.
+An example:
+::
+#include "../asteroid/test-suites/ref-programs/patterns.ast"
+
+If a pattern only applies to a certain datatype then a constraint expression of the form ``:%<datatype>`` appears 
+right after the pattern in the documentation.  If the pattern applies to multiple datatypes then the 
+different datatypes are separated by or-bars, e.g. ``:%<datatype1>|%<datatype2>``.
+
+Common number sets
+%%%%%%%%%%%%%%%%%%
+
+patterns **@digit** \: %integer
+      Matches single digit integers.
+
+patterns **@even** \: %integer
+      Matches integers which are even numbers.
+
+patterns **@nat** \: %integer
+      Matches integers which are natural numbers.
+
+patterns **@negative** \: %integer | %real
+      Matches negative reals and integers.
+
+patterns **@neg_int** \: %integer
+      Matches negative integers.
+
+patterns **@neg_int** \: %integer
+      Matches negative integers.
+
+patterns **@odd** \: %integer
+      Matches integers which are odd numbers.
+
+patterns **@positive** \: %integer | %real
+      Matches positive reals and integers.
+
+patterns **@pos_int** \: %integer
+      Matches positive integers.
+
+patterns **@pos_real** \: %real
+      Matches postive reals.
+
+patterns **@prime** \: %integer
+      Matches prime numbers.
+
+patterns **@zero** \: %integer | %real
+      Matches the value 0, either as an integer or a real.
+
+Containers
+%%%%%%%%%%
+
+patterns **@bool_list** \: %list
+      Matches lists which only contain booleans.
+
+patterns **@func_list** \: %list
+      Matches lists which only contain functions.
+
+patterns **@int_list** \: %list
+      Matches lists which only contain integers.
+
+patterns **@list_list** \: %list
+      Matches lists which only contain lists.
+
+patterns **@real_list** \: %list
+      Matches lists which only contain reals.
+
+patterns **@str_list** \: %list
+      Matches lists which only contain strings.
+
+patterns **@tuple_list** \: %list
+      Matches lists which only contain tuples.
+
+Strings
+%%%%%%%
+
+patterns **@alphabetic** \: %string
+      Matches strings which only contain alphabetic characters.
+
+patterns **@alphanumeric** \: %string
+      Matches strings which only contain alphanumeric characters.
+
+patterns **@lowercase** \: %string
+      Matches strings which only contain lowercase alphabetic characters.
+
+patterns **@numeric** \: %string
+      Matches strings which only contain numeric characters.
+
+patterns **@uppercase** \: %string
+      Matches strings which only contain uppercase alphabetic characters.
+
+
+
+
 pick
 ^^^^
 
@@ -1373,64 +1473,6 @@ __STREAM__ **@rewind** ()
       Resets the stream pointer to the first element of the stream.
 
 
-type
-^^^^
-
-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"
-
-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.
-
-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  **@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,
-::
-#include "../asteroid/test-suites/ref-programs/type.ast"
 
 util
 ^^^^
@@ -1586,7 +1628,7 @@ The program prints out,
 Embedding Python into an Asteroid Program
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-Using Asteroid's ``escape`` expression allows us to embed arbitray Python
+Using Asteroid's ``escape`` function allows us to embed arbitray Python
 code into an Asteroid program,
 ::
       -- Printing hello once from each environment
@@ -1605,7 +1647,7 @@ Please note that the format of the Python code in the escaped string should foll
 same guidelines as the Python code embedded in strings handed to the Python `exec
 function <https://docs.python.org/3/library/functions.html#exec>`_.
 
-Not only does the ``escape`` expression give you access to the Python environment but
+Not only does the ``escape`` function give you access to the Python environment but
 it also gives you access to the current Asteroid interpreter state including its
 symbol table.  That means we can access any variable defined in the Asteroid
 environment from Python,
@@ -1628,7 +1670,7 @@ is the actual value stored.  In this case our program prints out,
 
 That is the type of the value is a string and the value is the actual string ``Hello World!``.
 
-Since ``escape`` represents an expression we can also return values from the
+Since ``escape`` is a function we can also return values from the
 Python code using a special ``__retval__`` variable.  The only trick is that
 we have to remember that values in Asteroid are pairs consisting of type information
 and values.  Here is a very simple program that exercises that part of the Python API,
diff --git a/docs/User Guide.rst b/docs/User Guide.rst
index 8921f5aa..65904b4b 100644
--- a/docs/User Guide.rst
+++ b/docs/User Guide.rst
@@ -1,11 +1,12 @@
 ..
     /******************************************************************
-    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 reference guide is
+    generated.  We use pcpp to insert live code snippets into the
+    document. In order to generate the reference guide run the
+    following command in the directory of
+    this doc:
 
-    bash generate_docs
+    python generate_docs.py
 
     ******************************************************************/
 ..
@@ -32,7 +33,7 @@ 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,
+that means the list ``[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.
@@ -43,20 +44,20 @@ that recursively computes the factorial of a positive integer and uses first-cla
 in order to ensure that the domain of the function is not violated,
 ::
     -- define first-class patterns
-    let POS_INT = pattern (x:%integer) if x > 0.
-    let NEG_INT = pattern (x:%integer) if x < 0.
+    let pos_int = pattern (x:%integer) if x > 0.
+    let neg_int = pattern (x:%integer) if x < 0.
 
     -- define our factorial function
     function fact
         with 0 do
             return 1
-        with n:*POS_INT do            -- use first pattern
+        with n:*pos_int do            -- use first pattern
             return n * fact (n-1).
-        with n:*NEG_INT do            -- use second pattern
+        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
+``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
 profound implications for software development in that pattern definition and usage
 points are now separate and patterns can be reused in different contexts.
@@ -69,29 +70,26 @@ with programming in Asteroid.
 The Basics
 ----------
 
-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,
+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 four primitive data types,
 
 * ``integer``, e.g. ``1024``
 * ``real``, e.g. ``1.75``
 * ``string``, e.g. ``"Hello, World!"``
 * ``boolean``, e.g. ``true``
 
-Asteroid arranges these primitive data types in a type hierarchy,
-
-``boolean`` < ``integer`` < ``real`` < ``string``
-
-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 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,)`` the 1-tuple versus ``(3)`` the parenthesized expression.
+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 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)``.
+Lists are mutable structures in that we can add or delete elements.  On the other hand, tuples are immutable objects;
+once created you cannot change them.
+Furthermore, 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
@@ -99,16 +97,11 @@ Here are some examples,
 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 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``
-
-That is, any list or tuple can be viewed as a string.  This is very convenient for printing lists and tuples,
+We can cast lists and tuples to strings for easy printing,
 ::
     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.
+    io @println ("this is my list: " + tostring [1,2,3]).
+Here the ``+`` operator acts like a string concantenation operator with the list ``[1,2,3]`` promoted to a string.
 
 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
@@ -119,22 +112,29 @@ 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.
 
 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).
+   assert (gettype(inc) == "function").
+Here is a small program demonstrating the ``pattern`` data type,
+::
+   -- define a first-class pattern
+   let p = pattern (x:%integer) if x>0.
+
+   -- check the type of the value stored in p
+   assert (gettype(p) == "pattern").
+Data types in Asteroid do not form type hierarchies as in C/C++ and Java, for example.
+Therefore, in mixed type arithmetic statements we have to explicitly convert data types as in,
+::
+   let x = 1.1 + toreal(1).
+Asteroid shares this view of data types with prgogramming languages like SML and Rust.
 
 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.
 
@@ -147,20 +147,14 @@ 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.
-
     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]``.
-
+    assert (b == [3,2,1]).
 We can achieve the same effect by giving a list of index values (a slice) to the ``@`` operator,
 ::
-    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]
-    io @println b.
+    assert (b == [3,2,1]).
 In Asteroid lists are considered objects with member functions that can manipulate list
 objects. We could rewrite the above example as,
 ::
@@ -186,12 +180,12 @@ an optional step specifier allowing you to generate integer values within that r
 
     -- build a list of odd values
     let a = [1 to 10 step 2].  -- list comprehension
-    io @println ("list: " + a).
+    io @println ("list: " + tostring a).
 
     -- reverse the list using a slice computed as comprehension
     let slice = [4 to 0 step -1]. -- list comprehension
     let b = a@slice.
-    io @println ("reversed list: " + b).
+    io @println ("reversed list: " + tostring b).
 The output is,
 ::
 
@@ -206,7 +200,7 @@ a list of alternating 1 and -1,
     load system math.
 
     let a = [1 to 10] @map (lambda with x do math @mod (x,2))
-                      @map (lambda with x do 1 if x else -1).
+                      @map (lambda with x do 1 if x==1 else -1).
 
     io @println a.
 where the output is,
@@ -219,7 +213,7 @@ where the output is,
 Tuples
 ^^^^^^
 
-As we saw earlier, the tuple is another fundamental, built-in data structure that can be found in Asteroid.
+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
@@ -233,7 +227,7 @@ Lists and tuples may be nested,
              ("g","h","i")].
     -- Access an element in the nested structure.
     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,
+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.
 
@@ -307,7 +301,7 @@ The following is a more involved example,
     let Person(name,age,gender) = people@1.
 
     -- print out the member values
-    io @println (name + " is " + age + " years old and is a " +  gender + ".").
+    io @println (name + " is " + tostring age + " years old and is a " +  gender + ".").
 The output is,
 ::
 
@@ -340,6 +334,7 @@ where we pattern match the pattern 1 on the left side to the value 1 on the righ
 
 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.
+This is often called "destructuring" of a 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).
@@ -354,7 +349,7 @@ the variables ``x`` and ``y`` where we expect our values to be,
     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.
+Matching the pattern against the value ``(1,2)`` stored in ``p`` first matches the pair structure against the pair value and then 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,
 ::
@@ -368,34 +363,40 @@ The following is an example involving structures and objects,
     let Person(n,a,p) = joe.              -- pattern match object
 
     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``.
+We first construct an object ``joe`` with the first ``let`` statement and then 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
 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
-the type pattern ``%integer``.
-
-Asteroid also
-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,
+This ``let`` statement succeeds because ``1`` is an integer value that can be pattern-matched against
+the type pattern ``%integer``.  Type pattern exist for all builtin data types, ``%real`` and ``%list``.
+If you introduce a user defined type via a structure, then Asteroid will create a type pattern for all objects
+of that data type.  Here is a simple example,
 ::
-    load system io.
+    structure Foo with
+        data a.
+        data b.
+    end
+
+    let %Foo = Foo(1,2).
+Notice the type pattern for the user defined type ``Foo`` in the ``let`` statement.
 
-    let t:(x,y) = (1,2).  -- using a named pattern on lhs
-    io @println t.
-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,
+Asteroid also supports conditional patterns.  Here is an example where we to make sure that the
+variable ``t`` on the left matches a pair of integer values,
 ::
-    (1,2)
+    let t if t is (%integer,%integer) = (1,2).
 
-Named patterns are a shorthand notation for conditional patterns; in this case,
+Of course, this ``let`` statement is going to be successful because the value on the right is indeed a
+pair of integers.  This kind of conditional pattern appears so often in Asteroid code that
+Asteroid has a shorthand notation for this,
 ::
-    let t if t is (x,y) = (1,2).
+    let t:(%integer,%integer) = (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
+Again, here the ``let`` statement is only successful if ``t`` matches a pair of integers.
+
+Shorthand conditional patterns often look
+like a variable declarations in other languages. In Asteroid, though, it is still just all
 about pattern matching.  Consider,
 ::
     load system io.
@@ -403,10 +404,9 @@ about pattern matching.  Consider,
 
     let x:%real = math @pi.
     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.141592653589793``.
+The left side of the ``let`` statement is a conditional pattern that matches any real value, and
+if that match is successful then the value is bound to the variable ``x``.
+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
@@ -459,14 +459,13 @@ The output is,
     the third bird is a chicken
 
 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)``.
+iterate while 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,
 ::
     load system io.
-    load system type.
 
-    let x = type @tointeger (io @input "Please enter an integer: ").
+    let x = tointeger (io @input "Please enter an integer: ").
 
     if x < 0 do
         let x = 0.
@@ -516,8 +515,8 @@ In Asteroid functions are multi-dispatch, that is,
 a single function can have multiple bodies each attached to a different pattern
 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,
+Asteroid where each ``with`` clause introduces a new pattern with its
+corresponding function body,
 ::
     load system io.
 
@@ -551,7 +550,7 @@ The output is as expected,
 Notice that we use the multi-dispatch mechanism to deal with the base cases in the first two ``with`` clauses.
 In the third ``with`` clause we use the pattern ``[pivot|rest]`` to match the input list.
 Here the variable ``pivot`` matches the first element of the list, and the variable ``rest`` matches the remaining list. This remaining list is the original list with its first element removed.
-The function body then implements the pretty much standard recursive definition of the
+The function body then implements the pretty much standard definition of the
 quick sort.  Just keep in mind that function calls are expressed via juxtaposition
 of function name and actual argument; no parentheses necessary.
 
@@ -576,6 +575,10 @@ Pattern Matching in Expressions: The Is Predicate
 
 We can also have pattern matching
 in expressions using the ``is`` predicate.
+The
+left operand of the ``is`` predicate is a term and
+the right operand is a pattern.
+If the pattern match succeeds the predicate will return ``true`` otherwise it will return ``false``.
 Consider the following example,
 ::
     load system io.
@@ -583,9 +586,9 @@ Consider the following example,
     let p = (1,2).
 
     if p is (x,y,z) do
-        io @println ("it's a triple with: "+x+","+y+","+z)
+        io @println ("it's a triple with: "+ tostring x +","+ tostring y +","+ tostring z)
     elif p is (x,y) do
-        io @println ("it's a pair with: "+x+","+y).
+        io @println ("it's a pair with: "+ tostring x +","+ tostring y).
     else do
         io @println "it's something else".
     end
@@ -601,9 +604,7 @@ be used.  That means we can use the predicate also on the right side of ``let``
 
     let true = (1,2) is (1,2).
 
-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
+This is kind of strange looking but it succeeds.    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`` pattern on the left of the ``=`` symbol.
 
@@ -681,7 +682,7 @@ the kind of values that are being passed to a particular function body,
             throw Error("factorial is not defined for "+n).
     end
 
-    io @println ("The factorial of 3 is: " + factorial 3).
+    io @println ("The factorial of 3 is: " + tostring (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.
@@ -701,7 +702,7 @@ This gives us,
             throw Error("factorial is not defined for "+n).
     end
 
-    io @println ("The factorial of 3 is: " + factorial 3).
+    io @println ("The factorial of 3 is: " + tostring (factorial 3)).
 The parentheses as they appear in the conditional pattern expressions are necessary.
 
 Pattern Matching in For Loops
@@ -739,7 +740,6 @@ Exception handling in Asteroid is very similar to exception handling in many of
 ::
     load system io.
     load system random.
-    load system type.
 
     structure Head with
         data val.
@@ -757,9 +757,9 @@ Exception handling in Asteroid is very similar to exception handling in many of
             throw Tail i.
         end
     catch Head v do
-        io @println ("you win with "+type @tostring (v,type @stringformat (4,2))).
+        io @println ("you win with "+tostring (v,stringformat (4,2))).
     catch Tail v do
-        io @println ("you loose with "+type @tostring (v,type @stringformat (4,2))).
+        io @println ("you loose with "+tostring (v,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.
 
@@ -844,7 +844,7 @@ data fields.  So even if we declare a structure like this,
 
     -- pattern matching ignores function definitions
     let Person(name,age) = Person("Scarlett",28).
-    io @println (name+" is "+age+" years old").
+    io @println (name+" is "+ tostring 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,
@@ -861,7 +861,6 @@ 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.
@@ -879,24 +878,24 @@ Here is the program listing for the example in Asteroid,
    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
+   for (Dog(name,tricks) if 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.
+After declaring the structure, we instantiate the dogs with their
+respective trick repertoires and we then put them on a list.  The last couple of lines
+of the program consist of a ``for`` loop over the 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 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 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``.
@@ -955,17 +954,17 @@ difficult to read.
 
 We can express the same function with a first-class pattern,
 ::
-    let TP = pattern q if (q is %boolean) or
+    let tp = pattern q if (q is %boolean) or
                           (q is %integer) or
                           (q is %string).
 
-    function foo with (x:*TP,y) do
+    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
-``TP``.
+``tp``.
 
 Pattern Reuse
 ^^^^^^^^^^^^^
@@ -996,94 +995,94 @@ In order to write these two functions we had to repeat the almost identical patt
 four times.  First-class patterns allow us to write the same two functions in a
 much more elegant way,
 ::
-    let POS_INT = pattern (x:%integer) if x > 0.
-    let NEG_INT = pattern (x:%integer) if x < 0.
+    let pos_int = pattern (x:%integer) if x > 0.
+    let neg_int = pattern (x:%integer) if x < 0.
 
     function fact
         with 0 do
             return 1
-        with n:*POS_INT do
+        with n:*pos_int do
             return n * fact (n-1).
-        with *NEG_INT do
+        with *neg_int do
             throw Error("fact undefined for negative values").
     end
 
     function sign
         with 0 do
             return 1
-        with *POS_INT do
+        with *pos_int do
             return 1.
-        with *NEG_INT do
+        with *neg_int do
             return -1.
     end
-The relevant patterns are now stored in the variables ``POS_INT`` and ``NEG_INT``
+The relevant patterns are now stored in the variables ``pos_int`` and ``neg_int``
 which are then used in the function definitions.
 
-Constraint Patterns
-^^^^^^^^^^^^^^^^^^^
+Patterns as Constraints
+^^^^^^^^^^^^^^^^^^^^^^^
 
 Sometimes we want to use patterns as constraints on other patterns.  Consider
-the following (somewhat artificial) example,
+the following example,
 ::
 
-   let x: (v if (v is %integer) and v > 0) = some_value.
+   let x: v if (v is %integer) and (v > 0) = some_value.
 
-Here we want to use the pattern ``v if (v is %integer) and v > 0`` purely as a constraint
+Here we want to use the pattern ``v if (v is %integer) and (v > 0)`` purely as a constraint
 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
+if the variable ``some_value`` holds a positive integer.  The problem is that this pattern
 introduces a spurious binding of the variable ``v`` into the current environment
-which might be undesirable due to variable name clashes.  Constraint patterns
-address this.  We can rewrite the above statement as follows,
+which might be undesirable due to variable name clashes.
+We can rewrite the above statement using the pattern scope operator ``%[...]%`` as follows,
 ::
 
-   let x: %[v if (v is %integer) and v > 0]% = some_value.
+   let x: %[v if (v is %integer) and (v > 0) ]% = some_value.
 
-By placing the pattern ``v if (v is %integer) and v > 0`` within the ``%[...]%``
-operators the pattern still functions as before but does not bind the variable ``v``
+By placing the pattern ``v if (v is %integer) and (v > 0)`` within the ``%[...]%``
+scope operator the pattern still functions as before but does not bind the variable ``v``
 into the current environment.
 
-The most common use of constraint patterns is the prevention of non-linear patterns
+The most common use of patterns as constraints is the prevention of non-linear patterns
 in functions.  Consider the following program,
 ::
    load system io.
 
-   let POS_INT = pattern %[v if (v is %integer) and v > 0]%.
+   let pos_int = pattern %[v if (v is %integer) and (v > 0)]%.
 
-   function add with (a:*POS_INT,b:*POS_INT) do
+   function add with (a:*pos_int,b:*pos_int) do
       return a+b.
    end
 
    io @println (add(1,2)).
-Without the ``%[...]%`` operators around the pattern ``v if (v is %integer) and v > 0``
+Without the ``%[...]%`` scope operator 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``
+``(a:*pos_int,b:*pos_int)`` would instantiate two instances of the variable ``v``
 leading to a non-linear pattern which is not supported by Asteroid.
-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
+With the ``%[...]%`` scope operator 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.
 
-Sometimes we need to use constraint patterns instead of straightforward patterns
+Sometimes we need to use patterns as constraints 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,
 ::
    -- declare a pattern that matches scalar values
-   let Scalar = pattern %[p if (p is %integer) or (p is %real)]%.
+   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)]%.
+   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
+      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).
-In the function definition of ``dot2d`` we see that the ``Pair`` pattern is used
+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
+However, 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
@@ -1094,6 +1093,43 @@ when trying to resolve non-linearities otherwise the binding term list can just
 of the variable names appearing in the pattern that you want to bind into the current
 scope.
 
+Notes on First-Class Patterns
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+It is important to remember that first-class patterns act like macros or dynamically scoped functions
+when they are used.  That is, anything that is referenced from within the pattern needs to be defined
+in the environment where the pattern is actually used!  That is especially true for patterns defined in different modules.
+
+Consider the following code,
+::
+    function foo with none do
+        load system math.  -- math only available in the function local scope
+        return pattern %[(x:%integer) if math@mod(x,2) == 0]%.
+    end
+
+    let even_pattern = foo().
+    let n:*even_pattern = 2.  -- Error: module 'math' not defined
+
+This code will fail with the error,
+::
+    error: 'math' is not defined
+
+Here, we construct a first-class pattern in the local scope of the function ``foo`` and return it to the caller.
+Since patterns are
+only evaluated at their usage points the ``math`` module in the function has no effect.  Furthermore,
+when finally applying the pattern in the last ``let`` statement the code will fail since the ``math`` module
+is not defined in that scope.
+
+To remedy the situation we have to move the loading of the ``math`` module into the scope where the
+pattern is used,
+::
+    function foo with none do
+        return pattern %[(x:%integer) if math@mod(x,2) == 0]%.
+    end
+
+    load system math.  -- now 'math' is available in the scope of the pattern usage
+    let even_pattern = foo().
+    let n:*even_pattern = 2.
+
 
 Basic Asteroid I/O
 ------------------
@@ -1104,41 +1140,41 @@ I/O functions are defined as member functions of the ``io`` module. The ``printl
 
     let a = 1.
     let b = 2.
-    io @println ("a + b = " + (a + b)).
+    io @println ("a + b = " + tostring (a + b)).
 The output is
 ::
 
     a + b = 3
 
-We can use the ``tostring`` function defined in the ``type`` module to provide some
+We can use the builtin ``tostring`` function 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])])
+    tostring(value[,stringformat(width spec[,precision spec])])
 
+Here the structures appearing in square brackets are optional.
 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)).
+    let b = tostring(true,stringformat(10)).
     io @println b.
 
-    let i = type @tostring(5,type @stringformat(5)).
+    let i = tostring(5,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)).
+    let s = tostring("hello there!",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)).
+    let r = tostring(math@pi,stringformat(6,3)).
     io @println r.
 The output of the program is,
 ::
@@ -1166,13 +1202,12 @@ The output is,
     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,
+We can use the builtin type casting functions such as ``tointeger`` or ``toreal``
+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: ")).
+    let i if i > 0  = tointeger(io @input("Please enter a positive integer value: ")).
 
     for k in 1 to i do
         io @println k.
@@ -1186,7 +1221,6 @@ The output is,
     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
 -----------------
@@ -1217,11 +1251,11 @@ Say that you wanted to load the ``math`` module so you could execute a certain t
     load system io.
     load system math.
 
-    let x = math @sin( math @pi / 2 ).
-    io @println("The sine of pi / 2 is " + x + ".").
+    let x = math @sin( math@pi / 2.0 ).
+    io @println("The sine of pi / 2 is " + tostring 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>`_.
+If you want the complete list of modules, make sure to check out the reference guide.
 
 
 More on Exceptions
@@ -1318,12 +1352,11 @@ exception object itself.  Here is an example using a ``wildcard``,
 Here is an example using a variable,
 ::
     load system io.
-    load system type.
 
     try
         let (x,y) = (1,2,3).
     catch e do
-        io @println ("something happened: "+type @tostring(e)).
+        io @println ("something happened: "+ tostring e).
     end
 In this last example we simply convert the caught exception object into a string
 and print it,
@@ -1346,15 +1379,14 @@ In order to demonstrate this type of multi-dispatch, we show the example program
 written in Asteroid,
 ::
     load system io.
-    load system type.
 
-    let pos_num = pattern %[x if type @isscalar(x) and x > 0]%.
+    let pos_num = pattern %[x if isscalar(x) and x > 0]%.
 
     structure Asteroid with
        data size.
        function __init_
           with v:*pos_num do
-             let this @size = v.
+             let this@size = v.
           end
     end
 
@@ -1362,7 +1394,7 @@ written in Asteroid,
         data size.
        function __init_
           with v:*pos_num do
-             let this @size = v.
+             let this@size = v.
           end
     end
 
@@ -1391,8 +1423,9 @@ written in Asteroid,
     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.
+Each ``with`` clause in the function ``collide_with`` introduces a new pattern with its
+corresponding function body.
+Each pattern represents a different data type.  In this case different kinds of pairs.
 The function bodies in this case are simple ``return`` statements
 but they could be arbitrary computations.  The output of the program is,
 ::
diff --git a/docs/User Guide.txt b/docs/User Guide.txt
index f7447f8f..03546228 100644
--- a/docs/User Guide.txt
+++ b/docs/User Guide.txt
@@ -1,11 +1,12 @@
 ..
     /******************************************************************
-    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 reference guide is
+    generated.  We use pcpp to insert live code snippets into the
+    document. In order to generate the reference guide run the
+    following command in the directory of
+    this doc:
 
-    bash generate_docs
+    python generate_docs.py
 
     ******************************************************************/
 
@@ -31,7 +32,7 @@ paradigm with first-class patterns.  Here are just two examples:
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-001.ast"
 
-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,
+that means the list ``[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,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-002.ast"
 
@@ -45,7 +46,7 @@ in order to ensure that the domain of the function is not violated,
 #include "../asteroid/test-suites/ug-programs/prgm-003.ast"
 
 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
+``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
 profound implications for software development in that pattern definition and usage
 points are now separate and patterns can be reused in different contexts.
@@ -58,30 +59,26 @@ with programming in Asteroid.
 The Basics
 ----------
 
-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,
+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 four primitive data types,
 
 * ``integer``, e.g. ``1024``
 * ``real``, e.g. ``1.75``
 * ``string``, e.g. ``"Hello, World!"``
 * ``boolean``, e.g. ``true``
 
-Asteroid arranges these primitive data types in a type hierarchy,
-
-``boolean`` < ``integer`` < ``real`` < ``string``
-
-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,
-::
-#include "../asteroid/test-suites/ug-programs/prgm-004.ast"
-
-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 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,)`` the 1-tuple versus ``(3)`` the parenthesized expression.
+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 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)``. 
+Lists are mutable structures in that we can add or delete elements.  On the other hand, tuples are immutable objects;
+once created you cannot change them.
+Furthermore, 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"
@@ -90,16 +87,11 @@ 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 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``
-
-That is, any list or tuple can be viewed as a string.  This is very convenient for printing lists and tuples,
+We can cast lists and tuples to strings for easy printing,
 ::
 #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.
+Here the ``+`` operator acts like a string concantenation operator with the list ``[1,2,3]`` promoted to a string. 
 
 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
@@ -110,15 +102,23 @@ interchangeably.  That is, the following ``let`` statements will succeed,
 #include "../asteroid/test-suites/ug-programs/prgm-008.ast"
 
 showing that ``()`` and ``none`` are equivalent and pattern-match each other.
-The ``none`` data type itself does not belong to any type hierarchy.
 
 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).
+Here is a small program demonstrating the ``pattern`` data type,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-008c.ast"
+
+
+Data types in Asteroid do not form type hierarchies as in C/C++ and Java, for example.  
+Therefore, in mixed type arithmetic statements we have to explicitly convert data types as in,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-008b.ast"
+
+Asteroid shares this view of data types with prgogramming languages like SML and Rust.  
 
 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.
 
@@ -133,8 +133,6 @@ elements of a list are accessed via the ``@`` operator,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-009.ast"
 
-The output is: ``[3,2,1]``.
-
 We can achieve the same effect by giving a list of index values (a slice) to the ``@`` operator,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-009a.ast"
@@ -181,7 +179,7 @@ where the output is,
 Tuples
 ^^^^^^
 
-As we saw earlier, the tuple is another fundamental, built-in data structure that can be found in Asteroid.
+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"
@@ -190,7 +188,7 @@ Lists and tuples may be nested,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-015.ast"
 
-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,
+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"
 
@@ -263,6 +261,7 @@ where we pattern match the pattern 1 on the left side to the value 1 on the righ
 
 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.
+This is often called "destructuring" of a 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).
@@ -277,47 +276,50 @@ the variables ``x`` and ``y`` where we expect our values to be,
     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.
+Matching the pattern against the value ``(1,2)`` stored in ``p`` first matches the pair structure against the pair value and then 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"
 
-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``.
+We first construct an object ``joe`` with the first ``let`` statement and then 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
 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``. 
-
-Asteroid also
-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,
+This ``let`` statement succeeds because ``1`` is an integer value that can be pattern-matched against
+the type pattern ``%integer``.  Type pattern exist for all builtin data types, ``%real`` and ``%list``.
+If you introduce a user defined type via a structure, then Asteroid will create a type pattern for all objects
+of that data type.  Here is a simple example,
 ::
-#include "../asteroid/test-suites/ug-programs/prgm-020.ast"
+#include "../asteroid/test-suites/ug-programs/prgm-019a.ast"
 
-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,
+Notice the type pattern for the user defined type ``Foo`` in the ``let`` statement.
+
+Asteroid also supports conditional patterns.  Here is an example where we to make sure that the
+variable ``t`` on the left matches a pair of integer values,
 ::
-    (1,2)
+    let t if t is (%integer,%integer) = (1,2).
 
-Named patterns are a shorthand notation for conditional patterns; in this case,
+Of course, this ``let`` statement is going to be successful because the value on the right is indeed a
+pair of integers.  This kind of conditional pattern appears so often in Asteroid code that 
+Asteroid has a shorthand notation for this,
 ::
-    let t if t is (x,y) = (1,2).
+    let t:(%integer,%integer) = (1,2).
+
+Again, here the ``let`` statement is only successful if ``t`` matches a pair of integers.
 
-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
+Shorthand conditional patterns often look
+like a variable declarations in other languages. In Asteroid, though, it is still just all
 about pattern matching.  Consider,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-021.ast"
 
-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.141592653589793``.
+The left side of the ``let`` statement is a conditional pattern that matches any real value, and
+if that match is successful then the value is bound to the variable ``x``.  
+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 
@@ -360,7 +362,7 @@ The output is,
     the third bird is a chicken
 
 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)``.
+iterate while 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,
 ::
@@ -396,8 +398,8 @@ In Asteroid functions are multi-dispatch, that is,
 a single function can have multiple bodies each attached to a different pattern
 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,
+Asteroid where each ``with`` clause introduces a new pattern with its
+corresponding function body,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-026.ast"
 
@@ -409,7 +411,7 @@ The output is as expected,
 Notice that we use the multi-dispatch mechanism to deal with the base cases in the first two ``with`` clauses.
 In the third ``with`` clause we use the pattern ``[pivot|rest]`` to match the input list.
 Here the variable ``pivot`` matches the first element of the list, and the variable ``rest`` matches the remaining list. This remaining list is the original list with its first element removed.
-The function body then implements the pretty much standard recursive definition of the
+The function body then implements the pretty much standard definition of the
 quick sort.  Just keep in mind that function calls are expressed via juxtaposition
 of function name and actual argument; no parentheses necessary.
 
@@ -433,6 +435,10 @@ Pattern Matching in Expressions: The Is Predicate
 
 We can also have pattern matching
 in expressions using the ``is`` predicate.
+The
+left operand of the ``is`` predicate is a term and
+the right operand is a pattern.
+If the pattern match succeeds the predicate will return ``true`` otherwise it will return ``false``.
 Consider the following example,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-028.ast"
@@ -449,9 +455,7 @@ be used.  That means we can use the predicate also on the right side of ``let``
 
     let true = (1,2) is (1,2).
 
-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
+This is kind of strange looking but it succeeds.    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`` pattern on the left of the ``=`` symbol.
 
@@ -596,21 +600,21 @@ 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 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.
+After declaring the structure, we instantiate the dogs with their
+respective trick repertoires and we then put them on a list.  The last couple of lines
+of the program consist of a ``for`` loop over the 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 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 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``.
@@ -669,17 +673,17 @@ difficult to read.
 
 We can express the same function with a first-class pattern,
 ::
-    let TP = pattern q if (q is %boolean) or
+    let tp = pattern q if (q is %boolean) or
                           (q is %integer) or
                           (q is %string).
 
-    function foo with (x:*TP,y) do
+    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
-``TP``.
+``tp``.
 
 Pattern Reuse
 ^^^^^^^^^^^^^
@@ -697,46 +701,46 @@ much more elegant way,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-039.ast"
 
-The relevant patterns are now stored in the variables ``POS_INT`` and ``NEG_INT``
+The relevant patterns are now stored in the variables ``pos_int`` and ``neg_int``
 which are then used in the function definitions.
 
-Constraint Patterns
-^^^^^^^^^^^^^^^^^^^
+Patterns as Constraints
+^^^^^^^^^^^^^^^^^^^^^^^
 
 Sometimes we want to use patterns as constraints on other patterns.  Consider
-the following (somewhat artificial) example,
+the following example,
 ::
 
-   let x: (v if (v is %integer) and v > 0) = some_value.
+   let x: v if (v is %integer) and (v > 0) = some_value.
 
-Here we want to use the pattern ``v if (v is %integer) and v > 0`` purely as a constraint
+Here we want to use the pattern ``v if (v is %integer) and (v > 0)`` purely as a constraint
 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
+if the variable ``some_value`` holds a positive integer.  The problem is that this pattern
 introduces a spurious binding of the variable ``v`` into the current environment
-which might be undesirable due to variable name clashes.  Constraint patterns
-address this.  We can rewrite the above statement as follows,
+which might be undesirable due to variable name clashes.   
+We can rewrite the above statement using the pattern scope operator ``%[...]%`` as follows,
 ::
 
-   let x: %[v if (v is %integer) and v > 0]% = some_value.
+   let x: %[v if (v is %integer) and (v > 0) ]% = some_value.
 
-By placing the pattern ``v if (v is %integer) and v > 0`` within the ``%[...]%``
-operators the pattern still functions as before but does not bind the variable ``v``
+By placing the pattern ``v if (v is %integer) and (v > 0)`` within the ``%[...]%``
+scope operator the pattern still functions as before but does not bind the variable ``v``
 into the current environment.
 
-The most common use of constraint patterns is the prevention of non-linear patterns
+The most common use of patterns as constraints is the prevention of non-linear patterns
 in functions.  Consider the following program,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-043.ast"
 
-Without the ``%[...]%`` operators around the pattern ``v if (v is %integer) and v > 0``
+Without the ``%[...]%`` scope operator 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``
+``(a:*pos_int,b:*pos_int)`` would instantiate two instances of the variable ``v``
 leading to a non-linear pattern which is not supported by Asteroid.
-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
+With the ``%[...]%`` scope operator 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.
 
-Sometimes we need to use constraint patterns instead of straightforward patterns
+Sometimes we need to use patterns as constraints 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.  
@@ -744,9 +748,9 @@ Consider the following program,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-043a.ast"
 
-In the function definition of ``dot2d`` we see that the ``Pair`` pattern is used 
+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 
+However, 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 
@@ -757,6 +761,43 @@ when trying to resolve non-linearities otherwise the binding term list can just
 of the variable names appearing in the pattern that you want to bind into the current
 scope.
 
+Notes on First-Class Patterns
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+It is important to remember that first-class patterns act like macros or dynamically scoped functions 
+when they are used.  That is, anything that is referenced from within the pattern needs to be defined 
+in the environment where the pattern is actually used!  That is especially true for patterns defined in different modules.
+
+Consider the following code,
+::
+    function foo with none do
+        load system math.  -- math only available in the function local scope
+        return pattern %[(x:%integer) if math@mod(x,2) == 0]%.
+    end
+
+    let even_pattern = foo().  
+    let n:*even_pattern = 2.  -- Error: module 'math' not defined
+
+This code will fail with the error,
+::
+    error: 'math' is not defined
+
+Here, we construct a first-class pattern in the local scope of the function ``foo`` and return it to the caller.  
+Since patterns are 
+only evaluated at their usage points the ``math`` module in the function has no effect.  Furthermore,
+when finally applying the pattern in the last ``let`` statement the code will fail since the ``math`` module
+is not defined in that scope.
+
+To remedy the situation we have to move the loading of the ``math`` module into the scope where the
+pattern is used,
+::
+    function foo with none do
+        return pattern %[(x:%integer) if math@mod(x,2) == 0]%.
+    end
+
+    load system math.  -- now 'math' is available in the scope of the pattern usage
+    let even_pattern = foo().  
+    let n:*even_pattern = 2. 
+
 
 Basic Asteroid I/O
 ------------------
@@ -770,12 +811,13 @@ The output is
 
     a + b = 3
 
-We can use the ``tostring`` function defined in the ``type`` module to provide some
+We can use the builtin ``tostring`` function 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])])
+    tostring(value[,stringformat(width spec[,precision spec])])
 
+Here the structures appearing in square brackets are optional.
 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,
@@ -806,8 +848,8 @@ The output is,
     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,
+We can use the builtin type casting functions such as ``tointeger`` or ``toreal``
+to convert the string returned from ``input`` into a numeric value,
 ::
 #include "../asteroid/test-suites/ug-programs/prgm-054.ast"
 
@@ -820,7 +862,6 @@ The output is,
     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
 -----------------
@@ -852,7 +893,7 @@ 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>`_.
+If you want the complete list of modules, make sure to check out the reference guide.
 
 
 More on Exceptions
@@ -947,8 +988,9 @@ 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.
+Each ``with`` clause in the function ``collide_with`` introduces a new pattern with its
+corresponding function body.
+Each pattern represents a different data type.  In this case different kinds of pairs.
 The function bodies in this case are simple ``return`` statements
 but they could be arbitrary computations.  The output of the program is,
 ::
diff --git a/docs/conf.py b/docs/conf.py
index b2719ea9..6644376c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -18,11 +18,14 @@
 # -- Project information -----------------------------------------------------
 
 project = 'Asteroid'
-copyright = '2022- University of Rhode Island'
+copyright = '2021- University of Rhode Island'
 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.4'
+# when generating docs make sure that PYTHONPATH points
+# to the root directory of the github repo
+from asteroid.version import VERSION
+release = VERSION
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/docs/generate_docs b/docs/generate_docs
deleted file mode 100755
index 4d5679c4..00000000
--- a/docs/generate_docs
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-echo "generating 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"
-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"
-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"
-pcpp --passthru-comments --line-directive nothing "Quickstart Tutorial.txt" > "Quickstart Tutorial.rst"
-
-echo "generating ADB.rst"
-#cpp -w -P -traditional "ADB.txt" > "ADB.rst"
-pcpp --passthru-comments --line-directive nothing "ADB.txt" > "ADB.rst"
diff --git a/docs/generate_docs.py b/docs/generate_docs.py
new file mode 100755
index 00000000..e80d12d7
--- /dev/null
+++ b/docs/generate_docs.py
@@ -0,0 +1,29 @@
+'''
+This python script generates the RST files for our documentation.
+
+NOTE: make sure that you have PCPP installed on your system before attempting
+to generate documentation,
+
+      pip install pcpp
+'''
+
+import subprocess
+
+try:
+   print("generating User Guide.rst")
+   subprocess.run(["pcpp","--passthru-comments","--line-directive","nothing","-o","User Guide.rst","User Guide.txt"])
+
+   print("generating Reference Guide.rst")
+   subprocess.run(["pcpp","--passthru-comments","--line-directive","nothing","-o","Reference Guide.rst","Reference Guide.txt"])
+
+   print("generating Asteroid in Action.rst")
+   subprocess.run(["pcpp","--passthru-comments","--line-directive","nothing","-o","Asteroid in Action.rst","Asteroid in Action.txt"])
+
+   print("generating Quickstart Tutorial.rst")
+   subprocess.run(["pcpp","--passthru-comments","--line-directive","nothing","-o","Quickstart Tutorial.rst","Quickstart Tutorial.txt"])
+
+   print("generating MAD.rst")
+   subprocess.run(["pcpp","--passthru-comments","--line-directive","nothing","-o","MAD.rst","MAD.txt"])
+except FileNotFoundError as e:
+   print(str(e))
+   exit(1)
diff --git a/docs/index.rst b/docs/index.rst
index d327a3e9..4396907f 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -21,4 +21,4 @@ Contents
    User Guide
    Reference Guide
    Asteroid in Action
-   ADB
\ No newline at end of file
+   MAD
\ No newline at end of file
diff --git a/docs/strip b/docs/strip
deleted file mode 100644
index c8525d8e..00000000
--- a/docs/strip
+++ /dev/null
@@ -1,57 +0,0 @@
-#!/bin/bash
-# Strip C comments
-# by Stewart Ravenhall <stewart.ravenhall@ukonline.co.uk> -- 4 October 2000
-# Un-Korn-ized by Paolo Bonzini <bonzini@gnu.org> -- 24 November 2000
-# adapted to bash by Lutz Hamel <lutzhamel@uri.edu> -- 6 February 2022
-
-# Strip everything between /* and */ inclusive
-
-# Copes with multi-line comments,
-# disassociated end comment symbols,
-# disassociated start comment symbols,
-# multiple comments per line
-
-# Check given file exists
-program=`echo $0|sed -e 's:.*/::'`
-if [ "$#" = 1 ] && [ "$1" != "-" ] && [ ! -f "$1" ]; then
-        echo "$program: $1 does not exist"
-        exit 2
-fi
-
-# Create shell variables for ASCII 1 (control-a)
-# and ASCII 2 (control-b)
-a="`echo | tr '\012' '\001'`"
-b="`echo | tr '\012' '\002'`"
-
-sed '
-        # If no start comment then go to end of script
-        /\/\*/!b
-        :a
-        s:/\*:'"$a"':g
-        s:\*/:'"$b"':g
-
-        # If no end comment
-    /'"$b"'/!{
-        :b
-
-                # If not last line then read in next one
-                $!{
-                        N
-                        ba
-                }
-
-                # If last line then remove from start
-                # comment to end of line
-                # then go to end of script
-                s:'"$a[^$b]"'*$::
-                bc
-        }
-
-        # Remove comments
-        '"s:$a[^$b]*$b"'::g
-    /'"$a"'/ bb
-
-        :c
-        s:'"$a"':/*:g
-        s:'"$b"':*/:g
-' $1
diff --git a/setup.py b/setup.py
index d9c253f1..6d23e6a2 100644
--- a/setup.py
+++ b/setup.py
@@ -1,11 +1,15 @@
+# when cutting releases make sure that PYTHONPATH points
+# to the root directory of the github repo
+
 from setuptools import setup, find_packages
+from asteroid.version import VERSION
 
 with open("README.md", "r") as fh:
     long_description = fh.read()
 
 setup(
     name="asteroid-lang",
-    version="1.1.4",
+    version=VERSION,
     author="University of Rhode Island",
     author_email="lutzhamel@uri.edu",
     description="A modern, multi-paradigm programming language.",
@@ -28,7 +32,7 @@
         "License :: OSI Approved :: MIT License",
         "Operating System :: OS Independent",
     ],
-    python_requires=">=3.6",
+    python_requires=">=3.10",
     entry_points={
         "console_scripts": [
             "asteroid = asteroid:main",


Test patch:
diff --git a/asteroid/test-suites/action-tests/test012.ast b/asteroid/test-suites/action-tests/test012.ast
index 04121140..309a1e9b 100644
--- a/asteroid/test-suites/action-tests/test012.ast
+++ b/asteroid/test-suites/action-tests/test012.ast
@@ -4,5 +4,5 @@
   let ext = ".txt".
 
   for i in 1 to 5 do
-      io @println (root+i+ext).
+      io @println (root + tostring i + ext).
   end
diff --git a/asteroid/test-suites/action-tests/test013.ast b/asteroid/test-suites/action-tests/test013.ast
index 3cea1353..0de780b0 100644
--- a/asteroid/test-suites/action-tests/test013.ast
+++ b/asteroid/test-suites/action-tests/test013.ast
@@ -1,5 +1,4 @@
   load system io.
-  load system type.
   load system util.
   load system pick.
   load system random.
@@ -7,7 +6,7 @@
   random @seed(42).
 
   -- make up lists of symbols useful for password construction
-  let int_list = [0 to 9] @map(type @tostring).
+  let int_list = [0 to 9] @map(tostring).
   let lc_list = [97 to 122] @map(util @achar). -- lower case characters
   let uc_list = [65 to 90] @map(util @achar). --upper case characters
   let sp_list = ["!","_","#","$","%","*"].
diff --git a/asteroid/test-suites/action-tests/test016.ast b/asteroid/test-suites/action-tests/test016.ast
index 40abab14..e7bc4ca7 100644
--- a/asteroid/test-suites/action-tests/test016.ast
+++ b/asteroid/test-suites/action-tests/test016.ast
@@ -1,5 +1,5 @@
   load system io.
 
   for n in 0 to 5 do
-      io @println (n+" file"+("s " if n>1 or n==0 else " ")+"found").
+      io @println (tostring n + " file" + ("s " if n>1 or n==0 else " ") + "found").
   end
diff --git a/asteroid/test-suites/action-tests/test017.ast b/asteroid/test-suites/action-tests/test017.ast
index bfca622a..3a600062 100644
--- a/asteroid/test-suites/action-tests/test017.ast
+++ b/asteroid/test-suites/action-tests/test017.ast
@@ -41,7 +41,7 @@
   -- put the words into a hash table, the value is the count of the words
   let ht = hash @hash().
   for w in wl do
-      if not ht @get(w) do
+      if ht @get(w) is none do
           ht @insert(w,1).
       else do
           ht @insert(w,ht @get(w)+1).
diff --git a/asteroid/test-suites/action-tests/test018.ast b/asteroid/test-suites/action-tests/test018.ast
index b527952a..45a77afa 100644
--- a/asteroid/test-suites/action-tests/test018.ast
+++ b/asteroid/test-suites/action-tests/test018.ast
@@ -7,13 +7,13 @@
   for startix in 0 to stra @length()-1 do
       for endix in startix to stra @length()-1 do
           let s = stra @[startix to endix].
-          if strb @index(s) and s @length() > common @length() do
+          if strb @index(s) =/= -1 and s @length() > common @length() do
               let common = s.
           end
       end
   end
 
-  if common do
+  if common =/= "" do
       io @println ("The longest common substring is '"+common+"'.").
   else do
       io @println ("There are no common substrings.").
diff --git a/asteroid/test-suites/action-tests/test022.ast b/asteroid/test-suites/action-tests/test022.ast
index b90110c8..398cfa36 100644
--- a/asteroid/test-suites/action-tests/test022.ast
+++ b/asteroid/test-suites/action-tests/test022.ast
@@ -104,7 +104,7 @@
       -- Note: make this code more general
       let n_gram = [word_list@i, word_list@(i+1), word_list @(i+2)] @join(" ").
       -- put the N-gram into a hash table, the value is the count of the N-gram in the text.
-      if not ht @get(n_gram) do
+      if ht @get(n_gram) is none do
           ht @insert(n_gram,1).
       else do
           ht @insert(n_gram,ht @get(n_gram)+1).
@@ -112,5 +112,5 @@
   end
 
   for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
-      io @println (n_gram+": "+cnt).
+      io @println (n_gram+": "+ tostring cnt).
   end
diff --git a/asteroid/test-suites/action-tests/test024.ast b/asteroid/test-suites/action-tests/test024.ast
index f8e3dbfe..fbd155fa 100644
--- a/asteroid/test-suites/action-tests/test024.ast
+++ b/asteroid/test-suites/action-tests/test024.ast
@@ -1,7 +1,7 @@
   load system io.
   load system math.
 
-  let tau = 2 * math @pi.
+  let tau = 2.0 * math @pi.
 
   io @println (math @e).
   io @println tau.
diff --git a/asteroid/test-suites/action-tests/test026.ast b/asteroid/test-suites/action-tests/test026.ast
index 74f53e4b..606a57d8 100644
--- a/asteroid/test-suites/action-tests/test026.ast
+++ b/asteroid/test-suites/action-tests/test026.ast
@@ -12,5 +12,5 @@
           throw Error("factorial is not defined for "+n).
       end
 
-  io @println ("The factorial of 3 is: " + fact (3)).
+  io @println ("The factorial of 3 is: " + tostring(fact 3)).
   assert (fact(3) == 6).
diff --git a/asteroid/test-suites/action-tests/test033.ast b/asteroid/test-suites/action-tests/test033.ast
index 4f14055b..f676e4eb 100644
--- a/asteroid/test-suites/action-tests/test033.ast
+++ b/asteroid/test-suites/action-tests/test033.ast
@@ -4,7 +4,7 @@
   function isprime with x do
       if x >= 2 do
           for y in range(2,x) do
-              if not math @mod(x,y) do
+              if math @mod(x,y) == 0 do
                   return false.
               end
           end
diff --git a/asteroid/test-suites/action-tests/test034.ast b/asteroid/test-suites/action-tests/test034.ast
index e739bf6b..5db7e783 100644
--- a/asteroid/test-suites/action-tests/test034.ast
+++ b/asteroid/test-suites/action-tests/test034.ast
@@ -4,7 +4,7 @@
   function isprime with x do
       if x >= 2 do
           for y in range(2,x) do
-              if not math @mod(x,y) do
+              if math @mod(x,y) == 0 do
                   return false.
               end
           end
diff --git a/asteroid/test-suites/action-tests/test035.ast b/asteroid/test-suites/action-tests/test035.ast
index f5951893..62687fe3 100644
--- a/asteroid/test-suites/action-tests/test035.ast
+++ b/asteroid/test-suites/action-tests/test035.ast
@@ -4,7 +4,7 @@
   function isprime with x do
       if x >= 2 do
           for y in range(2,x) do
-              if not math @mod(x,y) do
+              if math @mod(x,y) == 0 do
                   return false.
               end
           end
@@ -30,7 +30,7 @@
   while n > 1 do
       let factor = primes_list @ix.
       let ix = ix+1.
-      if not math @mod(n,factor) do
+      if math @mod(n,factor) == 0 do
           let ix = 0.
           let n = n/factor.
           let factors = factors+[factor].
diff --git a/asteroid/test-suites/action-tests/test038.ast b/asteroid/test-suites/action-tests/test038.ast
index 9ba4e8b0..6d4e5eec 100644
--- a/asteroid/test-suites/action-tests/test038.ast
+++ b/asteroid/test-suites/action-tests/test038.ast
@@ -1,7 +1,6 @@
   load system io.
   load system random.
   load system util.
-  load system type.
 
   let randint = random @randint.
 
@@ -13,5 +12,5 @@
 
   -- generating a random number in the appropriate interval
   let n = 10.
-  io @println (randint(0.0,type @toreal(n))).
+  io @println (randint(0.0, toreal n)).
   io @println (randint(0,n)).
diff --git a/asteroid/test-suites/action-tests/test039.ast b/asteroid/test-suites/action-tests/test039.ast
index ff6e72b8..ef8ccb11 100644
--- a/asteroid/test-suites/action-tests/test039.ast
+++ b/asteroid/test-suites/action-tests/test039.ast
@@ -1,17 +1,16 @@
   load system io.
   load system util.
-  load system type.
 
   let n = 1234.
   let sq = n*n.
-  let sq_str = type @tostring(sq).
+  let sq_str = tostring sq.
   if sq_str @length() < 8 do
       let prefix = [1 to 8-sq_str@length()] @map(lambda with _ do return "0")
                                             @join("").
       let sq_str = prefix + sq_str.
   end
   let rstr = sq_str @[2 to 5].
-  let rval = type @tointeger(rstr).
+  let rval = tointeger rstr.
   io @println rval.
 
   assert (rval == 5227)
diff --git a/asteroid/test-suites/action-tests/test043.ast b/asteroid/test-suites/action-tests/test043.ast
index 65d1b8f7..1c4359a4 100644
--- a/asteroid/test-suites/action-tests/test043.ast
+++ b/asteroid/test-suites/action-tests/test043.ast
@@ -3,11 +3,11 @@
 
   let values = [727.7, 1086.5, 1091.0, 1361.3, 1490.5, 1956.1].
 
-  let avg = values @reduce(lambda with (x,y) do return x+y) / values @length().
+  let avg = values @reduce(lambda with (x,y) do return x+y) / toreal(values @length()).
   let diff_sq = values @map(lambda with x do return math @pow(x-avg,2)).
   let numerator = diff_sq @reduce(lambda with (x,y) do return x+y).
   let denominator = values @length() -1.
-  let sigma = math @sqrt(numerator/denominator).
+  let sigma = math @sqrt(numerator/toreal denominator).
   io @println sigma.
 
   assert (sigma == 420.96248961952256)
diff --git a/asteroid/test-suites/action-tests/test045.ast b/asteroid/test-suites/action-tests/test045.ast
index 3f23b73c..d115c8a6 100644
--- a/asteroid/test-suites/action-tests/test045.ast
+++ b/asteroid/test-suites/action-tests/test045.ast
@@ -1,7 +1,6 @@
   load system io.
   load system math.
   load system util.
-  load system type.
 
   -- define common math functions locally so the
   -- formulas are easy to read
@@ -11,7 +10,6 @@
   let pow = math @pow.
   let atan = math @atan.
   let pi = math @pi.
-  let toreal = type @toreal.
 
   function polar_to_cartesian with (r,psi) do
       -- return a tuple: (x,y)
@@ -24,11 +22,11 @@
 
   function cartesian_to_psi
       with (x,y) if x > 0  do
-          return atan(toreal(y)/x).
+          return atan(toreal y/toreal x).
       with (x,y) if x < 0 and y >= 0 do
-          return atan(toreal(y)/x)+pi.
+          return atan(toreal y/toreal x)+pi.
       with (x,y) if x < 0 and y < 0 do
-          return atan(toreal(y)/x)-pi.
+          return atan(toreal y/toreal x)-pi.
       with (x,y) if x == 0 and y > 0 do
           return pi/2.
       with (x,y) if x == 0 and y < 0 do
diff --git a/asteroid/test-suites/action-tests/test046.ast b/asteroid/test-suites/action-tests/test046.ast
index 0876a4eb..ce312a4d 100644
--- a/asteroid/test-suites/action-tests/test046.ast
+++ b/asteroid/test-suites/action-tests/test046.ast
@@ -16,7 +16,7 @@
           let inside = inside+1.
       end
   end
-  let area = 4.0 * inside / n.
+  let area = 4.0 * toreal inside / toreal n.
   io @println area.
 
   assert (area == 3.1392).
diff --git a/asteroid/test-suites/action-tests/test047.ast b/asteroid/test-suites/action-tests/test047.ast
index b04b5155..5ef4b4ad 100644
--- a/asteroid/test-suites/action-tests/test047.ast
+++ b/asteroid/test-suites/action-tests/test047.ast
@@ -1,18 +1,17 @@
   load system io.
   load system random.
   load system util.
-  load system type.
 
   random @seed(42).
 
   let n = random @randint(0,10).
-  let guess = type @tointeger(io @input("Guess my number between 0 and 10: ")).
+  let guess = tointeger(io @input("Guess my number between 0 and 10: ")).
   while guess =/= n do
       if guess < n do
           io @println "Too small.".
       elif guess > n  do
            io @println "Too big.".
       end
-      let guess = type @tointeger(io @input("Try again: ")).
+      let guess = tointeger(io @input("Try again: ")).
   end
   io @println "Yes, this is it!".
diff --git a/asteroid/test-suites/action-tests/test048.ast b/asteroid/test-suites/action-tests/test048.ast
index 0984ee04..4b23dc88 100644
--- a/asteroid/test-suites/action-tests/test048.ast
+++ b/asteroid/test-suites/action-tests/test048.ast
@@ -1,8 +1,7 @@
   load system io.
-  load system type.
 
   let bin = "101101".
-  let int = type @tointeger(bin,2).
+  let int = tointeger(bin,2).
   io @println int.
 
   assert (int == 45).
diff --git a/asteroid/test-suites/action-tests/test049.ast b/asteroid/test-suites/action-tests/test049.ast
index fd0656c3..a4dd8fab 100644
--- a/asteroid/test-suites/action-tests/test049.ast
+++ b/asteroid/test-suites/action-tests/test049.ast
@@ -1,8 +1,4 @@
   load system io.
-  load system type.
-
-  let tobase = type @tobase.
-  let tointeger = type @tointeger.
 
   let val = 42.
 
diff --git a/asteroid/test-suites/action-tests/test050.ast b/asteroid/test-suites/action-tests/test050.ast
index 4b3838b0..9fd6f182 100644
--- a/asteroid/test-suites/action-tests/test050.ast
+++ b/asteroid/test-suites/action-tests/test050.ast
@@ -1,12 +1,11 @@
   load system io.
-  load system type.
 
   let number = 139487854.
 
 
-  let s = type @tostring number @explode()
-                                @map(type @tointeger)
-                                @reduce(lambda with (x,y) do return x+y).
+  let s = tostring number @explode()
+                          @map tointeger
+                          @reduce (lambda with (x,y) do x+y).
   io @println s.
 
   assert (s == 49).
diff --git a/asteroid/test-suites/action-tests/test052.ast b/asteroid/test-suites/action-tests/test052.ast
index 5d41c460..589de576 100644
--- a/asteroid/test-suites/action-tests/test052.ast
+++ b/asteroid/test-suites/action-tests/test052.ast
@@ -1,7 +1,6 @@
   load system io.
-  load system type.
 
-  let a = type @tointeger([67, 8, 1, 5, 45] @map(type @tostring) @sort(true) @join("")).
+  let a = tointeger ([67, 8, 1, 5, 45] @map tostring @sort true @join "").
   io @println a.
 
   assert (a == 8675451).
diff --git a/asteroid/test-suites/action-tests/test053.ast b/asteroid/test-suites/action-tests/test053.ast
index 4f35a8de..6179dc9d 100644
--- a/asteroid/test-suites/action-tests/test053.ast
+++ b/asteroid/test-suites/action-tests/test053.ast
@@ -2,7 +2,6 @@
   load system math.
   load system util.
   load system hash.
-  load system type.
 
   let roman_hash = hash @hash().
   roman_hash @insert(1000,["","M","MM","MMM"]).
@@ -11,11 +10,11 @@
   roman_hash @insert(1,["","I","II","III","IV","V","VI","VII","VIII","IX"]).
 
   let n = 2018.
-  let p10 = range(type @tostring n @length()) @map(lambda with x do return math @pow(10,x))
-                                              @reverse().
-  let digits = type @tostring n @explode()
-                                @map(type @tointeger).
-  let z = util @zip(digits, p10).
+  let p10 = range(tostring n @length()) @map(lambda with x do math @pow (10,x))
+                                        @reverse().
+  let digits = tostring n @explode ()
+                          @map tointeger.
+  let z = util @zip (digits, p10).
   io @println z.
   let roman = "".
   for (d,p) in z do
diff --git a/asteroid/test-suites/action-tests/test054.ast b/asteroid/test-suites/action-tests/test054.ast
index 9a12bd9d..48745b41 100644
--- a/asteroid/test-suites/action-tests/test054.ast
+++ b/asteroid/test-suites/action-tests/test054.ast
@@ -13,7 +13,7 @@
           return names @n.
       with (n:%integer) if n < 100 do
           let r = names @(n / 10 + 18).
-          let r = r + ("-" + names @(mod(n,10))) if mod(n,10) else "".
+          let r = r + ("-" + names @(mod(n,10))) if mod(n,10) =/= 0 else "".
           return r.
       with (n:%integer) if n < 1000 do
           return spell_part(n,100,"hundred").
@@ -24,7 +24,7 @@
   function spell_part
       with (n:%integer,base:%integer,name:%string) do
           let r = spell_number(n/base) + " " + name.
-          return r + " " + spell_number(mod(n,base)) if mod(n,base) else r.
+          return r + " " + spell_number(mod(n,base)) if mod(n,base) =/= 0 else r.
       end
 
   io @println (spell_number 15).
diff --git a/asteroid/test-suites/action-tests/test055.ast b/asteroid/test-suites/action-tests/test055.ast
index 09efbd39..6bcb712d 100644
--- a/asteroid/test-suites/action-tests/test055.ast
+++ b/asteroid/test-suites/action-tests/test055.ast
@@ -2,6 +2,6 @@
 
   let (a,b) = (10,20).
   let (b,a) = (a,b).
-  io @println ("a = "+a,"b = "+b).
+  io @println ("a = "+ tostring a,"b = "+ tostring b).
 
   assert ((a,b) is (20,10)).
diff --git a/asteroid/test-suites/action-tests/test068.ast b/asteroid/test-suites/action-tests/test068.ast
index 4441301e..350cd555 100644
--- a/asteroid/test-suites/action-tests/test068.ast
+++ b/asteroid/test-suites/action-tests/test068.ast
@@ -59,6 +59,6 @@ function sum with lst:%list do
 end
 
 let dt = [1 to 100] @map(lambda with _ do return random @random()).
-let mavg = [3 to 96] @map(lambda with i do return sum(window(dt,i))/7).
+let mavg = [3 to 96] @map(lambda with i do return sum(window(dt,i))/toreal 7).
 
 plot(dt @[3 to 96],mavg).
diff --git a/asteroid/test-suites/action-tests/test069.ast b/asteroid/test-suites/action-tests/test069.ast
index 8a1c090f..bbb2275a 100644
--- a/asteroid/test-suites/action-tests/test069.ast
+++ b/asteroid/test-suites/action-tests/test069.ast
@@ -2,4 +2,6 @@
 
   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")).
+  io @println ((tostring x +" is in the list") 
+          if array @member x 
+          else (tostring x + " is not in the list")).
diff --git a/asteroid/test-suites/action-tests/test070.ast b/asteroid/test-suites/action-tests/test070.ast
index 779bb07e..9f407eb0 100644
--- a/asteroid/test-suites/action-tests/test070.ast
+++ b/asteroid/test-suites/action-tests/test070.ast
@@ -3,8 +3,8 @@
   let array = [10, 14, 0, 15, 17, 20, 30, 35].
   let x = 17.
 
-  if array @reduce(lambda with (acc,i) do return true if i==x else acc,false) do
-      io @println (x+" is in the list").
+  if array @reduce(lambda with (acc,i) do true if i==x else acc,false) do
+      io @println (tostring x + " is in the list").
   else
-      io @println (x+" is not in the list").
+      io @println (tostring x + " is not in the list").
   end
diff --git a/asteroid/test-suites/action-tests/test071.ast b/asteroid/test-suites/action-tests/test071.ast
index a8127013..b67a2ca2 100644
--- a/asteroid/test-suites/action-tests/test071.ast
+++ b/asteroid/test-suites/action-tests/test071.ast
@@ -1,10 +1,9 @@
   load system io.
   load system math.
   load system util.
-  load system type.
 
   let mod = math @mod.
 
   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).
+  let odd = array @reduce (lambda with (acc,i) do i if isnone acc and mod(i,2) =/= 0 else acc,none).
   io @println odd.
diff --git a/asteroid/test-suites/action-tests/test072.ast b/asteroid/test-suites/action-tests/test072.ast
index 2d5b867d..a9c0b57c 100644
--- a/asteroid/test-suites/action-tests/test072.ast
+++ b/asteroid/test-suites/action-tests/test072.ast
@@ -1,7 +1,7 @@
   load system io.
   load system math.
 
-  let array = [20 to 30] @filter(lambda with x do return math @mod(x,2)).
+  let array = [20 to 30] @filter(lambda with x do math @mod(x,2)=/=0).
   io @println array.
 
   assert (array == [21,23,25,27,29]).
diff --git a/asteroid/test-suites/action-tests/test077.ast b/asteroid/test-suites/action-tests/test077.ast
index 8581896a..a7ff9e5b 100644
--- a/asteroid/test-suites/action-tests/test077.ast
+++ b/asteroid/test-suites/action-tests/test077.ast
@@ -1,9 +1,8 @@
   load system io.
-  load system type.
 
   let a = [3, 7, 19, 20, 34].
-  let b = type @toboolean(a @reduce(lambda with (x,y) do return y if x<y else false)).
+  let b = a @reduce(lambda with ((_,x),y) do (true,y) if x<=y else (false,y),(true,a@0)).
 
-  io @println b.
+  io @println (b@0).
 
-  assert (b).
+  assert (b@0).
diff --git a/asteroid/test-suites/action-tests/test078.ast b/asteroid/test-suites/action-tests/test078.ast
index e7863b20..8d706304 100644
--- a/asteroid/test-suites/action-tests/test078.ast
+++ b/asteroid/test-suites/action-tests/test078.ast
@@ -26,7 +26,7 @@
       io @println "".
       for r in m do
           for e in r do
-              io @print (e + " ").
+              io @print (tostring e + " ").
           end
           io @println ("").
       end
diff --git a/asteroid/test-suites/action-tests/test080.ast b/asteroid/test-suites/action-tests/test080.ast
index d5a245c8..0608e4bc 100644
--- a/asteroid/test-suites/action-tests/test080.ast
+++ b/asteroid/test-suites/action-tests/test080.ast
@@ -18,7 +18,7 @@
 
   let color_hash = hash @hash().
   for (_,color) in fruit_lst do
-      if not color_hash @get(color) do
+      if color_hash @get(color) is none do
           color_hash @insert(color,1).
       else
           color_hash @insert(color, color_hash @get(color) +1).
diff --git a/asteroid/test-suites/action-tests/test081.ast b/asteroid/test-suites/action-tests/test081.ast
index 403b2f71..30050235 100644
--- a/asteroid/test-suites/action-tests/test081.ast
+++ b/asteroid/test-suites/action-tests/test081.ast
@@ -1,12 +1,11 @@
   load system io.
-  load system type.
 
   function format with v do
       let maxlen = 3.
-      let vstr = type @tostring v.
-      return [1 to maxlen-len(vstr)] @map(lambda with _ do return " ") @join("") + vstr.
+      let vstr = tostring v.
+      return [1 to maxlen-len(vstr)] @map(lambda with _ do " ") @join("") + vstr.
   end
 
   for i in 1 to 10 do
-      io @println ([1 to 10] @map(lambda with x do return format(i*x)) @join(" ")).
+      io @println ([1 to 10] @map(lambda with x do format(i*x)) @join(" ")).
   end
diff --git a/asteroid/test-suites/action-tests/test082.ast b/asteroid/test-suites/action-tests/test082.ast
index 009dcdb9..218ce827 100644
--- a/asteroid/test-suites/action-tests/test082.ast
+++ b/asteroid/test-suites/action-tests/test082.ast
@@ -1,7 +1,6 @@
   load system io.
   load system vector.
   load system util.
-  load system type.
 
   let triangle = [[1]].
   let ix = 0.
@@ -16,5 +15,5 @@
   end
 
   for r in triangle do
-      io @println (r @map(lambda with v do return type @tostring v) @join(" ")).
+      io @println (r @map(lambda with v do tostring v) @join(" ")).
   end
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test001.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test001.ast
deleted file mode 100644
index fdb8f4b5..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test001.ast
+++ /dev/null
@@ -1,41 +0,0 @@
-
---------------------------------------
--- patterns_test0.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
--- By Timothy Colaneri
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with x.
-let ptrn2 = pattern with ( 1, 2, z).
-let ptrn3 = pattern with ( 1, y, z).
-let ptrn4 = pattern with ( x, y, z).
-
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do         --will SUBSUME all other patterns
-        return 0.
-    with *ptrn2 do
-        return 1.
-    with *ptrn3 do
-        return 2.
-    with *ptrn4 do
-        return 3.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 1 , 2 , 3 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test002.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test002.ast
deleted file mode 100644
index 4aca597a..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test002.ast
+++ /dev/null
@@ -1,36 +0,0 @@
-
---------------------------------------
--- patterns_test1.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with ( 1, value1, value2).
-let ptrn2 = pattern with ( 1, y, z).
-let ptrn3 = pattern with ( x, y, z).
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do --will SUBSUME ( 1, y, z)
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do
-        return 3.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 1 , 2 , 3 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test003.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test003.ast
deleted file mode 100644
index b8d7a07e..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test003.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
---------------------------------------
--- patterns_test2.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with 1.
-let ptrn2 = pattern with 2.
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do --will SUBSUME 1 
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with 1 do
-        return 3.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 1 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test004.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test004.ast
deleted file mode 100644
index 6beefa2e..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test004.ast
+++ /dev/null
@@ -1,38 +0,0 @@
-
---------------------------------------
--- patterns_test3.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with ( 1, 2, 3).
-let ptrn2 = pattern with ( 1, 2, ( x1, "test_string" ) ).
-let ptrn3 = pattern with ( 1, 2, ( var, "test_string" ) ).
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do 
-        return 1.
-    with *ptrn2 do --will SUBSUME ( 1, 2, ( var,"test_string"))
-        return 2.
-    with ( x, y, z) do
-        return 3.
-    with *ptrn3 do
-        return 3
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 1 , 2 , 3 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test005.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test005.ast
deleted file mode 100644
index 4e7b5e88..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test005.ast
+++ /dev/null
@@ -1,33 +0,0 @@
-
---------------------------------------
--- patterns_test4.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- let ptrn1 = pattern with ( x, y, z).
-let ptrn2 = pattern with ( (x1,y1), (x2,y2), (x3,y3) ).
-
--- A testing function with multiple patterns
-function testFunction
-    with ( x, y, z) do  -- *** will SUBSUME ( (x,y), (x,y), (x,y) ) ***
-        return 1.
-    with *ptrn2 do 
-        return 2.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 1 , 2 , 3 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test006.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test006.ast
deleted file mode 100644
index 8b40532b..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test006.ast
+++ /dev/null
@@ -1,39 +0,0 @@
-
---------------------------------------
--- patterns_test5.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with "name1".
-let ptrn2 = pattern with "name2".
-let ptrn3 = pattern with "name2".
-let ptrn4 = pattern with "name4".
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  
-        return 1.
-    with *ptrn2 do   -- *** will SUBSUME "name2" ***
-        return 2.
-    with *ptrn3 do   -- duplicate pattern
-        return 2.
-    with *ptrn4 do 
-        return 2.
-    end.
-        
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( "name4" ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test008.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test008.ast
deleted file mode 100644
index 3f2c3b09..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test008.ast
+++ /dev/null
@@ -1,41 +0,0 @@
-
---------------------------------------
--- patterns_test7.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with 1.1.
-let ptrn2 = pattern with 1.2.
-let ptrn3 = pattern with 1.3.
-let ptrn4 = pattern with 1.1.
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do       -- *** will subsume 1.1 
-        return 1. 
-    with *ptrn2 do 
-        return 2.
-    with *ptrn3 do 
-        return 3.
-    with *ptrn4 do     -- *** duplicate pattern
-        return 4.     
-    end.
-    
-
-try
-    -- Evaluate the function with a test input.
-    let x = 1.1.
-    let y = testFunction( x ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + y ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test009.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test009.ast
deleted file mode 100644
index 7044b22c..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test009.ast
+++ /dev/null
@@ -1,38 +0,0 @@
-
---------------------------------------
--- patterns_test8.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with 1.10.
-let ptrn2 = pattern with 1.10000.
-
--- A testing function with multiple patterns
-function testFunction
-    with 1.10 do       -- *** will subsume 1.10000...
-        return 1. 
-    with 1.2 do 
-        return 2.
-    with 1.3 do 
-        return 3.
-    with *ptrn2 do   -- *** duplicate pattern 1.10
-        return 4.     
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = 1.1.
-    let y = testFunction( x ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + y ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test010.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test010.ast
deleted file mode 100644
index 4839ba30..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test010.ast
+++ /dev/null
@@ -1,36 +0,0 @@
-
---------------------------------------
--- patterns_test9.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with false.
-
--- A testing function with multiple patterns
-function testFunction
-    with true do       
-        return 1. 
-    with *ptrn1 do -- *** will subsume false
-        return 2.    
-    with false do -- *** duplicate pattern
-        return 2.  
-    end.
-    
-try
-
-    -- Evaluate the function with a test input.
-    let x = true.
-    let y = testFunction( x ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + y ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test011.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test011.ast
deleted file mode 100644
index c94207bd..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test011.ast
+++ /dev/null
@@ -1,33 +0,0 @@
-
---------------------------------------
--- patterns_test10.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with ".*p.*".
-
-function test_function 
-  with *ptrn1 do               -- RE ".*p.*"will match to all ".*http.*" and ".*https.*"
-    return "Found a p.".
-  with ".*http.*" do          --Redundant
-    return "Found a url.".
-  with ".*https.*" do         --Redundant
-    return "Found a secure url.".
-  with ".*z.*" do
-    return "Found a z.".
-  end.
-
-try
-
-  let var = test_function( "test string z" ).
-  io @println ( var ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test012.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test012.ast
deleted file mode 100644
index 9a28752e..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test012.ast
+++ /dev/null
@@ -1,36 +0,0 @@
-
---------------------------------------
--- patterns_test11.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with ".*q.*".
-let ptrn2 = pattern with ".*http.*".
-let ptrn3 = pattern with ".*https.*".
-let ptrn4 = pattern with ".*z.*".
-
-function test_function 
-  with *ptrn1 do               
-    return "Found a q.".
-  with *ptrn2 do          -- RE ".*http.*" will match to all ".*https.*" patterns
-    return "Found a url.".
-  with *ptrn3 do         --Redundant
-    return "Found a secure url.".
-  with *ptrn4 do
-    return "Found a z.".
-  end.
-
-try
-
-  let var = test_function( "test string z" ).
-  io @println ( var ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test013.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test013.ast
deleted file mode 100644
index ffe14da6..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test013.ast
+++ /dev/null
@@ -1,33 +0,0 @@
-
---------------------------------------
--- patterns_test12.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with [ x, y ].
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME [ 1, 2 ] ***
-        return 1.
-    with [ 1, 2 ] do 
-        return 2.
-    end.
-
-
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test014.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test014.ast
deleted file mode 100644
index 799ee34d..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test014.ast
+++ /dev/null
@@ -1,37 +0,0 @@
-
---------------------------------------
--- patterns_test13.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
--- By Timothy Colaneri
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with [ x , y].
-let ptrn2 = pattern with [ head | tail ].
-let ptrn3 = pattern with [ a, b, c, d ].
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  
-        return 1.
-    with *ptrn2 do  -- *** will SUBSUME [ a, b, c, d ] ***
-        return 2.
-    with *ptrn3 do 
-        return 3.    
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test015.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test015.ast
deleted file mode 100644
index fa54d6b4..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test015.ast
+++ /dev/null
@@ -1,36 +0,0 @@
-
---------------------------------------
--- patterns_test14.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with [ h1 | h2 | h3 |  tail ].
-let ptrn2 = pattern with [ h1 | h2 | h3 | h4 | tail ].
-let ptrn3 = pattern with [ h1 | tail ].
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME [ h1 | h2 | h3 | h4 | tail ] ***
-        return 1.
-    with *ptrn2 do
-        return 2. 
-    with *ptrn3 do -- ** will not catch ** can still make matches others can't! ex. [ 1, 2]
-        return 3. 
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test016.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test016.ast
deleted file mode 100644
index 27244a5a..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test016.ast
+++ /dev/null
@@ -1,39 +0,0 @@
-
---------------------------------------
--- patterns_test15.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with [ 1 | 2 | 3 | 4 | tail ].
-let ptrn2 = pattern with [ 1, 2, 3, 4 ].
-let ptrn3 = pattern with [ h1 | tail ].
-let ptrn4 = pattern with [].
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME [1, 2, 3, 4 ] ***
-        return 1.
-    with *ptrn2 do
-        return 2. 
-    with *ptrn3 do 
-        return 3. 
-    with *ptrn4 do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test017.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test017.ast
deleted file mode 100644
index d059bbce..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test017.ast
+++ /dev/null
@@ -1,38 +0,0 @@
---------------------------------------
--- patterns_test16.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with person1:( fname, lname).
-let ptrn2 = pattern with person2:( fname, lname1, lname2).
-let ptrn3 = pattern with location:( long, lat ).
-let ptrn4 = pattern with ().
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME location:( long, lat ) ***
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do 
-        return 3. 
-    with *ptrn4 do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( 3 , 4 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test018.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test018.ast
deleted file mode 100644
index 2061a3b5..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test018.ast
+++ /dev/null
@@ -1,38 +0,0 @@
---------------------------------------
--- patterns_test17.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with person1:( fname, lname).
-let ptrn2 = pattern with person2:( fname, lname1, lname2).
-let ptrn3 = pattern with (x,y).
-let ptrn4 = pattern with ().
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME (x, y) ***
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do 
-        return 3. 
-    with *ptrn4 do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( 3 , 4 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test019.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test019.ast
deleted file mode 100644
index 07ac60ad..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test019.ast
+++ /dev/null
@@ -1,35 +0,0 @@
---------------------------------------
--- patterns_test18.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with ( fname, lname).
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME (x, y) ***
-        return 1.
-    with person2:( fname, lname1, lname2) do
-        return 2.
-    with coord:( x, y ) do 
-        return 3. 
-    with () do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( 3 , 4 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test020.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test020.ast
deleted file mode 100644
index 674a1a10..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test020.ast
+++ /dev/null
@@ -1,37 +0,0 @@
---------------------------------------
--- patterns_test19.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with person:[( fname, lname)| tail].
-let ptrn2 = pattern with person:( fname, lname1, lname2).
-let ptrn3 = pattern with person:[( fname1, lname1)|( fname2, lname2)| tail].
-
--- A testing function with multiple patterns
-function testFunction
-    with *ptrn1 do  -- *** will SUBSUME [( fname1, lname1)|( fname2, lname2)| tail] ***
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do 
-        return 3. 
-    with () do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction[ ("test","name") ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test021.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test021.ast
deleted file mode 100644
index d288b323..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test021.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
---------------------------------------
--- patterns_test20.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with 0.
-let ptrn2 = pattern with (n:%integer).
-let ptrn3 = pattern with (n:%integer).
-
-function fact
-    with *ptrn1 do
-        return 1
-    with *ptrn2 do   -- Will subsume pattern (n:%integer)
-        return n * fact (n-1).
-    with *ptrn3 do
-        throw Error("factorial is not defined for "+n).
-    end.
-     
-try 
-    -- Evaluate the function with a test input.
-    let x = fact( 5 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test022.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test022.ast
deleted file mode 100644
index c72d3ef9..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test022.ast
+++ /dev/null
@@ -1,38 +0,0 @@
-
---------------------------------------
--- patterns_test21.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with 0.
-let ptrn2 = pattern with (x:%integer, y:%integer ).
-let ptrn3 = pattern with (n:%integer, m:%real).
-let ptrn4 = pattern with (value1:%integer, value2:%real).
-
-function testFunction
-    with *ptrn1 do
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do   -- Will Subsume (value1:%integer, value2:%real)
-        return 3.
-    with *ptrn4 do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( 5,1 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test023.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test023.ast
deleted file mode 100644
index 8a25b2fd..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test023.ast
+++ /dev/null
@@ -1,38 +0,0 @@
-
---------------------------------------
--- patterns_test22.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with 0.
-let ptrn2 = pattern with ( var1 , var2 ).
-let ptrn3 = pattern with (x:%integer, y:%integer ).
-let ptrn4 = pattern with (n:%real, m:%real).
-
-function testFunction
-    with *ptrn1 do
-        return 1.
-    with *ptrn2 do          -- Will leave all following patterns redundant
-        return -1.
-    with *ptrn3 do
-        return 2.
-    with *ptrn4 do
-        return 3.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( 5,1 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test024.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test024.ast
deleted file mode 100644
index 5bdfae58..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test024.ast
+++ /dev/null
@@ -1,39 +0,0 @@
-
---------------------------------------
--- patterns_test23.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with x:%tuple.
-let ptrn2 = pattern with (x:%integer, y:%integer ).
-let ptrn3 = pattern with (n:%real, m:%real).
-let ptrn4 = pattern with ( x, y, z).
-
-function testFunction
-    with *ptrn1 do                   -- Will render all following patterns redundant
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do
-        return 3.
-    with *ptrn4 do
-        return 4.
-    end.
-    
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( (5,1) ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test025.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test025.ast
deleted file mode 100644
index 0bb71365..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test025.ast
+++ /dev/null
@@ -1,34 +0,0 @@
---------------------------------------
--- patterns_test24.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-let ptrn1 = pattern with [ head1 | head2 | tail ].
-
-function testFunction
-    with x:%list do    -- Will match everything intended for [ head1 | head2 | tail ]
-        return 1.
-    with (x:%integer, y:%integer ) do
-        return 2.
-    with (n:%real, m:%real) do
-        return 3.
-    with *ptrn1 do
-        return 4.
-    end.
-    
-try 
-    -- Evaluate the function with a test input.
-    let x = testFunction( (5,1) ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test026.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test026.ast
deleted file mode 100644
index 20dd5e1f..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test026.ast
+++ /dev/null
@@ -1,46 +0,0 @@
-
---------------------------------------
--- patterns_test25.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-structure Person with
-    data name.
-    data age.
-    data gender.
-    end
-
--- define a list of persons
-let people = [
-    Person("George", 32, "M"),
-    Person("Sophie", 46, "F"),
-    Person("Oliver", 21, "X")
-    ].
-
-let ptrn1 = pattern with Person("George", 32, "M").
-let ptrn2 = pattern with Person("Sophie", 46, "F").
-let ptrn3 = pattern with Person("George", 32, "M").
-  
-function testFunction
-    with *ptrn1 do    -- *** will Subsume Person("George", 32, "M")
-        return 1.
-    with *ptrn2 do
-        return 2.
-    with *ptrn3 do  --duplicate structure/object
-        return 3.
-    end.
-
-try 
-    
-    let x = testFunction( Person("George", 32, "M") ).
-    io @println ( x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test027.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test027.ast
deleted file mode 100644
index 302b05e3..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test027.ast
+++ /dev/null
@@ -1,44 +0,0 @@
-
---------------------------------------
--- patterns_test26.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
--- implements Peano addition on terms
-load system io.
-load "util".
-
-structure S with
-    data x.
-    end 
-    
-structure add with
-    data left.
-    data right.
-    end
-
-let ptrn1 = pattern with add(x,0).
-let ptrn2 = pattern with add(x,y).
-let ptrn3 = pattern with add(x,S(y)).
-let ptrn4 = pattern with term.
-
-function reduce
-    with *ptrn1 do              -- Will subsume all matches for add(x,S(y))
-        return 1.
-    with *ptrn2 do      
-        return reduce(x).
-    with *ptrn3 do         -- The redundant pattern
-        return S(reduce(add(x,y))).
-    with *ptrn4 do     
-        return term.
-    end 
-
-try      
-    io @println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test028.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test028.ast
deleted file mode 100644
index 53dd6fe3..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test028.ast
+++ /dev/null
@@ -1,47 +0,0 @@
-
---------------------------------------
--- patterns_test27.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-structure Dog
-  with
-    data name.
-    data tricks.
-
-    function __init__
-      with *ptrn1 do -- Will subsume all matches for (self, name, [])
-        let this@name = name.
-        let this@tricks = tricks.
-      with *ptrn2 do  -- Redundant Constructor 
-        let this@name = name.
-        let this@tricks = [].
-      with *ptrn3 do
-        let this@name = name.
-        let this@tricks = [].
-      end
-
-    function add_trick
-      with new_trick do
-        let this@tricks = this@tricks + [new_trick].
-      end
-  end
-
-let ptrn1 = pattern with (name, tricks).
-let ptrn2 = pattern with (name, []).
-let ptrn3 = pattern with name.
-
-try      
-    
-  -- Fido the dog
-  let fido = Dog("Fido").
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/test029.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test029.ast
deleted file mode 100644
index c37d2419..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/test029.ast
+++ /dev/null
@@ -1,54 +0,0 @@
-
---------------------------------------
--- patterns_test28.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-structure Person with
-    data name.
-    data age.
-    data gender.
-    end
-
--- define a list of persons
-let people = [
-    Person("George", 32, "M"),
-    Person("Sophie", 46, "F"),
-    Person("Oliver", 21, "X")
-    ].
-
-function test_function 
-  with *ptrn1 do
-    return "Found a p.".
-  with *ptrn2 do   -- *** The regular expression ".*g.*" will subsume ".*gg.*"
-    return "Found a g.".
-  with *ptrn3 do
-    return "Found a v.".
-  with *ptrn4 do  -- will be redundant
-    return "Found a gg.".
-  end.
-  
-let ptrn1 = pattern with Person(name:".*p.*",_,_).
-let ptrn2 = pattern with Person(name:".*g.*",_,_).
-let ptrn3 = pattern with Person(name:".*v.*",_,_).
-let ptrn4 = pattern with Person(name:".*gg.*",_,_).
-
-let loopCounter = 0.
-
--- print names that contain 'p'
-for Person(_,_,_) in people do
-  try
-    io @println (test_function( people @loopCounter )).
-  catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-  catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-  end.
-  let loopCounter = loopCounter + 1.
-end.
-
diff --git a/asteroid/programs/boom.ast b/asteroid/test-suites/programs/boom.ast
similarity index 100%
rename from asteroid/programs/boom.ast
rename to asteroid/test-suites/programs/boom.ast
diff --git a/asteroid/test-suites/programs/calc-io.txt b/asteroid/test-suites/programs/calc-io.txt
new file mode 100644
index 00000000..ab856ee1
--- /dev/null
+++ b/asteroid/test-suites/programs/calc-io.txt
@@ -0,0 +1,1 @@
+(2+3)*2
diff --git a/asteroid/programs/calc/calc.ast b/asteroid/test-suites/programs/calc.ast
similarity index 70%
rename from asteroid/programs/calc/calc.ast
rename to asteroid/test-suites/programs/calc.ast
index bffac692..5fd0aa4a 100644
--- a/asteroid/programs/calc/calc.ast
+++ b/asteroid/test-suites/programs/calc.ast
@@ -7,7 +7,8 @@
 -- Lutz Hamel, (c) University of Rhode Island
 
 load system io.
-load "lexer".
+load tokenizer.
+load lexer.
 
 -------------------------------------------------------------------------
 -- A recursive descent parser implementing the following grammar:
@@ -17,34 +18,34 @@ load "lexer".
 -- The parser implements arithmetic on integer values
 
 function expression
-  with lexer:%Lexer do
-    let val = mulexp(lexer).
+  with lex do
+    let val = mulexp(lex).
     loop do
-      let token = lexer @peek().
-      if not token do
+      let token = lex @peek().
+      if isnone token do
         break.
       elif token @type == "add" do
-        lexer @token_match("add").
-        let val = val + mulexp(lexer).
+        lex @token_match("add").
+        let val = val + mulexp(lex).
       elif token @type == "sub" do
-        lexer @token_match("sub").
-        let val = val - mulexp(lexer)
+        lex @token_match("sub").
+        let val = val - mulexp(lex)
       else do
         break.
       end
     end
     return val.
-  end
+end
 
 function mulexp
-  with lexer:%Lexer do
+  with lexer do
     let val = rootexp(lexer).
-    if not lexer @peek() do
+    if isnone (lexer @peek()) do
       return val.
     end
     loop do
       let token = lexer @peek().
-      if not token do
+      if isnone token do
         break.
       elif token @type == "mul" do
         lexer @token_match("mul").
@@ -57,15 +58,11 @@ function mulexp
       end
     end
     return val.
-  end
+end
 
 function rootexp
-  with lexer:%Lexer do
-    try
-      let Token(type,val) = lexer @peek().
-    catch _ do
-      return none.
-    end
+  with lexer do
+    let tokenizer @Token(type,val) = lexer @peek().
     if type == "number" do
       lexer @token_match("number").
       return val.
@@ -80,21 +77,23 @@ function rootexp
     else do
       throw Error("syntax error at token "+val).
     end
-  end
+end
 
 -------------------------------------------------------------------------
 -- driver part of the script
+if toplevel () do
+  -- tokenize input
+  let input = io @read().
+  let lexer = lexer @Lexer input.
+  #println lexer.
 
--- tokenize input
-let input = io @read().
-let lexer = Lexer(tokenize(input)).
-#println lexer.
+  -- parse and interpret input
+  let val = expression(lexer).
+    io @println val.
+  if not (lexer @eof()) do
+    throw Error("tokens still in input stream")
+  end
 
--- parse and interpret input
-let val = expression(lexer).
-if not (lexer @eof()) do
-  throw Error("tokens still in input stream")
+  -- print out the final value of the parsed and interpreted expression
+  io @println val.
 end
-
--- print out the final value of the parsed and interpreted expression
-io @println val.
diff --git a/asteroid/test-suites/programs/cls.ast b/asteroid/test-suites/programs/cls.ast
new file mode 100755
index 00000000..ebd0108a
--- /dev/null
+++ b/asteroid/test-suites/programs/cls.ast
@@ -0,0 +1,11 @@
+#!/usr/bin/env asteroid
+load system io.
+load system util.
+load system random.
+
+util @cls().
+
+for i in 1 to 3 do
+    io @println ("Random value " + tostring(random@random())).
+    util @sleep 0.5
+end
diff --git a/asteroid/programs/dogs.ast b/asteroid/test-suites/programs/dogs.ast
similarity index 90%
rename from asteroid/programs/dogs.ast
rename to asteroid/test-suites/programs/dogs.ast
index 0b81cf4b..89e524d1 100644
--- a/asteroid/programs/dogs.ast
+++ b/asteroid/test-suites/programs/dogs.ast
@@ -1,5 +1,4 @@
 load system io.
-load system type.
 
 structure Dog with
   data name.
@@ -14,7 +13,7 @@ let buddy = Dog ("Buddy",["sit stay","roll over"]).
 -- 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.*")]%.
+                          if tostring tricks is ".*fetch.*")]%.
 
 -- one way to do this
 for (Dog(name,tricks) if Dog(name,tricks) is *fetcher) in [fido,buddy] do
diff --git a/asteroid/programs/escape.ast b/asteroid/test-suites/programs/escape.ast
similarity index 100%
rename from asteroid/programs/escape.ast
rename to asteroid/test-suites/programs/escape.ast
diff --git a/asteroid/test-suites/programs/fact-io.txt b/asteroid/test-suites/programs/fact-io.txt
new file mode 100644
index 00000000..00750edc
--- /dev/null
+++ b/asteroid/test-suites/programs/fact-io.txt
@@ -0,0 +1,1 @@
+3
diff --git a/asteroid/programs/fact.ast b/asteroid/test-suites/programs/fact.ast
similarity index 77%
rename from asteroid/programs/fact.ast
rename to asteroid/test-suites/programs/fact.ast
index f4ed5dcd..55e24861 100644
--- a/asteroid/programs/fact.ast
+++ b/asteroid/test-suites/programs/fact.ast
@@ -4,7 +4,6 @@
 -- with type classes and conditional matching
 
 load system io.
-load system type.
 
 let POS_INT = pattern %[(x:%integer) if x > 0]%.
 let NEG_INT = pattern %[(x:%integer) if x < 0]%.
@@ -19,8 +18,8 @@ function fact
     end
 
 try
-  let i = type @tointeger(io @input "Enter an integer value: ").
-  io @println ("The factorial of "+i+" is: " + fact (i)).
+  let i = tointeger(io @input "Enter an integer value: ").
+  io @println ("The factorial of "+ tostring i +" is: " + tostring (fact i)).
 catch e do
   io @println e.
 end
diff --git a/asteroid/programs/formatted.ast b/asteroid/test-suites/programs/formatted.ast
similarity index 100%
rename from asteroid/programs/formatted.ast
rename to asteroid/test-suites/programs/formatted.ast
diff --git a/asteroid/test-suites/programs/guess-io.txt b/asteroid/test-suites/programs/guess-io.txt
new file mode 100644
index 00000000..f1ef7a1a
--- /dev/null
+++ b/asteroid/test-suites/programs/guess-io.txt
@@ -0,0 +1,5 @@
+Leo
+10
+5
+3
+4
diff --git a/asteroid/programs/guess.ast b/asteroid/test-suites/programs/guess.ast
similarity index 83%
rename from asteroid/programs/guess.ast
rename to asteroid/test-suites/programs/guess.ast
index 486a71c2..04a56266 100644
--- a/asteroid/programs/guess.ast
+++ b/asteroid/test-suites/programs/guess.ast
@@ -4,7 +4,6 @@
 load system io.
 load system util.
 load system random.
-load system type.
 
 random @seed 42. -- make it predictable
 
@@ -22,7 +21,7 @@ let number = random @randint (1, 20).
 io @println (name + ", I am thinking of a number between 1 and 20, can you guess it?").
 
 while guesses_made < 6 do
-    let guess = type @tointeger (io @input "Take a guess: ").
+    let guess = tointeger (io @input "Take a guess: ").
     let guesses_made = guesses_made + 1.
 
     if guess < number do
@@ -35,9 +34,9 @@ while guesses_made < 6 do
 end
 
 if guess == number do
-    io @println ("Good job, " + name + "! You guessed my number in " + guesses_made + " guesses!").
+    io @println ("Good job, " + name + "! You guessed my number in " + tostring guesses_made + " guesses!").
 else do
-    io @println ("Nope. The number I was thinking of was " + number).
+    io @println ("Nope. The number I was thinking of was " + tostring number).
 end
 
 io @println "".
diff --git a/asteroid/programs/hello.ast b/asteroid/test-suites/programs/hello.ast
similarity index 100%
rename from asteroid/programs/hello.ast
rename to asteroid/test-suites/programs/hello.ast
diff --git a/asteroid/programs/largest.ast b/asteroid/test-suites/programs/largest.ast
similarity index 82%
rename from asteroid/programs/largest.ast
rename to asteroid/test-suites/programs/largest.ast
index d269f804..57cade7d 100644
--- a/asteroid/programs/largest.ast
+++ b/asteroid/test-suites/programs/largest.ast
@@ -16,8 +16,8 @@ end
 
 let number_list = [34,50,25,100,65].
 let result = largest (number_list,lambda with (x,y) do x > y).
-io @println("The largest number is "+result).
+io @println("The largest number is " + tostring result).
 
 let char_list = ["y","m","a","q"].
 let result = largest (char_list,lambda with (x,y) do util @ascii x > util @ascii y).
-io @println("The largest charactor is "+result).
+io @println("The largest charactor is " + tostring result).
diff --git a/asteroid/programs/calc/lexer.ast b/asteroid/test-suites/programs/lexer.ast
similarity index 73%
rename from asteroid/programs/calc/lexer.ast
rename to asteroid/test-suites/programs/lexer.ast
index 15fc5c7e..16abcdf7 100644
--- a/asteroid/programs/calc/lexer.ast
+++ b/asteroid/test-suites/programs/lexer.ast
@@ -2,25 +2,29 @@
 -- tokenize function.
 -- Lutz Hamel, (c) University of Rhode Island
 
-load "tokenizer".
+load tokenizer.
 
 structure Lexer with
   data token_stream.
 
+  function __init__ with input:%string do
+    let this@token_stream = tokenizer @tokenize input.
+  end
+
   function get
     with none do
       return this @token_stream @get().
-    end
+  end
 
   function peek
     with none do
       return this @token_stream @peek().
-    end
+  end
 
   function eof
     with none do
       return this @token_stream @eof().
-    end
+  end
 
   function token_match
     with token_type do
@@ -30,6 +34,12 @@ structure Lexer with
       else do
         throw Error("expected token "+token_type+" got "+token @type).
       end
-    end
+  end
 
 end -- structure
+
+if toplevel() do
+  load system io.
+  let lex = Lexer("1+1").
+  io @println (lex @token_stream).
+end
diff --git a/asteroid/programs/life.ast b/asteroid/test-suites/programs/life.ast
similarity index 98%
rename from asteroid/programs/life.ast
rename to asteroid/test-suites/programs/life.ast
index d4f55b9c..552877ac 100644
--- a/asteroid/programs/life.ast
+++ b/asteroid/test-suites/programs/life.ast
@@ -136,7 +136,7 @@ function life
         for gen in 0 to (maxgen-1) do
             compute_new_state(map1, map2).
             util @cls().
-            io @println("map @ generation " + gen).
+            io @println("map @ generation " + tostring gen).
             show_map(map2).
             -- implement double buffering
             let (map1,map2) = (map2,map1). -- swap the maps
diff --git a/asteroid/programs/names.csv b/asteroid/test-suites/programs/names.csv
similarity index 100%
rename from asteroid/programs/names.csv
rename to asteroid/test-suites/programs/names.csv
diff --git a/asteroid/programs/people.ast b/asteroid/test-suites/programs/people.ast
similarity index 100%
rename from asteroid/programs/people.ast
rename to asteroid/test-suites/programs/people.ast
diff --git a/asteroid/programs/qsort.ast b/asteroid/test-suites/programs/qsort.ast
similarity index 100%
rename from asteroid/programs/qsort.ast
rename to asteroid/test-suites/programs/qsort.ast
diff --git a/asteroid/programs/simple.ast b/asteroid/test-suites/programs/simple.ast
similarity index 100%
rename from asteroid/programs/simple.ast
rename to asteroid/test-suites/programs/simple.ast
diff --git a/asteroid/programs/stream.ast b/asteroid/test-suites/programs/stream.ast
similarity index 88%
rename from asteroid/programs/stream.ast
rename to asteroid/test-suites/programs/stream.ast
index fc493fef..7aa2b232 100644
--- a/asteroid/programs/stream.ast
+++ b/asteroid/test-suites/programs/stream.ast
@@ -15,4 +15,4 @@ while not s @eof() do
 end
 s @rewind().
 
-io @println(s @__string__()).
+io @println s.
diff --git a/asteroid/programs/teams.ast b/asteroid/test-suites/programs/teams.ast
similarity index 86%
rename from asteroid/programs/teams.ast
rename to asteroid/test-suites/programs/teams.ast
index 885617ed..0388bd4f 100644
--- a/asteroid/programs/teams.ast
+++ b/asteroid/test-suites/programs/teams.ast
@@ -7,7 +7,7 @@ load system dataframe.
 
 -- team participants
 let df = dataframe @dataframe().
-df @read_csv("names.csv",true).
+df @read_csv("programs/names.csv",true).
 let names = df @col(0).
 
 -- shuffle names
@@ -26,7 +26,7 @@ until names is [].
 
 -- print teams
 for (i,team) in util @zip(1 to len(teams),teams) do
-  let team_str = "team " + i + (":  " if i < 10 else ": ").
+  let team_str = "team " + tostring i + (":  " if i < 10 else ": ").
   repeat do
     let [name|team] = team.
     let team_str = team_str + name + ("" if team is [] else ", ").
diff --git a/asteroid/programs/test_hash.ast b/asteroid/test-suites/programs/test_hash.ast
similarity index 100%
rename from asteroid/programs/test_hash.ast
rename to asteroid/test-suites/programs/test_hash.ast
diff --git a/asteroid/programs/calc/tokenizer.ast b/asteroid/test-suites/programs/tokenizer.ast
similarity index 88%
rename from asteroid/programs/calc/tokenizer.ast
rename to asteroid/test-suites/programs/tokenizer.ast
index a30879b5..90bf8e1e 100644
--- a/asteroid/programs/calc/tokenizer.ast
+++ b/asteroid/test-suites/programs/tokenizer.ast
@@ -4,13 +4,12 @@
 -- how regular expression can be used during pattern matching.
 -- Lutz Hamel, (c) University of Rhode Island
 
-load system type.
 load system stream.
 
 structure Token with
   data type.
   data value.
-  end
+end
 
 function get_number
   with input_stream do
@@ -18,8 +17,8 @@ function get_number
     while input_stream @peek() is "[0-9]" do
       let number = number + input_stream @get().
     end
-    return type @tointeger(number).
-  end
+    return tointeger(number).
+end
 
 function tokenize
   with input:%string do
@@ -64,8 +63,10 @@ function tokenize
     return output_stream.
   end
 
--- test harness for tokenizer
--- load system io.
--- let output_stream = tokenize("(101+1)*2").
--- let output_stream = tokenize("101").
--- println (output_stream @__string__()).
+if toplevel() do
+  -- test harness for tokenizer
+  load system io.
+  let output_stream = tokenize("(101+1)*2").
+  let output_stream = tokenize("101").
+  io @ println (tostring output_stream).
+end
diff --git a/asteroid/test-suites/redundant-pattern-test/test001.ast b/asteroid/test-suites/redundant-pattern-test/test001.ast
index ddfc98a9..df81f608 100644
--- a/asteroid/test-suites/redundant-pattern-test/test001.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test001.ast
@@ -24,10 +24,8 @@ function testFunction
 try
     -- Evaluate the function with a test input.
     let x = testFunction( 1 , 2 , 3 ).
-    io @println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + tostring x ).
+    throw Error("Fail: subsumption not detected")
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test002.ast b/asteroid/test-suites/redundant-pattern-test/test002.ast
index f23edb60..b026674e 100644
--- a/asteroid/test-suites/redundant-pattern-test/test002.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test002.ast
@@ -25,11 +25,9 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + tostring x ).
+    throw Error("Fail: subsumption not detected")
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
 
diff --git a/asteroid/test-suites/redundant-pattern-test/test003.ast b/asteroid/test-suites/redundant-pattern-test/test003.ast
index 5dc40885..a144830d 100644
--- a/asteroid/test-suites/redundant-pattern-test/test003.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test003.ast
@@ -23,10 +23,9 @@ try
     let x = testFunction( 1 ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + tostring x ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test004.ast b/asteroid/test-suites/redundant-pattern-test/test004.ast
index 8ff5a315..45beab9c 100644
--- a/asteroid/test-suites/redundant-pattern-test/test004.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test004.ast
@@ -26,10 +26,9 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + tostring x ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test005.ast b/asteroid/test-suites/redundant-pattern-test/test005.ast
index 1f15728a..8d793dd3 100644
--- a/asteroid/test-suites/redundant-pattern-test/test005.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test005.ast
@@ -21,10 +21,9 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + tostring x ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test006.ast b/asteroid/test-suites/redundant-pattern-test/test006.ast
index 90a3ecd4..ecdff5cb 100644
--- a/asteroid/test-suites/redundant-pattern-test/test006.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test006.ast
@@ -25,10 +25,9 @@ try
     let x = testFunction( "name4" ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + tostring x ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test008.ast b/asteroid/test-suites/redundant-pattern-test/test008.ast
index 0127b9f0..e7c91f2b 100644
--- a/asteroid/test-suites/redundant-pattern-test/test008.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test008.ast
@@ -27,10 +27,9 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + tostring y ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test009.ast b/asteroid/test-suites/redundant-pattern-test/test009.ast
index faeb6e2b..1d2a468d 100644
--- a/asteroid/test-suites/redundant-pattern-test/test009.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test009.ast
@@ -26,10 +26,9 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + tostring y ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test010.ast b/asteroid/test-suites/redundant-pattern-test/test010.ast
index 0ce788d3..f8033c1e 100644
--- a/asteroid/test-suites/redundant-pattern-test/test010.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test010.ast
@@ -24,10 +24,9 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + tostring y ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test011.ast b/asteroid/test-suites/redundant-pattern-test/test011.ast
index 1c02d54a..bd6247a1 100644
--- a/asteroid/test-suites/redundant-pattern-test/test011.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test011.ast
@@ -23,9 +23,8 @@ try
     
     let var = test_function( "test string z" ).
     io @println ( var ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test012.ast b/asteroid/test-suites/redundant-pattern-test/test012.ast
index 6dbf2448..80ac90ae 100644
--- a/asteroid/test-suites/redundant-pattern-test/test012.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test012.ast
@@ -23,9 +23,8 @@ try
     
   let var = test_function( "test string z" ).
   io @println ( var ).
+  throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test013.ast b/asteroid/test-suites/redundant-pattern-test/test013.ast
deleted file mode 100644
index f65e685c..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test013.ast
+++ /dev/null
@@ -1,31 +0,0 @@
-
---------------------------------------
--- patterns_test12.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with [ x, y ] do  -- *** will SUBSUME [ 1, 2 ] ***
-        return 1.
-    with [ 1, 2 ] do 
-        return 2.
-    end.
-
-try
-    
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test014.ast b/asteroid/test-suites/redundant-pattern-test/test014.ast
deleted file mode 100644
index 0a086e33..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test014.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
---------------------------------------
--- patterns_test13.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
--- By Timothy Colaneri
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with [ x, y ] do  
-        return 1.
-    with [ head | tail ] do  -- *** will SUBSUME [ a, b, c, d ] ***
-        return 2.
-    with [ a, b, c, d ] do 
-        return 3.    
-    end.
-    
-
-try
-    
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test015.ast b/asteroid/test-suites/redundant-pattern-test/test015.ast
deleted file mode 100644
index e79d08f3..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test015.ast
+++ /dev/null
@@ -1,32 +0,0 @@
-
---------------------------------------
--- patterns_test14.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with [ h1 | h2 | h3 |  tail ] do  -- *** will SUBSUME [ h1 | h2 | h3 | h4 | tail ] ***
-        return 1.
-    with [ h1 | h2 | h3 | h4 | tail ] do
-        return 2. 
-    with [ h1 | tail ] do -- ** will not catch ** can still make matches others can't! ex. [ 1, 2]
-        return 3. 
-    end.
-
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test016.ast b/asteroid/test-suites/redundant-pattern-test/test016.ast
deleted file mode 100644
index 88759fd7..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test016.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
---------------------------------------
--- patterns_test15.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with [ 1 | 2 | 3 | 4 | tail ] do  -- *** will SUBSUME [1, 2, 3, 4 ] ***
-        return 1.
-    with [ 1, 2, 3, 4 ] do
-        return 2. 
-    with [ h1 | tail ] do 
-        return 3. 
-    with [] do
-        return 4.
-    end.
-
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction[ 3 , 4 ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test017.ast b/asteroid/test-suites/redundant-pattern-test/test017.ast
deleted file mode 100644
index 3ad7cf43..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test017.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
---------------------------------------
--- patterns_test16.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with person1:( fname, lname) do  -- *** will SUBSUME location:( long, lat ) ***
-        return 1.
-    with person2:( fname, lname1, lname2) do
-        return 2.
-    with location:( long, lat ) do 
-        return 3. 
-    with () do
-        return 4.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 3 , 4 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test018.ast b/asteroid/test-suites/redundant-pattern-test/test018.ast
deleted file mode 100644
index 03a7b092..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test018.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
---------------------------------------
--- patterns_test17.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with person1:( fname, lname) do  -- *** will SUBSUME (x, y) ***
-        return 1.
-    with person2:( fname, lname1, lname2) do
-        return 2.
-    with ( x, y ) do 
-        return 3. 
-    with () do
-        return 4.
-    end.
-    
-try
-    
-    -- Evaluate the function with a test input.
-    let x = testFunction( 3 , 4 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test019.ast b/asteroid/test-suites/redundant-pattern-test/test019.ast
deleted file mode 100644
index 9236d691..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test019.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
---------------------------------------
--- patterns_test18.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with ( fname, lname) do  -- *** will SUBSUME (x, y) ***
-        return 1.
-    with person2:( fname, lname1, lname2) do
-        return 2.
-    with coord:( x, y ) do 
-        return 3. 
-    with () do
-        return 4.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 3 , 4 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test020.ast b/asteroid/test-suites/redundant-pattern-test/test020.ast
deleted file mode 100644
index 2d6b98b6..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test020.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
---------------------------------------
--- patterns_test19.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
--- A testing function with multiple patterns
-function testFunction
-    with person:[( fname, lname)| tail] do  -- *** will SUBSUME [( fname1, lname1)|( fname2, lname2)| tail] ***
-        return 1.
-    with person:( fname, lname1, lname2) do
-        return 2.
-    with person:[( fname1, lname1)|( fname2, lname2)| tail] do 
-        return 3. 
-    with () do
-        return 4.
-    end.
-
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction[ ("test","name") ].
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ).
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test021.ast b/asteroid/test-suites/redundant-pattern-test/test021.ast
deleted file mode 100644
index 36a5a18b..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test021.ast
+++ /dev/null
@@ -1,33 +0,0 @@
-
---------------------------------------
--- patterns_test20.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-function fact
-    with 0 do
-        return 1
-    with (n:%integer) do   -- Will subsume pattern (n:%integer)
-        return n * fact (n-1).
-    with (n:%integer) do
-        throw Error("factorial is not defined for "+n).
-    end.
-
-try
-    
-    -- Evaluate the function with a test input.
-    let x = fact( 5 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x ). 
-
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test022.ast b/asteroid/test-suites/redundant-pattern-test/test022.ast
deleted file mode 100644
index 6d1ff98b..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test022.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
---------------------------------------
--- patterns_test21.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-function testFunction
-    with 0 do
-        return 1.
-    with (x:%integer, y:%integer ) do
-        return 2.
-    with (n:%integer, m:%real) do   -- Will Subsume (value1:%integer, value2:%real)
-        return 3.
-    with (value1:%integer, value2:%real) do
-        return 4.
-    end.
-
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 5,1 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ).
-
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test023.ast b/asteroid/test-suites/redundant-pattern-test/test023.ast
deleted file mode 100644
index 9a31dcd1..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test023.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
---------------------------------------
--- patterns_test22.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-function testFunction
-    with 0 do
-        return 1.
-    with ( var1 , var2 ) do          -- Will leave all following patterns redundant
-        return -1.
-    with (x:%integer, y:%integer ) do
-        return 2.
-    with (n:%real, m:%real) do
-        return 3.
-    end.
-    
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( 5,1 ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test024.ast b/asteroid/test-suites/redundant-pattern-test/test024.ast
deleted file mode 100644
index 2c6ebd41..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test024.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
---------------------------------------
--- patterns_test23.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-function testFunction
-    with x:%tuple do                   -- Will render all following patterns redundant
-        return 1.
-    with (x:%integer, y:%integer ) do
-        return 2.
-    with (n:%real, m:%real) do
-        return 3.
-    with ( x, y, z) do
-        return 4.
-    end.
-    
-
-try
-    -- Evaluate the function with a test input.
-    let x = testFunction( (5,1) ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-test/test025.ast b/asteroid/test-suites/redundant-pattern-test/test025.ast
deleted file mode 100644
index f16a04b8..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test025.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
---------------------------------------
--- patterns_test24.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-function testFunction
-    with x:%list do    -- Will match everything intended for [ head1 | head2 | tail ]
-        return 1.
-    with (x:%integer, y:%integer ) do
-        return 2.
-    with (n:%real, m:%real) do
-        return 3.
-    with [ head1 | head2 | tail ] do
-        return 4.
-    end.
-
-try
-        
-    -- Evaluate the function with a test input.
-    let x = testFunction( (5,1) ).
-
-    -- If the function test worked, print the output we got.
-    io @println( "The value returned is: " + x  ). 
-catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test026.ast b/asteroid/test-suites/redundant-pattern-test/test026.ast
index d5ae7057..7e2b687c 100644
--- a/asteroid/test-suites/redundant-pattern-test/test026.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test026.ast
@@ -38,10 +38,9 @@ function testFunction
 try    
     let x = testFunction( Person("George", 32, "M") ).
     io @println ( x ).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
 
diff --git a/asteroid/test-suites/redundant-pattern-test/test027.ast b/asteroid/test-suites/redundant-pattern-test/test027.ast
index b1eba2aa..1df2d0b3 100644
--- a/asteroid/test-suites/redundant-pattern-test/test027.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test027.ast
@@ -31,9 +31,8 @@ function reduce
     
 try    
     io @println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
+    throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test028.ast b/asteroid/test-suites/redundant-pattern-test/test028.ast
index 944c33bf..b4d094b5 100644
--- a/asteroid/test-suites/redundant-pattern-test/test028.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test028.ast
@@ -35,9 +35,8 @@ try
     
   -- Fido the dog
   let fido = Dog("Fido").
+  throw Error("Fail: subsumption not detected")
+
 catch Exception("RedundantPatternFound",s) do
     io @println("PASS.").
-catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-test/test029.ast b/asteroid/test-suites/redundant-pattern-test/test029.ast
deleted file mode 100644
index 97a44a28..00000000
--- a/asteroid/test-suites/redundant-pattern-test/test029.ast
+++ /dev/null
@@ -1,48 +0,0 @@
-
---------------------------------------
--- patterns_test28.ast
--- a simple program to test for
--- subsumption detection in Asteroid.
---------------------------------------
---------------------------------------
-load system io.
-load "util".
-
-structure Person with
-    data name.
-    data age.
-    data gender.
-    end
-
--- define a list of persons
-let people = [
-    Person("George", 32, "M"),
-    Person("Sophie", 46, "F"),
-    Person("Oliver", 21, "X")
-    ].
-
-function test_function 
-  with Person(name:".*p.*",_,_) do
-    return "Found a p.".
-  with Person(name:".*g.*",_,_) do   -- *** The regular expression ".*g.*" will subsume ".*gg.*"
-    return "Found a g.".
-  with Person(name:".*v.*",_,_) do
-    return "Found a v.".
-  with Person(name:".*gg.*",_,_) do  -- will be redundant
-    return "Found a gg.".
-  end.
-
-let loopCounter = 0.
-
--- print names that contain 'p'
-for Person(_,_,_) in people do
-  try
-    io @println (test_function( people @loopCounter )).
-  catch Exception("RedundantPatternFound",s) do
-    io @println("PASS.").
-  catch e do
-    io @println("FAIL.").
-    throw Error("FAIL: unexpected error "+e).
-  end.
-  let loopCounter = loopCounter + 1.
-end.
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/format.ast b/asteroid/test-suites/ref-programs/format.ast
index 98c5d197..2f5e6bd3 100644
--- a/asteroid/test-suites/ref-programs/format.ast
+++ b/asteroid/test-suites/ref-programs/format.ast
@@ -1,20 +1,19 @@
     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)).
+    let b = tostring(true,stringformat(10)).
     io @println b.
 
-    let i = type @tostring(5,type @stringformat(5)).
+    let i = tostring(5,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)).
+    let s = tostring("hello there!",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)).
+    let r = tostring(math@pi,stringformat(6,3)).
     io @println r.
diff --git a/asteroid/test-suites/ref-programs/io.ast b/asteroid/test-suites/ref-programs/io.ast
new file mode 100644
index 00000000..d96bf5b6
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/io.ast
@@ -0,0 +1,8 @@
+-- test module for test ref-programs/prgm-007.ast
+
+load system io.
+
+function output with a do
+   io @println a.
+end
+
diff --git a/asteroid/test-suites/ref-programs/math.ast b/asteroid/test-suites/ref-programs/math.ast
index ff4e64c2..bd419bb4 100644
--- a/asteroid/test-suites/ref-programs/math.ast
+++ b/asteroid/test-suites/ref-programs/math.ast
@@ -1,5 +1,5 @@
     load system io.
     load system math.
 
-    let x = math @sin( math @pi / 2 ).
-    io @println("The sine of pi / 2 is " + x + ".").
+    let x = math @sin( math @pi / 2.0 ).
+    io @println("The sine of pi / 2 is " + tostring x + ".").
diff --git a/asteroid/test-suites/ref-programs/patterns.ast b/asteroid/test-suites/ref-programs/patterns.ast
new file mode 100644
index 00000000..14c27b45
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/patterns.ast
@@ -0,0 +1,9 @@
+   load system patterns.
+
+   let evens = [].
+   for num in 1 to 10 do
+      if num is *patterns@even do
+         let evens = evens@append(num).
+      end
+   end
+   assert(evens is [2,4,6,8,10]).
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/pick.ast b/asteroid/test-suites/ref-programs/pick.ast
index 1ba8821b..2a48d130 100644
--- a/asteroid/test-suites/ref-programs/pick.ast
+++ b/asteroid/test-suites/ref-programs/pick.ast
@@ -1,7 +1,7 @@
    load system io.
    load system pick.
 
-   let po = pick @pick([1 to 10]).
+   let po = pick @pick [1 to 10].
    let objects = po @pickitems 3.
    io @println objects.
    
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/prgm-001.ast b/asteroid/test-suites/ref-programs/prgm-001.ast
new file mode 100644
index 00000000..6c8a6198
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-001.ast
@@ -0,0 +1,11 @@
+
+      let i = 0.
+
+      loop
+         let i = i+1.
+         if i==10 do
+            break.
+         end
+      end
+
+      assert (i==10).
diff --git a/asteroid/test-suites/ref-programs/prgm-002.ast b/asteroid/test-suites/ref-programs/prgm-002.ast
new file mode 100644
index 00000000..04b92def
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-002.ast
@@ -0,0 +1,5 @@
+
+      function inc with i do
+         i+1.
+      end
+
diff --git a/asteroid/test-suites/ref-programs/prgm-003.ast b/asteroid/test-suites/ref-programs/prgm-003.ast
new file mode 100644
index 00000000..eb5192b1
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-003.ast
@@ -0,0 +1,10 @@
+
+      let tuple_list = [
+              (0,"duck"),
+              (1,"chicken"),
+              (2,"turkey")
+              ].
+
+      for (1,bird) in tuple_list do
+         assert(bird is "chicken").
+      end
diff --git a/asteroid/test-suites/ref-programs/prgm-004.ast b/asteroid/test-suites/ref-programs/prgm-004.ast
new file mode 100644
index 00000000..97f5d43d
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-004.ast
@@ -0,0 +1,7 @@
+
+      function sign
+         with x if x >= 0 do
+            return 1.
+         with x if x < 0 do
+            return -1.
+      end
diff --git a/asteroid/test-suites/ref-programs/prgm-005.ast b/asteroid/test-suites/ref-programs/prgm-005.ast
new file mode 100644
index 00000000..f02a50e4
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-005.ast
@@ -0,0 +1,11 @@
+
+      let x = 0.
+
+      function foo with none do
+         global x.
+         let x = 1.
+      end
+
+      assert(x==0).
+      foo().
+      assert(x==1).
diff --git a/asteroid/test-suites/ref-programs/prgm-006-io.txt b/asteroid/test-suites/ref-programs/prgm-006-io.txt
new file mode 100644
index 00000000..021ea30c
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-006-io.txt
@@ -0,0 +1,2 @@
+10
+
diff --git a/asteroid/test-suites/ref-programs/prgm-006.ast b/asteroid/test-suites/ref-programs/prgm-006.ast
new file mode 100644
index 00000000..d5f46753
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-006.ast
@@ -0,0 +1,15 @@
+
+      load system io.
+
+      let x = tointeger (io @input "Please enter an integer: ").
+
+      if x < 0 do
+          io @println "Negative".
+      elif x == 0 do
+          io @println "Zero".
+      elif x == 1 do
+          io @println "One".
+      else do
+          io @println "Positive".
+      end
+
diff --git a/asteroid/test-suites/ref-programs/prgm-007.ast b/asteroid/test-suites/ref-programs/prgm-007.ast
new file mode 100644
index 00000000..d8115ff5
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-007.ast
@@ -0,0 +1,5 @@
+
+      load io. -- load my IO module
+      load system io as systemio. -- load the system IO module and rename it to systemio
+      io @output "Foobar".
+      systemio @println "Hello World!".
diff --git a/asteroid/test-suites/ref-programs/prgm-008.ast b/asteroid/test-suites/ref-programs/prgm-008.ast
new file mode 100644
index 00000000..4d90704b
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-008.ast
@@ -0,0 +1,10 @@
+
+      match (1,2)
+         with (x,y) if x > y do
+            let x = "GT".
+         with (x,y) if x < y do
+            let x = "LT".
+         with _ do
+            throw Error("not a valid tuple").
+      end
+      assert(x == "LT").
diff --git a/asteroid/test-suites/ref-programs/prgm-009.ast b/asteroid/test-suites/ref-programs/prgm-009.ast
new file mode 100644
index 00000000..e45d1e52
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-009.ast
@@ -0,0 +1,9 @@
+
+      load system io.
+
+      let l = ["bmw", "volkswagen", "mercedes"].
+
+      repeat
+         let [element|l] = l.
+         io @println element.
+      until l is [].
diff --git a/asteroid/test-suites/ref-programs/prgm-010.ast b/asteroid/test-suites/ref-programs/prgm-010.ast
new file mode 100644
index 00000000..11751f81
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-010.ast
@@ -0,0 +1,9 @@
+      -- define a structure of type A
+      structure A with
+          data a.
+          data b.
+      end
+
+      let obj = A(1,2).       -- call default constructor
+      assert( obj@a == 1 ).  -- access first data member
+      assert( obj@b == 2 ).  -- access second data member
diff --git a/asteroid/test-suites/ref-programs/prgm-011.ast b/asteroid/test-suites/ref-programs/prgm-011.ast
new file mode 100644
index 00000000..fa225023
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-011.ast
@@ -0,0 +1,18 @@
+      -- 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 "+ tostring(this@age) +" years old".
+          end
+      end
+
+      let betty = Person("Betty",21).  -- call constructor
+      assert( betty@name == "Betty" ).
+      assert( betty@age == 21 ).
+
+      assert(tostring betty is "Betty is 21 years old").
diff --git a/asteroid/test-suites/ref-programs/prgm-012.ast b/asteroid/test-suites/ref-programs/prgm-012.ast
new file mode 100644
index 00000000..4974716b
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-012.ast
@@ -0,0 +1,7 @@
+      load system io.
+
+      try
+          let x = 1/0.
+      catch Exception("ArithmeticError", s) do
+          io @println s.
+      end
diff --git a/asteroid/test-suites/ref-programs/prgm-013.ast b/asteroid/test-suites/ref-programs/prgm-013.ast
new file mode 100644
index 00000000..10183b32
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-013.ast
@@ -0,0 +1,8 @@
+      load system io.
+
+      let i = 10.
+
+      while i >= 0 do
+         io @println i.
+         let i = i-1.
+      end
diff --git a/asteroid/test-suites/ref-programs/prgm-014.ast b/asteroid/test-suites/ref-programs/prgm-014.ast
new file mode 100644
index 00000000..de64cf6b
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-014.ast
@@ -0,0 +1,7 @@
+      structure A with
+         data a.
+         data b.
+      end
+
+      let obj = A(1,2).
+      assert( obj@a == 1 ).  -- access member a
diff --git a/asteroid/test-suites/ref-programs/prgm-015.ast b/asteroid/test-suites/ref-programs/prgm-015.ast
new file mode 100644
index 00000000..9af02587
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/prgm-015.ast
@@ -0,0 +1,11 @@
+   load system io.
+
+   if (1,2) is (x,y) do
+      io @println "success".
+      assert(isdefined "x").
+      assert(isdefined "y").
+   else
+      io @println "not matched".
+      assert(not isdefined "x").
+      assert(not isdefined "y").
+   end
diff --git a/asteroid/test-suites/ref-programs/stream.ast b/asteroid/test-suites/ref-programs/stream.ast
index 41971f97..5ee8272c 100644
--- a/asteroid/test-suites/ref-programs/stream.ast
+++ b/asteroid/test-suites/ref-programs/stream.ast
@@ -3,7 +3,7 @@
 
    let s = stream @stream [1 to 10].
    while not s @eof() do
-      io @print (s @get() + " ").
+      io @print (tostring (s @get()) + " ").
    end
    io @println "".
    
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/type.ast b/asteroid/test-suites/ref-programs/type.ast
index 28b79870..82fc6335 100644
--- a/asteroid/test-suites/ref-programs/type.ast
+++ b/asteroid/test-suites/ref-programs/type.ast
@@ -1,5 +1,4 @@
-   load system type.
 
    let i = 1.
-   assert(type @gettype(i) == "integer").
+   assert(gettype(i) == "integer").
    
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test002.ast b/asteroid/test-suites/regression-tests/test002.ast
index a8f98724..61532d69 100644
--- a/asteroid/test-suites/regression-tests/test002.ast
+++ b/asteroid/test-suites/regression-tests/test002.ast
@@ -1,9 +1,7 @@
 
 load system io.
 load system util.
-load system type.
 
-let isnone = type @isnone.
 
 -----------------------------------------------------------------------
 let x = [1,2].
diff --git a/asteroid/test-suites/regression-tests/test004.ast b/asteroid/test-suites/regression-tests/test004.ast
index 1a7c7ee7..a25cdabf 100644
--- a/asteroid/test-suites/regression-tests/test004.ast
+++ b/asteroid/test-suites/regression-tests/test004.ast
@@ -1,5 +1,4 @@
 
 load system io.
-load system type.
-let l if type @tostring l is "\[.*\]" = [1,2,3].
+let l if tostring l is "\[.*\]" = [1,2,3].
 io @println l.
diff --git a/asteroid/test-suites/regression-tests/test012.ast b/asteroid/test-suites/regression-tests/test012.ast
index f5bc7a54..5733f2ea 100644
--- a/asteroid/test-suites/regression-tests/test012.ast
+++ b/asteroid/test-suites/regression-tests/test012.ast
@@ -1,6 +1,6 @@
 
 -- Palindrome list filter
-load io.
+load system io.
 
 function filter 
     with (x:%string) if x @explode() == x @explode() @reverse() do
diff --git a/asteroid/test-suites/regression-tests/test013.ast b/asteroid/test-suites/regression-tests/test013.ast
index 3b7251e2..4d6d9e80 100644
--- a/asteroid/test-suites/regression-tests/test013.ast
+++ b/asteroid/test-suites/regression-tests/test013.ast
@@ -1,4 +1,4 @@
 
-load io.
+load system io.
 let i:%integer = 1.
 io @print i.
diff --git a/asteroid/test-suites/regression-tests/test015.ast b/asteroid/test-suites/regression-tests/test015.ast
index 61c1b43b..c7a9b667 100644
--- a/asteroid/test-suites/regression-tests/test015.ast
+++ b/asteroid/test-suites/regression-tests/test015.ast
@@ -147,4 +147,4 @@ catch _ do
     io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
---------------------------------------------------END----
\ No newline at end of file
+--------------------------------------------------END----
diff --git a/asteroid/test-suites/regression-tests/test017.ast b/asteroid/test-suites/regression-tests/test017.ast
index 3e412235..c845a4ae 100644
--- a/asteroid/test-suites/regression-tests/test017.ast
+++ b/asteroid/test-suites/regression-tests/test017.ast
@@ -1,6 +1,5 @@
 
 load system io.
-load system type.
 
-let (l:%list) if type @tostring l is "\[.*2.*\]" = [1,2,3].
+let (l:%list) if 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/test019.ast b/asteroid/test-suites/regression-tests/test019.ast
index ac1342b7..2c05a1a6 100644
--- a/asteroid/test-suites/regression-tests/test019.ast
+++ b/asteroid/test-suites/regression-tests/test019.ast
@@ -2,7 +2,7 @@
 -- Factorial
 
 load system io.
-load "util".
+load system util.
 
 function fact 
     with 0 do
@@ -13,6 +13,6 @@ function fact
         throw Error("factorial is not defined for "+n).
     end 
 
-io @println ("The factorial of 3 is: " + fact (3)).
+io @println ("The factorial of 3 is: " + tostring (fact (3))).
 assert (fact(3) == 6).
 
diff --git a/asteroid/test-suites/regression-tests/test027.ast b/asteroid/test-suites/regression-tests/test027.ast
index 3b53c07b..68cc3ab1 100644
--- a/asteroid/test-suites/regression-tests/test027.ast
+++ b/asteroid/test-suites/regression-tests/test027.ast
@@ -3,7 +3,7 @@ load system io.
 
 structure A with
     data a.
-    function hello with none do return "hello: "+ this @a end.
+    function hello with none do  "hello: "+ tostring (this@a) end.
     end
     
 structure B with
diff --git a/asteroid/test-suites/regression-tests/test038.ast b/asteroid/test-suites/regression-tests/test038.ast
index 6ab55e07..3ad23a81 100644
--- a/asteroid/test-suites/regression-tests/test038.ast
+++ b/asteroid/test-suites/regression-tests/test038.ast
@@ -1,4 +1,4 @@
 
 load system io.
 let t = (1,2).
-io @println ("tuple = " + t).
+io @println ("tuple = " + tostring t).
diff --git a/asteroid/test-suites/regression-tests/test040.ast b/asteroid/test-suites/regression-tests/test040.ast
index cd5b92ea..72558b23 100644
--- a/asteroid/test-suites/regression-tests/test040.ast
+++ b/asteroid/test-suites/regression-tests/test040.ast
@@ -1,6 +1,6 @@
 
 load system io.
-load "util".
+load system util.
 
 structure Dog with
 
@@ -33,8 +33,8 @@ buddy @add_trick("roll over").
 buddy @add_trick("sit stay").
 
 -- io @println out the tricks
-io @println ("Fido: " + fido @tricks).
-io @println ("Buddy: " + buddy @tricks).
+io @println ("Fido: " + tostring (fido@tricks)).
+io @println ("Buddy: " + tostring (buddy@tricks)).
 
 assert(fido @tricks is ["roll over", "play dead"]).
 assert(buddy @tricks is ["roll over", "sit stay"]).
diff --git a/asteroid/test-suites/regression-tests/test043.ast b/asteroid/test-suites/regression-tests/test043.ast
index 23eba019..b8172490 100644
--- a/asteroid/test-suites/regression-tests/test043.ast
+++ b/asteroid/test-suites/regression-tests/test043.ast
@@ -15,6 +15,6 @@ let people = [
     ].
     
 let Person(name,age,sex) = people @1.
-let output_str = name + " is " + age + " years old and is " + ("male" if sex is "M" else "female") + ".".
+let output_str = name + " is " + tostring age + " years old and is " + ("male" if sex is "M" else "female") + ".".
 io @println output_str.
 assert(output_str is "Sophie is 46 years old and is female.")
diff --git a/asteroid/test-suites/regression-tests/test060.ast b/asteroid/test-suites/regression-tests/test060.ast
index 947e5bf8..2860ef1e 100644
--- a/asteroid/test-suites/regression-tests/test060.ast
+++ b/asteroid/test-suites/regression-tests/test060.ast
@@ -1,6 +1,6 @@
 
 load system io.
-load "util".
+load system util.
 
 structure Person with
     data name.
@@ -21,7 +21,7 @@ for Person(_,age,_) in people do
     let sum = sum + age.
 end 
 
-io @println ("Average Age: " + (sum/n)).
+io @println ("Average Age: " + tostring (sum/n)).
 assert ((sum/n) == 33).
 
 for Person(name,_,"M") in people do
diff --git a/asteroid/test-suites/regression-tests/test067.ast b/asteroid/test-suites/regression-tests/test067.ast
index c5edecd9..a0224dad 100644
--- a/asteroid/test-suites/regression-tests/test067.ast
+++ b/asteroid/test-suites/regression-tests/test067.ast
@@ -1,8 +1,7 @@
 
-load system type.
 load system io.
 
-let cnt = type @tointeger(io @input("Please enter an integer value: ")).
+let cnt = tointeger(io @input("Please enter an integer value: ")).
 
 for i in 1 to cnt do
     io @println i.
diff --git a/asteroid/test-suites/regression-tests/test072.ast b/asteroid/test-suites/regression-tests/test072.ast
index 8bb43baa..90cfbea8 100644
--- a/asteroid/test-suites/regression-tests/test072.ast
+++ b/asteroid/test-suites/regression-tests/test072.ast
@@ -2,7 +2,7 @@
 -- Factorial
 
 load system io.
-load "util".
+load system util.
 
 function fact 
     with 0 do
@@ -11,5 +11,5 @@ function fact
         return n * fact (n-1).
     end 
 
-io @println ("The factorial of 3 is: " + fact (3)).
+io @println ("The factorial of 3 is: " + tostring (fact 3)).
 assert (fact(3) == 6).
diff --git a/asteroid/test-suites/regression-tests/test075.ast b/asteroid/test-suites/regression-tests/test075.ast
index 95b4ff34..de8daf41 100644
--- a/asteroid/test-suites/regression-tests/test075.ast
+++ b/asteroid/test-suites/regression-tests/test075.ast
@@ -1,7 +1,7 @@
 
 load system io.
-load "util".
+load system util.
 
 let [h|t] = [1,2,3].
-io @println ("head: " + h + " tail: " + t).
+io @println ("head: " + tostring h + " tail: " + tostring t).
 assert(h == 1 and t == [2,3]).
diff --git a/asteroid/test-suites/regression-tests/test085.ast b/asteroid/test-suites/regression-tests/test085.ast
deleted file mode 100644
index b34cb522..00000000
--- a/asteroid/test-suites/regression-tests/test085.ast
+++ /dev/null
@@ -1,14 +0,0 @@
-
-load system io.
-load "util".
-
-structure A with
-    data x.
-    data y.
-    end 
-
-let a = A(999, (lambda with none do return "Hello World!"+this@x)).
-io @println (a@1()).
-
-assert(a@1() is "Hello World!999").
-
diff --git a/asteroid/test-suites/regression-tests/test089.ast b/asteroid/test-suites/regression-tests/test089.ast
deleted file mode 100644
index d1225d87..00000000
--- a/asteroid/test-suites/regression-tests/test089.ast
+++ /dev/null
@@ -1,14 +0,0 @@
-
-load system io.
-load "util".
-
-structure A with
-    data x.
-    data y.
-    data z.
-    end 
-
-let a = A(1,2,3).
-let b = a@[0 to 2].
-io @println b.
-assert (b is [1,2,3]).
diff --git a/asteroid/test-suites/regression-tests/test096.ast b/asteroid/test-suites/regression-tests/test096.ast
deleted file mode 100644
index 16b7fac8..00000000
--- a/asteroid/test-suites/regression-tests/test096.ast
+++ /dev/null
@@ -1,12 +0,0 @@
-
-load system io.
-load "util".
-
-structure A with
-    data x.
-    end 
-    
-let a = A([1,2,3]).
-let a@0@1 = 0.
-io @println a.
-assert (a is A([1,0,3])).
diff --git a/asteroid/test-suites/regression-tests/test098.ast b/asteroid/test-suites/regression-tests/test098.ast
deleted file mode 100644
index d4e01890..00000000
--- a/asteroid/test-suites/regression-tests/test098.ast
+++ /dev/null
@@ -1,24 +0,0 @@
-
-load system io.
-load "util".
-
-structure A with 
-    data a.
-    end 
-    
-structure B with 
-    data x.
-    data y.
-    end 
-
-let x = A(1).
-let y = B(1,2).
-
-let A(z) = x.
-let B(v,w) = y.
-
-let xx = x@0.
-let yy = y@[0,1].
-
-io @println (x,y,xx,yy).
-assert ((x,y,xx,yy) is (A(1),B(1,2),1,[1,2])).
diff --git a/asteroid/test-suites/regression-tests/test114.ast b/asteroid/test-suites/regression-tests/test114.ast
index d11d40f9..80d1af3e 100644
--- a/asteroid/test-suites/regression-tests/test114.ast
+++ b/asteroid/test-suites/regression-tests/test114.ast
@@ -1,11 +1,8 @@
 -- tests for formatting
 
 load system io.
-load system type.
 load system math.
 
-let tostring = type @tostring.
-let stringformat = type @stringformat.
 
 let b = tostring(true,stringformat(10)).
 io @println b.
diff --git a/asteroid/test-suites/regression-tests/test115.ast b/asteroid/test-suites/regression-tests/test115.ast
index 4a1dede9..ab309d56 100644
--- a/asteroid/test-suites/regression-tests/test115.ast
+++ b/asteroid/test-suites/regression-tests/test115.ast
@@ -1,9 +1,6 @@
 -- testing the builtin 'len' function
 
 load system io.
-load system type.
-
-let tostring = type @tostring.
 
 structure Foo with
    data one.
@@ -11,9 +8,9 @@ structure Foo with
    data three.
    function hello
       with none do
-        io @println (tostring(this @one)+
-                 tostring(this @two)+
-                 tostring(this @three)).
+        io @println (tostring(this@one)+
+                 tostring(this@two)+
+                 tostring(this@three)).
       end
    end
 
diff --git a/asteroid/test-suites/regression-tests/test120.ast b/asteroid/test-suites/regression-tests/test120.ast
index 2deee960..5aa48237 100644
--- a/asteroid/test-suites/regression-tests/test120.ast
+++ b/asteroid/test-suites/regression-tests/test120.ast
@@ -6,7 +6,7 @@ assert(x == 2).
 let y = +3.0.
 assert(y == 3.0).
 
-let z = +x + +y - +x * +-x.
+let z = toreal(+x) + +y - toreal(+x) * + toreal(-x).
 assert(z == 9.0).
 
 assert(+12 == 12).
diff --git a/asteroid/test-suites/regression-tests/test127.ast b/asteroid/test-suites/regression-tests/test127.ast
index 02b8f27f..c4735f84 100644
--- a/asteroid/test-suites/regression-tests/test127.ast
+++ b/asteroid/test-suites/regression-tests/test127.ast
@@ -7,6 +7,8 @@ escape
 from asteroid.interp import interp
 from asteroid.state import state
 
+print(1)
+
 program = ''
 program += 'let x = 1.\n'
 program += 'let y = 0.\n'
@@ -24,6 +26,8 @@ except:
 
 assert( state.lineinfo[1] == 6)
 
+print(2)
+
 program = ''
 program += 'let x = 1.\n'
 program += 'let y = 0.\n'
@@ -46,6 +50,8 @@ except:
 
 assert( state.lineinfo[1] == 8)
 
+print(3)
+
 program = ''
 program += 'let x = 1.\n'
 program += 'let y = 0.\n'
@@ -74,11 +80,13 @@ except:
 
 assert( state.lineinfo[1] == 12)
 
+print(4)
+
 program = ''
 program += 'let x = 1.\n'
 program += 'let y = 0.\n'
 program += '\n'
-program += 'while (1) do\n'
+program += 'while (true) do\n'
 program += '    if ( x < 0) do\n'
 program += '        ...\n'
 program += '    elif ( x < 1 ) do\n'
@@ -100,6 +108,6 @@ try:
     interp(program,exceptions=True)
 except:
     pass
-
+    
 assert( state.lineinfo[1] == 13 )
 "
diff --git a/asteroid/test-suites/regression-tests/test129.ast b/asteroid/test-suites/regression-tests/test129.ast
index 4baa699a..527df49e 100644
--- a/asteroid/test-suites/regression-tests/test129.ast
+++ b/asteroid/test-suites/regression-tests/test129.ast
@@ -6,18 +6,18 @@ let n = E + e - 4.00e01 + 0.1.
 io @println(n).
 assert(n == -69.8999999999897).
 
-let s = type @tostring(n,type @stringformat(10,10,true)).
+let s = tostring(n,stringformat(10,10,true)).
 io @println(s).
 assert(s == "-6.9900000000e+01").
 
-let s = type @tostring(n,type @stringformat(10,10,false)).
+let s = tostring(n,stringformat(10,10,false)).
 io @println(s).
 assert(s == "-69.9000000000").
 
 let y = 1.
-io @println(type @gettype(y)).
-assert(type @gettype(y) == "integer").
+io @println(gettype(y)).
+assert(gettype(y) == "integer").
 
 let z = 1.0.
-io @println(type @gettype(z)).
-assert(type @gettype(z) == "real").
\ No newline at end of file
+io @println(gettype(z)).
+assert(gettype(z) == "real").
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test130.ast b/asteroid/test-suites/regression-tests/test130.ast
deleted file mode 100644
index 7ace9a41..00000000
--- a/asteroid/test-suites/regression-tests/test130.ast
+++ /dev/null
@@ -1,8 +0,0 @@
--- patterns are just values: we can pattern match and index
-let z = pattern ((p,q),(r,t)).
-let (x,_) = z.
-let y = z@0.
-
-assert((1,2) is %[*x]%).
-assert((1,2) is %[*y]%).
-
diff --git a/asteroid/test-suites/regression-tests/test131.ast b/asteroid/test-suites/regression-tests/test131.ast
deleted file mode 100644
index 1eec448e..00000000
--- a/asteroid/test-suites/regression-tests/test131.ast
+++ /dev/null
@@ -1,4 +0,0 @@
--- patterns can always match themselves.
-let z = pattern (p,q).
-assert(z is %[*z]%).
-
diff --git a/asteroid/test-suites/regression-tests/test133.ast b/asteroid/test-suites/regression-tests/test133.ast
deleted file mode 100644
index 643acb69..00000000
--- a/asteroid/test-suites/regression-tests/test133.ast
+++ /dev/null
@@ -1,13 +0,0 @@
--- testing structures as boolean values
-assert(lambda with x do return x+1).
-assert(pattern x).
-assert((1,2)).
-assert(not ()).
-
-structure A with
-   data a.
-   data b.
-end
-
-assert(A(1,2)).
-
diff --git a/asteroid/test-suites/regression-tests/test135.ast b/asteroid/test-suites/regression-tests/test135.ast
index 05b0c027..03cbad87 100644
--- a/asteroid/test-suites/regression-tests/test135.ast
+++ b/asteroid/test-suites/regression-tests/test135.ast
@@ -7,7 +7,7 @@ end
 
 try
    let B(x,y) = A(1,2).
-catch Exception(t,m) do
-   assert(m is "'B' is not defined").
+catch e:Exception(t,m) do
+   assert(m is "illegal pattern, 'B' is not a type").
 end
 
diff --git a/asteroid/test-suites/regression-tests/test143.ast b/asteroid/test-suites/regression-tests/test143.ast
index d6321277..57a8a823 100644
--- a/asteroid/test-suites/regression-tests/test143.ast
+++ b/asteroid/test-suites/regression-tests/test143.ast
@@ -7,7 +7,7 @@ structure Person with
          let this @age = age.
       end
       function __str__ with none do
-         return this@name+" is "+this@age+" years old".
+         this@name+" is "+ tostring (this@age) +" years old".
       end
 end
 
@@ -15,5 +15,4 @@ 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").
+assert(tostring betty is "Betty is 21 years old").
diff --git a/asteroid/test-suites/regression-tests/test145.ast b/asteroid/test-suites/regression-tests/test145.ast
deleted file mode 100644
index 496682e7..00000000
--- a/asteroid/test-suites/regression-tests/test145.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-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/regression-tests/test147.ast b/asteroid/test-suites/regression-tests/test147.ast
new file mode 100644
index 00000000..e0c65f14
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test147.ast
@@ -0,0 +1,29 @@
+load system math.
+
+let test_cases = [
+    (3.14, 3),
+    (3.508, 4),
+    (12.99999, 13),
+    (13.00000, 13),
+    (13.00001, 13),
+    (13.49999, 13),
+    (13.50000, 14),
+    (13.50001, 14),
+    (13.99999, 14),
+    (14.00000, 14),
+    (14.00001, 14),
+    (14.49999, 14),
+    (14.50000, 14),
+    (12.5, 12),
+    (13.5, 14),
+    (14.5, 14),
+    (15.5, 16),
+    (0.0, 0),
+    (-0.0, 0),
+    (-53.246, -53),
+    (-53.5, -54)
+].
+
+for (input, expected_output) in test_cases do
+    assert (math @round input == expected_output).
+end
diff --git a/asteroid/test-suites/regression-tests/test152.ast b/asteroid/test-suites/regression-tests/test152.ast
new file mode 100644
index 00000000..f486c4a9
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test152.ast
@@ -0,0 +1,8 @@
+load system os.
+load system io.
+
+if os @platform == "darwin" do
+	io @println (os @env @get "HOME").
+end
+
+
diff --git a/asteroid/test-suites/regression-tests/test153.ast b/asteroid/test-suites/regression-tests/test153.ast
new file mode 100644
index 00000000..437747d0
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test153.ast
@@ -0,0 +1,12 @@
+let p = (1,2).
+match p
+   with (x,y) if x > y do
+      let x = "GT".
+   with (x,y) if x < y do
+      let x = "LT".
+   with _ do
+      throw Error("not a valid tuple").
+end
+assert(x =="LT").
+
+
diff --git a/asteroid/test-suites/regression-tests/test154.ast b/asteroid/test-suites/regression-tests/test154.ast
new file mode 100644
index 00000000..7ee39753
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test154.ast
@@ -0,0 +1,4 @@
+load system io as myio.
+
+myio @println "Hello, World!".
+
diff --git a/asteroid/test-suites/regression-tests/test155.ast b/asteroid/test-suites/regression-tests/test155.ast
new file mode 100644
index 00000000..eddf1e53
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test155.ast
@@ -0,0 +1,8 @@
+load system io.
+
+if toplevel() do
+        io @println "Hello, World!".
+else do
+        throw Error "toplevel operator did not work".
+end
+
diff --git a/asteroid/test-suites/regression-tests/test156.ast b/asteroid/test-suites/regression-tests/test156.ast
new file mode 100644
index 00000000..ededa596
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test156.ast
@@ -0,0 +1,11 @@
+structure A with
+  data a.
+  function __init__ with _ do 
+    let this@a = 2.
+  end
+end
+
+-- testing objects as patterns
+let o = A(1).
+let *o = A(1).
+
diff --git a/asteroid/test-suites/regression-tests/test157.ast b/asteroid/test-suites/regression-tests/test157.ast
new file mode 100644
index 00000000..69217b05
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test157.ast
@@ -0,0 +1,514 @@
+load system io.
+load system math.
+
+-- Math library revision test 6/18/2023 ttc
+
+let failures = 0.
+let EXPECTED = pattern with Exception( "SystemError" , _ ).
+
+--                                      **********************
+--                                      **** Constants    ****
+--                                      **********************
+let x = math@ pi.
+let y = math@ tau.
+assert( math@isclose( (2.0*x) ,y)  ). -- assert tau is correct value
+
+--                                      **********************
+--                                      **** Combinations ****
+--                                      **********************
+assert( math@comb(10,7) == 120 ). 
+assert( math@comb(10,5) == 252 ).
+assert( math@comb(7,5) == 21 ).
+assert( math@comb(5,7) == 0 ).
+assert( math@comb(0,7) == 0 ).
+
+try
+    math@comb(-1,7).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@comb(10.2,7).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** Permutations ****
+--                                      **********************
+assert( math@perm(10,7) == 604800 ). 
+assert( math@perm(10,5) == 30240 ).
+assert( math@perm(7,5) == 2520 ).
+assert( math@perm(5,7) == 0 ).
+assert( math@perm(0,7) == 0 ).
+
+try
+    math@perm(-1,7).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@perm(10.3,7).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** isqrt        ****
+--                                      **********************
+assert( math@isqrt(16) == 4 ).
+assert( math@isqrt(17) == 4 ).
+assert( math@isqrt(18) == 4 ).
+assert( math@isqrt(20) == 4 ).
+assert( math@isqrt(4) == 2 ).
+assert( math@isqrt(5) == 2 ).
+assert( math@isqrt(101) == 10 ).
+assert( math@isqrt(150) == 12 ).
+
+try
+    math@isqrt(-1.1).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@isqrt("hello").
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** ldexp        ****
+--                                      **********************
+assert( math@isclose( math@ldexp(7,7) , 896.0 )).
+assert( math@isclose( math@ldexp(-4,12) , -16384.0 )).
+assert( math@isclose( math@ldexp(11,-3) , 11.0/8.0 )).
+assert( math@isclose( math@ldexp(9,8) , 2304.0 )).
+
+try
+    mathldexp("hello",7).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@ldexp(7,"hello").
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** prod         ****
+--                                      **********************
+assert( math@prod( [1,2,3,4,5] ) == 120 ).
+assert( math@prod( (1,2,3,4,5) ) == 120 ).
+assert( math@prod( [-2,-2,-2,-2] ) == 16 ).
+assert( math@prod( [-2,-2,-2,-2,-2] ) == -32 ).
+assert( math@isclose( math@prod(12.3,100.01,14.56,9.5) , 170150.61336) ).
+assert( math@prod( [1,2,3,4,5] ) == math@prod( (5,4,3,2,1) ) ).
+
+try
+    math@prod( ["h","e","l","l","o"] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@prod( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** sum          ****
+--                                      **********************
+assert( math@sum( [1,2,3,4,5] ) == 15 ).
+assert( math@sum( (1,2,3,4,5) ) == 15 ).
+assert( math@sum( [-2,-2,-2,-2] ) == -8 ).
+assert( math@sum( [-2,-2,-2,-2,-2] ) == -10 ).
+assert( math@isclose(  math@sum( (12.3,100.01,14.56,9.5) ) , 136.37) ).
+assert( math@sum( [1,2,3,4,5] ) == math@sum( (5,4,3,2,1) ) ).
+
+try
+    math@sum( ["h","e","l","l","o"] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@sum( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+--                                      **********************
+--                                      **** fsum         ****
+--                                      **********************
+assert( math@isclose( math@fsum( [0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1] ) , 1.0 )).
+assert( math@isclose( math@fsum( (1.0/5.0,1.0/5.0,1.0/5.0,1.0/5.0,1.0/5.0) ) , 1.0 )).
+
+try
+    math@fsum( ["h","e","l","l","o"] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@fsum( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+--                                      **********************
+--                                      **** lcm          ****
+--                                      **********************
+assert( math@lcm(4,5) == 20 ).
+assert( math@lcm(5,4) == 20 ).
+assert( math@lcm(6,8) == 24 ).
+assert( math@lcm(13,17) == 221 ).
+assert( math@lcm(101,117) == 11817 ).
+
+try
+    math@lcm( "a",12 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@lcm( 33,"b" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+--                                      **********************
+--                                      **** copysign     ****
+--                                      **********************
+assert( math@isclose( math@copysign(1.1,2.2) , 1.1 )).
+assert( math@isclose( math@copysign(1,2) , 1 )).
+assert( math@isclose( math@copysign(1.1,-2.2), -1.1 )).
+assert( math@isclose( math@copysign(1,-2) , -1 )).
+assert( math@isclose( math@copysign(-1.1,2.2) , 1.1 )).
+assert( math@isclose( math@copysign(-1,2) , 1 )).
+assert( math@isclose(  math@copysign(-1.1,-2.2) , -1.1 )).
+assert( math@isclose( math@copysign(-1,-2) , -1 )).
+
+try
+    math@copysign( "a",-12 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@copysign( 33,"b" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+--                                      **********************
+--                                      **** factorial    ****
+--                                      **********************
+assert( math@factorial(1) == 1 ).
+assert( math@factorial(0) == 1 ).
+assert( math@factorial(10) == 3628800 ).
+assert( math@factorial(5) == 120 ).
+assert( math@factorial(12) == 479001600 ).
+assert( math@factorial(3) == 6 ).
+
+try
+    math@copysign( 10.23 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@copysign( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+--                                      **********************
+--                                      **** trunc        ****
+--                                      **********************
+assert( math@trunc(1.00000001) == 1 ).
+assert( math@trunc(1.99999999) == 1 ).
+assert( math@trunc(-1.00000001) == -1 ).
+assert( math@trunc(-1.99999999) == -1 ).
+
+try
+    math@trunc( 5 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@trunc( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** fmod         ****
+--                                      **********************
+assert( math@fmod(12,10) == 2 ).
+assert( math@fmod(-12,10) == -2 ).
+assert( math@fmod(123,5) == 3 ).
+assert( math@fmod(-123,5) == -3 ).
+
+try
+    math@fmod( 5.5,100 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@fmod( "hello",100 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** atan2        ****
+--                                      **********************
+assert( math@isclose( math@atan2(12,10) , 0.8760580505981934) ).
+assert( math@isclose( math@atan2(0.5,1.666) , 0.29156692663601214) ).
+assert( math@isclose( math@atan2(-0.9,4.001) , -0.22126091552495672) ).
+assert( math@isclose( math@atan2(-1,-1) , -2.35619449019234484) ).
+
+try
+    math@atan2( 5.5,"hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@atan2( "hello",100 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** remainder    ****
+--                                      **********************
+assert( math@isclose( math@remainder(12,10) , 2.0 )).
+assert( math@isclose( math@remainder(2,2) , 0.0 )).
+assert( math@isclose( math@remainder(2,4) , 2.0 )).
+assert( math@isclose( math@remainder(2,0.5) , 0.0 )).
+assert( math@isclose( math@remainder(0.5,0.11) , -0.05 )).
+
+try
+    math@remainder( 5.5,"hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@remainder( "hello",100 ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** expm1        ****
+--                                      **********************
+assert( math@isclose( math@expm1(0) , 0.0 )).
+assert( math@isclose( math@expm1(1) , 1.718281828459045 )).
+assert( math@isclose( math@expm1(2) , 6.38905609893065 )).
+assert( math@isclose( math@expm1(2.1) , 7.16616991256765 )).
+assert( math@isclose( math@expm1(-1.1) , -0.6671289163019205 )).
+
+try
+    math@expm1( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@expm1( ["hello"] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** log2         ****
+--                                      **********************
+assert( math@isclose( math@log2(4) , 2.0 )).
+assert( math@isclose( math@log2(16) , 4.0 )).
+assert( math@isclose( math@log2(1024.0) , 10.0 )).
+assert( math@isclose( math@log2(2.1) , 1.070389327891398 )).
+
+try
+    math@log2( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@log2( ["hello"] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** log10        ****
+--                                      **********************
+assert( math@isclose( math@log10(10) , 1.0 )).
+assert( math@isclose( math@log10(100) , 2.0 )).
+assert( math@isclose( math@log10(1000.0) , 3.0 )).
+assert( math@isclose( math@log10(200.1) , 2.3012470886362113 )).
+
+try
+    math@log10( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@log10( ["hello"] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** dist         ****
+--                                      **********************
+assert( math@isclose( math@dist( (1,1) , (1,2) ) , 1.0 )).
+assert( math@isclose( math@dist( (1,1) , (2,1) ) , 1.0 )).
+assert( math@isclose( math@dist((2,3,4,5,6),(6,7,3,4,5)) , 5.916079783099616 )).
+assert( math@isclose( math@dist((1,1),(100,175)) , 200.19240744843447 )).
+
+try
+    math@dist( "hello","world" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@dist( (1,1), (1,2,3) ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** hypot        ****
+--                                      **********************
+assert( math@isclose( math@hypot( 3 , 4 ) , 5.0) ).
+assert( math@isclose( math@hypot( 1 , 1 ) , math@sqrt(2) )).
+assert( math@isclose( math@hypot( 5 , 5 ) , math@sqrt(50) )).
+assert( math@isclose(math@hypot( 8 , 15 ) , 17.0 )).
+assert( math@isclose( math@hypot( 13 , 17 ) , math@sqrt( math@pow(13,2) + math@pow(17,2)) )).
+
+try
+    math@hypot( "hello","world" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@hypot( [1,2,3], (1,2,3) ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** error        ****
+--                                      **********************
+assert( math@isclose( math@erf( 1.1 ) , 0.8802050695740817 )).
+assert( math@isclose( math@erf( -1.1 ) , -0.8802050695740817 )).
+assert( math@isclose( math@erf( 10 ) , 1.0 )).
+assert( math@isclose( math@erf( 0.13333 ) , 0.1495600366981686 )).
+
+try
+    math@erf( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@erf( [1,2,3] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** errorc       ****
+--                                      **********************
+assert( math@isclose( math@erfc( 1.1 ) , 0.11979493042591827 )).
+assert( math@isclose( math@erfc( -1.1 ) , 1.8802050695740817 )).
+assert( math@isclose( math@erfc( 10 ) , 2.088487583762545e-45 )).
+assert( math@isclose( math@erfc( 0.13333 ) , 0.8504399633018314 )).
+
+try
+    math@erfc( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@erfc( [1,2,3] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** gamma        ****
+--                                      **********************
+assert( math@isclose( math@gamma( 1.1 ) , 0.951350769866873 )).
+assert( math@isclose( math@gamma( -1.1 ) , 9.714806382902898 )).
+assert( math@isclose( math@gamma( 10 ) , 362880.0 )).
+assert( math@isclose( math@gamma( 0.13333 ) , 7.0407639878879245 )).
+
+try
+    math@gamma( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@gamma( [1,2,3] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+--                                      **********************
+--                                      **** lgamma       ****
+--                                      **********************
+assert( math@isclose( math@lgamma( 1.1 ) , -0.04987244125984036 )).
+assert( math@isclose( math@lgamma( -1.1 ) , 2.273651152924464 )).
+assert( math@isclose( math@lgamma( 10 ) , 12.801827480081467 )).
+assert( math@isclose( math@lgamma( 0.13333 ) , 1.9517166852887797 )).
+
+try
+    math@lgamma( "hello" ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+try
+    math@lgamma( [1,2,3] ).
+    let failures = failures + 1.
+catch *EXPECTED do
+    . --pass
+end
+
+---------------------------------------------------------------
+assert( failures == 0 ).
+io @println "Pass".
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test158.ast b/asteroid/test-suites/regression-tests/test158.ast
new file mode 100644
index 00000000..267fd27a
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test158.ast
@@ -0,0 +1,589 @@
+load system io.
+load system patterns.
+load system math.
+
+-- Expirmental patterns library test
+
+let failures = 0.
+let EXPECTED = pattern with Exception( "PatternMatchFailed" , _ ).
+
+--                                      **********************
+--                                      **** prime        ****
+--                                      **********************
+let x:*patterns@prime = 2.
+let x:*patterns@prime = 3.
+let x:*patterns@prime = 5.
+let x:*patterns@prime = 11.
+let x:*patterns@prime = 13.
+let x:*patterns@prime = 17.
+let x:*patterns@prime = 97.
+let x:*patterns@prime = 83.
+let x:*patterns@prime = 15485863.
+
+try
+    let x:*patterns@prime = 10.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@prime = 1024.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@prime = 999.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@prime = 63.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+--                                      **********************
+--                                      **** natural      ****
+--                                      **********************
+let x:*patterns@nat = 1.
+let x:*patterns@nat = 2.
+let x:*patterns@nat = 5.
+let x:*patterns@nat = 1486987.
+let x:*patterns@nat = 1010101.
+
+try
+    let x:*patterns@nat = -10.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@nat = -1.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@nat = 1.5.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+--                                      **********************
+--                                      **** pos/neg      ****
+--                                      **********************
+let x:*patterns@positive = 1.
+let x:*patterns@positive = 111111111.
+let x:*patterns@positive = 10.
+let x:*patterns@positive = 1235.3654.
+
+let x:*patterns@pos_int = 12.
+let x:*patterns@pos_int = 12213.
+let x:*patterns@pos_int = 1.
+
+let x:*patterns@pos_real = 1.23.
+let x:*patterns@pos_real = 15222.23.
+let x:*patterns@pos_real = 0.00023.
+
+let x:*patterns@negative = -1.
+let x:*patterns@negative = -111111111.
+let x:*patterns@negative = -10.
+let x:*patterns@negative = -1235.3654.
+
+let x:*patterns@neg_int = -12.
+let x:*patterns@neg_int = -12213.
+let x:*patterns@neg_int = -1.
+
+let x:*patterns@neg_real = -1.23.
+let x:*patterns@neg_real = -15222.23.
+let x:*patterns@neg_real = -0.00023.
+
+try
+    let x:*patterns@positive = -100.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@positive = -0.001.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@pos_int = -12.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@pos_int = 1.2.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@pos_real = -1.2.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@pos_real = 1.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@negative = 0.001.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@negative = 12.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@neg_int = -12.002.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@neg_int = 12.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@neg_real = 1.2.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@neg_real = -51.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+--                                      **********************
+--                                      **** zero         ****
+--                                      **********************
+let x:*patterns@zero = 0.
+let x:*patterns@zero = 0.0.
+
+try
+    let x:*patterns@zero = 2.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@zero = 0.00000000000001.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@zero = -0.2.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@zero = -10.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+--                                      **********************
+--                                      **** even/odd     ****
+--                                      **********************
+let x:*patterns@even = 2.
+let x:*patterns@even = 16.
+let x:*patterns@even = 2048.
+let x:*patterns@odd = 1.
+let x:*patterns@odd = 111117.
+let x:*patterns@odd = 3.
+
+try
+    let x:*patterns@even = 1.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@even = 2.01.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@even = 7.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@odd = 0.7.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@odd = 2.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@odd = 1024.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+--                                      **********************
+--                                      **** containers   ****
+--                                      **********************
+let x:*patterns@int_list = [1,2,3,4].
+let x:*patterns@int_list = [10].
+let x:*patterns@int_list = [-1,15,32].
+
+try
+    let x:*patterns@int_list = [1,2,3,4,5,6,7,8.2345,9,10,11,12,13,14,15].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@int_list = [1,2,3,4,"not a number",6,7,8,9,10,11,12,13,14,15].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@int_list = [ "a", "b", "c" ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@real_list = [-1.0,15.0,32.3].
+let x:*patterns@real_list = [ 1.000000001 ].
+let x:*patterns@real_list = [ 1.1 ,2.2 ,3.3 ,4.4 ,5.5 ,6.6 ,7.7 ,8.8 ,9.9 ,10.1].
+
+try
+    let x:*patterns@real_list = [ 1.1 ,2.2 ,3.3 ,4.4 ,5 ,6.6 ,7.7 ,8.8 ,9.9 ,10.1].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@real_list = [ 1.1 ,2.2 ,3.3 ,4.4 ,"not a number" ,6.6 ,7.7 ,8.8 ,9.9 ,10.1].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@real_list = [ "a", "b", "c" ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@str_list = [ "a", "b", "c" ].
+let x:*patterns@str_list = [ "a" ].
+let x:*patterns@str_list = [ "hello", "hello", "a", "b", "c", "d", "e", "f", "g" ].
+
+try
+    let x:*patterns@str_list = [ "a", "b", 1, "c" ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@str_list = [ "hello", "hello", "a", "b", 1, "c", "d", "e", "f", "g" ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@str_list = [ "hello", "hello", "a", "b", (lambda with x do true), "c", "d", "e", "f", "g" ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@bool_list = [ true, true, true, false, false, true, false, true, false, true, false, false ].
+let x:*patterns@bool_list = [ true ].
+let x:*patterns@bool_list = [ false, true, false, false ].
+let x:*patterns@bool_list = [ false ].
+
+try
+    let x:*patterns@bool_list = [ true, true, true, false, false, 1, false, true, false, true, false, false ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@bool_list = [ true, true, true, false, false, "false", false, true, false, true, false, false ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@bool_list = [ true, true, true, false, false, math@pi ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+function foo1
+    with _ do
+        true
+    end
+function foo2
+    with _ do
+        true
+    end
+function foo3
+    with _ do
+        true
+    end
+function foo4
+    with _ do
+        true
+    end
+function foo5
+    with _ do
+        true
+    end
+function foo6
+    with _ do
+        true
+    end
+
+let x:*patterns@func_list = [ foo1,foo2,foo3,foo4,foo5,foo6 ].
+let x:*patterns@func_list = [ patterns@is_prime ].
+let x:*patterns@func_list = [ foo1,foo2,foo3,(lambda with x do true ),foo4,foo5,foo6 ].
+
+try
+    let x:*patterns@func_list = [ foo1,foo2,foo3,10,foo4,foo5,foo6 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@func_list = [ foo1,foo2,foo3,"string",foo4,foo5,foo6 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@func_list = [ foo1,patterns@func_list,foo4,foo5,foo6 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@list_list = [ [1,2],[3,4],[4,5] ].
+let x:*patterns@list_list = [ [1,2],[3,4],[4,5],[6,7],[8,9,10,11] ].
+let x:*patterns@list_list = [ [1,2] ].
+
+try
+    let x:*patterns@list_list = [ [1,2],[3,4],4,5 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@list_list = [ (1,2) ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@list_list = [ 1,2,3 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@tuple_list = [ (1,2),(3,4),(4,5) ].
+let x:*patterns@tuple_list = [ (1,2),(3,4),(4,5),(6,7),(8,9,10,11) ].
+let x:*patterns@tuple_list = [ (1,2) ].
+
+try
+    let x:*patterns@tuple_list = [ (1,2),(3,4),4,5 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@tuple_list = [ [1,2] ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@tuple_list = [ 1,2,3 ].
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+--                                      **********************
+--                                      **** strings      ****
+--                                      **********************
+
+let x:*patterns@alphabetic =  "helloworld".
+let x:*patterns@alphabetic =  "abcdefghijklmnopqrstuvwxyz".
+let x:*patterns@alphabetic =  "testingtesting".
+
+try
+    let x:*patterns@alphabetic = "hello world!".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@alphabetic = "abc123".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@alphabetic = "onebad$character".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@numeric =  "123456789".
+let x:*patterns@numeric =  "1".
+let x:*patterns@numeric =  "6598942".
+
+try
+    let x:*patterns@numeric = "1234five678".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@numeric = "987654321O". -- o not 0
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@numeric = "1b11101".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@alphanumeric = "abc123".
+let x:*patterns@alphanumeric = "1234five6789".
+let x:*patterns@alphanumeric = "1l1l1l1".
+
+try
+    let x:*patterns@alphanumeric = "1b11101-123".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@alphanumeric = "!$%^&*".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@alphanumeric = "HELLO?".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@lowercase = "abcdefg".
+let x:*patterns@lowercase = "hello".
+let x:*patterns@lowercase = "z".
+
+try
+    let x:*patterns@lowercase = "HELLO".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@lowercase = "abcDefg".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@lowercase = "uppercaseA".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".
+let x:*patterns@uppercase = "Z".
+let x:*patterns@uppercase = "HELLO".
+
+try
+    let x:*patterns@uppercase = "HelloWorld".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@uppercase = "a".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@uppercase = "ABCDeFGHIJKLMNOPQRSTUVWXYZ".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+let x:*patterns@char = "a".
+let x:*patterns@char = "1".
+let x:*patterns@char = "?".
+
+try
+    let x:*patterns@char = "ABC".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@char = "??".
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+try
+    let x:*patterns@char = 1.
+    let failures = failures + 1.
+catch *EXPECTED do
+    .
+end
+
+
+
+
+assert(failures == 0).
+io@println "PASS".
\ No newline at end of file
diff --git a/asteroid/test-suites/run-tests.py b/asteroid/test-suites/run-tests.py
index 3e2d646f..6324ac5c 100755
--- a/asteroid/test-suites/run-tests.py
+++ b/asteroid/test-suites/run-tests.py
@@ -4,20 +4,22 @@
 # general testsuite driver
 ################################
 
-# the following is a list of directories of test cases the script will run
+# the following is a list of directories of test cases
 
 dirs = [
 	    'action-tests',
-        'first-class-redundant-pattern-tests',
+        'programs',
         'redundant-pattern-test',
         'ref-programs',
         'regression-tests',
         'ug-programs',
        ]
 
+# the exclusion list allows you to eliminate certain tests from the 
+# current run
+# TODO: make names test suite sensitive
 #exclusion_list = ['test015.ast']
 exclusion_list = []
-
 if exclusion_list:
     print("Exclusion list: {}".format(exclusion_list))
 
@@ -51,15 +53,20 @@
 # so that we can easily find our Asteroid modules
 (parent_dir,_) = os.path.split(file_path)
 sys.path.append(parent_dir)
-
 from interp import interp
 
+n_tests = 0
 for d in dirs:
-    tests = os.listdir(d)
-    tests.sort()
-    tests = list(set(tests) - set(exclusion_list))
+    # assemble the test list
+    test_list = os.listdir(d)
+    test_list = list(set(test_list) - set(exclusion_list))
+    test_list.sort()
+    n_tests += len(test_list)
+    # set the ASTEROIDPATH environment variable
+    old_val = os.getenv('ASTEROIDPATH')
+    os.environ['ASTEROIDPATH'] = d
 
-    for testname in tests:
+    for testname in test_list:
         # check that we are actually looking at test case
         if testname[-3:] == "ast":
             # if a <testname>-io.txt file exists map stdin to it
@@ -71,5 +78,13 @@
             print("**********"+d+"/"+testname+"************")
             print(p)
             print("**********output***********")
-            interp(p,exceptions=verbose_failure,redundancy=redundancy)
+            interp(p,
+                   exceptions=verbose_failure,
+                   redundancy=redundancy)
             f.close()
+    if old_val:
+        os.environ['ASTEROIDPATH'] = old_val
+    else:
+        del os.environ['ASTEROIDPATH']
+        
+print("Number of test cases:",n_tests)
diff --git a/asteroid/test-suites/ug-programs/prgm-003.ast b/asteroid/test-suites/ug-programs/prgm-003.ast
index f3779ce0..8c25a17f 100644
--- a/asteroid/test-suites/ug-programs/prgm-003.ast
+++ b/asteroid/test-suites/ug-programs/prgm-003.ast
@@ -1,13 +1,13 @@
     -- define first-class patterns
-    let POS_INT = pattern (x:%integer) if x > 0.
-    let NEG_INT = pattern (x:%integer) if x < 0.
+    let pos_int = pattern (x:%integer) if x > 0.
+    let neg_int = pattern (x:%integer) if x < 0.
 
     -- define our factorial function
     function fact
         with 0 do
             return 1
-        with n:*POS_INT do            -- use first pattern
+        with n:*pos_int do            -- use first pattern
             return n * fact (n-1).
-        with n:*NEG_INT do            -- use second pattern
+        with n:*neg_int do            -- use second pattern
             throw Error("undefined for "+n).
         end
diff --git a/asteroid/test-suites/ug-programs/prgm-004.ast b/asteroid/test-suites/ug-programs/prgm-004.ast
index 3e655040..a4f50663 100644
--- a/asteroid/test-suites/ug-programs/prgm-004.ast
+++ b/asteroid/test-suites/ug-programs/prgm-004.ast
@@ -1,1 +1,1 @@
-    let x:%string = "value: " + 1.
+    let x:%string = "value: " + tostring 1.
diff --git a/asteroid/test-suites/ug-programs/prgm-007.ast b/asteroid/test-suites/ug-programs/prgm-007.ast
index befc0059..3cec9b7f 100644
--- a/asteroid/test-suites/ug-programs/prgm-007.ast
+++ b/asteroid/test-suites/ug-programs/prgm-007.ast
@@ -1,2 +1,2 @@
     load system io.
-    io @println ("this is my list: " + [1,2,3]).
+    io @println ("this is my list: " + tostring [1,2,3]).
diff --git a/asteroid/test-suites/ug-programs/prgm-008a.ast b/asteroid/test-suites/ug-programs/prgm-008a.ast
index f4337f67..14f5ec7b 100644
--- a/asteroid/test-suites/ug-programs/prgm-008a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-008a.ast
@@ -1,4 +1,3 @@
-   load system type.
 
    -- define a function
    function inc with x do
@@ -6,4 +5,4 @@
    end
 
    -- show that 'inc' is of type 'function'
-   assert (type @gettype(inc) == "function").
\ No newline at end of file
+   assert (gettype(inc) == "function").
\ No newline at end of file
diff --git a/asteroid/test-suites/ug-programs/prgm-008b.ast b/asteroid/test-suites/ug-programs/prgm-008b.ast
new file mode 100644
index 00000000..254e60a3
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-008b.ast
@@ -0,0 +1,1 @@
+   let x = 1.1 + toreal(1).
\ No newline at end of file
diff --git a/asteroid/test-suites/ug-programs/prgm-008c.ast b/asteroid/test-suites/ug-programs/prgm-008c.ast
new file mode 100644
index 00000000..5f33705e
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-008c.ast
@@ -0,0 +1,7 @@
+   -- define a first-class pattern
+   let p = pattern (x:%integer) if x>0.
+
+   -- check the type of the value stored in p
+   assert (gettype(p) == "pattern").
+
+
diff --git a/asteroid/test-suites/ug-programs/prgm-009.ast b/asteroid/test-suites/ug-programs/prgm-009.ast
index 79ea85f1..790bf1b4 100644
--- a/asteroid/test-suites/ug-programs/prgm-009.ast
+++ b/asteroid/test-suites/ug-programs/prgm-009.ast
@@ -1,5 +1,3 @@
-    load system io.   
-
     let a = [1,2,3].          -- construct list a
     let b = [a@2, a@1, a@0].  -- reverse list a
-    io @println b.
+    assert (b == [3,2,1]).
diff --git a/asteroid/test-suites/ug-programs/prgm-009a.ast b/asteroid/test-suites/ug-programs/prgm-009a.ast
index 3b1d5253..37d12758 100644
--- a/asteroid/test-suites/ug-programs/prgm-009a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-009a.ast
@@ -1,5 +1,3 @@
-    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]
-    io @println b.
+    assert (b == [3,2,1]).
diff --git a/asteroid/test-suites/ug-programs/prgm-011.ast b/asteroid/test-suites/ug-programs/prgm-011.ast
index 2b1a2671..0e1facec 100644
--- a/asteroid/test-suites/ug-programs/prgm-011.ast
+++ b/asteroid/test-suites/ug-programs/prgm-011.ast
@@ -2,9 +2,9 @@
 
     -- build a list of odd values
     let a = [1 to 10 step 2].  -- list comprehension
-    io @println ("list: " + a).
+    io @println ("list: " + tostring a).
 
     -- reverse the list using a slice computed as comprehension
     let slice = [4 to 0 step -1]. -- list comprehension
     let b = a@slice.
-    io @println ("reversed list: " + b).
+    io @println ("reversed list: " + tostring b).
diff --git a/asteroid/test-suites/ug-programs/prgm-012.ast b/asteroid/test-suites/ug-programs/prgm-012.ast
index e44c738a..faf1b452 100644
--- a/asteroid/test-suites/ug-programs/prgm-012.ast
+++ b/asteroid/test-suites/ug-programs/prgm-012.ast
@@ -2,6 +2,6 @@
     load system math.
 
     let a = [1 to 10] @map (lambda with x do math @mod (x,2))
-                      @map (lambda with x do 1 if x else -1).
+                      @map (lambda with x do 1 if x==1 else -1).
 
     io @println a.
diff --git a/asteroid/test-suites/ug-programs/prgm-017.ast b/asteroid/test-suites/ug-programs/prgm-017.ast
index e3683a34..0997f349 100644
--- a/asteroid/test-suites/ug-programs/prgm-017.ast
+++ b/asteroid/test-suites/ug-programs/prgm-017.ast
@@ -19,4 +19,4 @@
     let Person(name,age,gender) = people@1.
 
     -- print out the member values
-    io @println (name + " is " + age + " years old and is a " +  gender + ".").
+    io @println (name + " is " + tostring age + " years old and is a " +  gender + ".").
diff --git a/asteroid/test-suites/ug-programs/prgm-019a.ast b/asteroid/test-suites/ug-programs/prgm-019a.ast
new file mode 100644
index 00000000..18e245a2
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-019a.ast
@@ -0,0 +1,6 @@
+    structure Foo with
+        data a.
+        data b.
+    end
+
+    let %Foo = Foo(1,2).
diff --git a/asteroid/test-suites/ug-programs/prgm-024.ast b/asteroid/test-suites/ug-programs/prgm-024.ast
index bb610428..4a00d07e 100644
--- a/asteroid/test-suites/ug-programs/prgm-024.ast
+++ b/asteroid/test-suites/ug-programs/prgm-024.ast
@@ -1,7 +1,6 @@
     load system io.
-    load system type.
 
-    let x = type @tointeger (io @input "Please enter an integer: ").
+    let x = tointeger (io @input "Please enter an integer: ").
 
     if x < 0 do
         let x = 0.
diff --git a/asteroid/test-suites/ug-programs/prgm-028.ast b/asteroid/test-suites/ug-programs/prgm-028.ast
index 3660b923..4cb4297b 100644
--- a/asteroid/test-suites/ug-programs/prgm-028.ast
+++ b/asteroid/test-suites/ug-programs/prgm-028.ast
@@ -3,9 +3,9 @@
     let p = (1,2).
 
     if p is (x,y,z) do
-        io @println ("it's a triple with: "+x+","+y+","+z)
+        io @println ("it's a triple with: "+ tostring x +","+ tostring y +","+ tostring z)
     elif p is (x,y) do
-        io @println ("it's a pair with: "+x+","+y).
+        io @println ("it's a pair with: "+ tostring x +","+ tostring y).
     else do
         io @println "it's something else".
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-031.ast b/asteroid/test-suites/ug-programs/prgm-031.ast
index ee7e2fcb..38ffb259 100644
--- a/asteroid/test-suites/ug-programs/prgm-031.ast
+++ b/asteroid/test-suites/ug-programs/prgm-031.ast
@@ -9,4 +9,4 @@
             throw Error("factorial is not defined for "+n).
     end
 
-    io @println ("The factorial of 3 is: " + factorial 3).
+    io @println ("The factorial of 3 is: " + tostring (factorial 3)).
diff --git a/asteroid/test-suites/ug-programs/prgm-031a.ast b/asteroid/test-suites/ug-programs/prgm-031a.ast
index 6bc53b22..c65ee0d0 100644
--- a/asteroid/test-suites/ug-programs/prgm-031a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-031a.ast
@@ -9,4 +9,4 @@
             throw Error("factorial is not defined for "+n).
     end
 
-    io @println ("The factorial of 3 is: " + factorial 3).
+    io @println ("The factorial of 3 is: " + tostring (factorial 3)).
diff --git a/asteroid/test-suites/ug-programs/prgm-033.ast b/asteroid/test-suites/ug-programs/prgm-033.ast
index 8e7f52d5..d0b5ea7a 100644
--- a/asteroid/test-suites/ug-programs/prgm-033.ast
+++ b/asteroid/test-suites/ug-programs/prgm-033.ast
@@ -1,6 +1,5 @@
     load system io.
     load system random.
-    load system type.
 
     structure Head with
         data val.
@@ -18,7 +17,7 @@
             throw Tail i.
         end
     catch Head v do
-        io @println ("you win with "+type @tostring (v,type @stringformat (4,2))).
+        io @println ("you win with "+tostring (v,stringformat (4,2))).
     catch Tail v do
-        io @println ("you loose with "+type @tostring (v,type @stringformat (4,2))).
+        io @println ("you loose with "+tostring (v,stringformat (4,2))).
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-036.ast b/asteroid/test-suites/ug-programs/prgm-036.ast
index 5a3a2f16..486c6093 100644
--- a/asteroid/test-suites/ug-programs/prgm-036.ast
+++ b/asteroid/test-suites/ug-programs/prgm-036.ast
@@ -11,4 +11,4 @@
 
     -- pattern matching ignores function definitions
     let Person(name,age) = Person("Scarlett",28).
-    io @println (name+" is "+age+" years old").
+    io @println (name+" is "+ tostring age+" years old").
diff --git a/asteroid/test-suites/ug-programs/prgm-037.ast b/asteroid/test-suites/ug-programs/prgm-037.ast
index 7784cc17..84d5e39e 100644
--- a/asteroid/test-suites/ug-programs/prgm-037.ast
+++ b/asteroid/test-suites/ug-programs/prgm-037.ast
@@ -1,5 +1,4 @@
    load system io.
-   load system type.
 
    structure Dog with
       data name.
@@ -17,6 +16,6 @@
    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
+   for (Dog(name,tricks) if tostring tricks is ".*fetch.*") in dogs do
       io @println (name+" knows how to fetch").
    end
diff --git a/asteroid/test-suites/ug-programs/prgm-039.ast b/asteroid/test-suites/ug-programs/prgm-039.ast
index 0ea8da05..36eb8d98 100644
--- a/asteroid/test-suites/ug-programs/prgm-039.ast
+++ b/asteroid/test-suites/ug-programs/prgm-039.ast
@@ -1,20 +1,20 @@
-    let POS_INT = pattern (x:%integer) if x > 0.
-    let NEG_INT = pattern (x:%integer) if x < 0.
+    let pos_int = pattern (x:%integer) if x > 0.
+    let neg_int = pattern (x:%integer) if x < 0.
 
     function fact
         with 0 do
             return 1
-        with n:*POS_INT do
+        with n:*pos_int do
             return n * fact (n-1).
-        with *NEG_INT do
+        with *neg_int do
             throw Error("fact undefined for negative values").
     end
 
     function sign
         with 0 do
             return 1
-        with *POS_INT do
+        with *pos_int do
             return 1.
-        with *NEG_INT do
+        with *neg_int do
             return -1.
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-040.ast b/asteroid/test-suites/ug-programs/prgm-040.ast
deleted file mode 100644
index f1ed709a..00000000
--- a/asteroid/test-suites/ug-programs/prgm-040.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-    load system io.
-    let P = pattern ([a],[b]).
-    let a = 1.
-    let b = 2.
-    let v = eval P. -- use pattern to construct a value
-    io @println v.
diff --git a/asteroid/test-suites/ug-programs/prgm-042.ast b/asteroid/test-suites/ug-programs/prgm-042.ast
deleted file mode 100644
index 34161b42..00000000
--- a/asteroid/test-suites/ug-programs/prgm-042.ast
+++ /dev/null
@@ -1,72 +0,0 @@
-    load system io.
-
-    -----------------------------
-    structure Family
-    -----------------------------
-        with
-            data parent1.
-            data parent2.
-            data children.
-
-            function __init__
-                with (p1:%Parent,p2:%Parent,c:%Children) do
-                    let this @parent1 = p1.
-                    let this @parent2 = p2.
-                    let this @children = c.
-                end
-        end
-
-    -----------------------------
-    structure Parent
-    -----------------------------
-        with
-            data name.
-            function __init__
-                with name:%string do
-                    let this @name = name
-                end
-        end
-
-    -----------------------------
-    structure Children
-    -----------------------------
-        with
-            data list.
-
-            function __init__
-                with list:%list do
-                    let this @list = list.
-                end
-        end
-
-    -----------------------------
-    let FP = pattern
-    -----------------------------
-        with Family (Parent p1, Parent p2, Children c).
-
-    -----------------------------
-    function construct_family
-    -----------------------------
-        with (P,p1,p2,c) do
-            return eval P.  -- run pattern in reverse, construct object network.
-        end
-
-    -----------------------------
-    function destructure_family
-    -----------------------------
-        with (P,term) do
-            let *P = term.   -- pattern match, destructure object network.
-            return [p1,p2]+c.
-        end
-
-    -----------------------------
-    -- construct families
-    -----------------------------
-    let f1 = construct_family (FP,"Harry","Bridget",["Sue","Peter"]).
-    let f2 = construct_family (FP,"Margot","Selma",["Latisha","Rudolf"]).
-
-    -----------------------------
-    -- destructure families
-    -----------------------------
-    io @println (destructure_family (FP,f1)).
-    io @println (destructure_family (FP,f2)).
diff --git a/asteroid/test-suites/ug-programs/prgm-043.ast b/asteroid/test-suites/ug-programs/prgm-043.ast
index d85223e3..faca2aa9 100644
--- a/asteroid/test-suites/ug-programs/prgm-043.ast
+++ b/asteroid/test-suites/ug-programs/prgm-043.ast
@@ -1,8 +1,8 @@
    load system io.
 
-   let POS_INT = pattern %[v if (v is %integer) and v > 0]%.
+   let pos_int = pattern %[v if (v is %integer) and (v > 0)]%.
 
-   function add with (a:*POS_INT,b:*POS_INT) do
+   function add with (a:*pos_int,b:*pos_int) do
       return a+b.
    end
 
diff --git a/asteroid/test-suites/ug-programs/prgm-043a.ast b/asteroid/test-suites/ug-programs/prgm-043a.ast
index 20c09726..919faf8e 100644
--- a/asteroid/test-suites/ug-programs/prgm-043a.ast
+++ b/asteroid/test-suites/ug-programs/prgm-043a.ast
@@ -1,12 +1,12 @@
    -- declare a pattern that matches scalar values
-   let Scalar = pattern %[p if (p is %integer) or (p is %real)]%.
+   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)]%.
+   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
+      with (*pair bind [x as a1, y as a2], *pair bind [x as b1, y as b2]) do
          a1*b1 + a2*b2
    end
 
diff --git a/asteroid/test-suites/ug-programs/prgm-044.ast b/asteroid/test-suites/ug-programs/prgm-044.ast
index dc29d9f8..35324afb 100644
--- a/asteroid/test-suites/ug-programs/prgm-044.ast
+++ b/asteroid/test-suites/ug-programs/prgm-044.ast
@@ -1,13 +1,12 @@
     load system io.
-    load system type.
 
-    let pos_num = pattern %[x if type @isscalar(x) and x > 0]%.
+    let pos_num = pattern %[x if isscalar(x) and x > 0]%.
    
     structure Asteroid with
        data size.
        function __init_
           with v:*pos_num do
-             let this @size = v.
+             let this@size = v.
           end
     end
 
@@ -15,7 +14,7 @@
         data size.
        function __init_
           with v:*pos_num do
-             let this @size = v.
+             let this@size = v.
           end
     end
 
diff --git a/asteroid/test-suites/ug-programs/prgm-050.ast b/asteroid/test-suites/ug-programs/prgm-050.ast
index 7e2d67f1..8f2392a2 100644
--- a/asteroid/test-suites/ug-programs/prgm-050.ast
+++ b/asteroid/test-suites/ug-programs/prgm-050.ast
@@ -1,8 +1,7 @@
     load system io.
-    load system type.
 
     try
         let (x,y) = (1,2,3).
     catch e do
-        io @println ("something happened: "+type @tostring(e)).
+        io @println ("something happened: "+ tostring e).
     end
diff --git a/asteroid/test-suites/ug-programs/prgm-051.ast b/asteroid/test-suites/ug-programs/prgm-051.ast
index 9b8599c0..ff4c31cc 100644
--- a/asteroid/test-suites/ug-programs/prgm-051.ast
+++ b/asteroid/test-suites/ug-programs/prgm-051.ast
@@ -2,4 +2,4 @@
 
     let a = 1.
     let b = 2.
-    io @println ("a + b = " + (a + b)).
+    io @println ("a + b = " + tostring (a + b)).
diff --git a/asteroid/test-suites/ug-programs/prgm-052.ast b/asteroid/test-suites/ug-programs/prgm-052.ast
index 98c5d197..2f5e6bd3 100644
--- a/asteroid/test-suites/ug-programs/prgm-052.ast
+++ b/asteroid/test-suites/ug-programs/prgm-052.ast
@@ -1,20 +1,19 @@
     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)).
+    let b = tostring(true,stringformat(10)).
     io @println b.
 
-    let i = type @tostring(5,type @stringformat(5)).
+    let i = tostring(5,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)).
+    let s = tostring("hello there!",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)).
+    let r = tostring(math@pi,stringformat(6,3)).
     io @println r.
diff --git a/asteroid/test-suites/ug-programs/prgm-054.ast b/asteroid/test-suites/ug-programs/prgm-054.ast
index bac775a6..a988fd08 100644
--- a/asteroid/test-suites/ug-programs/prgm-054.ast
+++ b/asteroid/test-suites/ug-programs/prgm-054.ast
@@ -1,7 +1,6 @@
     load system io.
-    load system type.
 
-    let i if i > 0  = type @tointeger(io @input("Please enter a positive integer value: ")).
+    let i if i > 0  = tointeger(io @input("Please enter a positive integer value: ")).
 
     for k in 1 to i do
         io @println k.
diff --git a/asteroid/test-suites/ug-programs/prgm-055.ast b/asteroid/test-suites/ug-programs/prgm-055.ast
index ff4e64c2..c6d3dddd 100644
--- a/asteroid/test-suites/ug-programs/prgm-055.ast
+++ b/asteroid/test-suites/ug-programs/prgm-055.ast
@@ -1,5 +1,5 @@
     load system io.
     load system math.
 
-    let x = math @sin( math @pi / 2 ).
-    io @println("The sine of pi / 2 is " + x + ".").
+    let x = math @sin( math@pi / 2.0 ).
+    io @println("The sine of pi / 2 is " + tostring x + ".").