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

Issue:
Tik 171
This PR fixes issue #171. It now passes the expression result through term2string to properly print it out.

![](https://i.imgur.com/imv5GP6.png)
List comprehensions do not automatically detect descending lists
Lists comprehensions of the form `X to Y` do not automatically adjust the `step` value when `X > Y`.

Example:
```
let x = [5 to 0].  -- Returns an empty list
```
patterns returned by functions used in pattern-matching contexts
Asteroid should support something like the following,
```
function foo
   with *g() do -- g returns a pattern that we use in the with clause.
      <something>
  end
```
where patterns returned from functions should be able to be used in pattern matching contexts.
Another example,
```
let v = x is *goo().
```
The variable `v` is either true or false depending if the term stored in `x` matches the pattern returned 
by `goo` or not.
update documentation
* user guide: look for typos and formatting issues
* reference guide: 
    - add section about type system
    - add section about language syntax
    - add section about pattern matching: first-class patterns, constraint patterns, type match patterns 
bug in class-local scope
The following program incorrectly allows the user to access class member variables without object identity,
```
load system io.

structure A with
   data a.
   data b.
   data c.

   function __init__
      with none do
        io @println (a,b,c,__init__).
        io @println (this @a, this @b, this @c, this @__init__).
        io @println d.
      end
end

let o = A().
```
prints out,
```
(0,1,2,3)
(none,none,none,(function ...))
Error: members.ast: 12: 'd' is not defined
```
where the first line of the output prints out the memory indexes of the individual structure members, including function members.  The second line is correct output when the object identity is given.
The third line is the expected behavior for all member variables given without object identity.  

scientific notation for floating point values
We need to extend Asteroid in order to support scientific notation for floating point values, e.g.
```
let v = 1.234E20.
```
Expressions as statements with Rust/R semantics
The idea would be to support expressions as statements in order to more readily support the REPL but also to enable Rust/R like syntax, e.g.
```
function foo with none do
   1
end
```
would define a function that returns the constant 1.  If an expression appears as the last statement of the function then the value of that expression is the return value for the function.  This works particularly well with `lambda` functions, e.g.
```
assert ((lambda with x do x+1) 1 == 2).
```

Asteroid specific stack trace when an uncaught Asteroid Exception is thrown
Asteroid specific stack trace when an uncaught Asteroid Exception is thrown rather than a generic Python trace.


Discussion / hints:

Fix patch:
diff --git a/.github/workflows/generate_documentation.yml b/.github/workflows/generate_documentation.yml
new file mode 100644
index 00000000..7725fe98
--- /dev/null
+++ b/.github/workflows/generate_documentation.yml
@@ -0,0 +1,41 @@
+name: Documentation Generation
+on:
+    push:
+        branches:
+            - master
+            - dev-1.0.0
+env:
+    PYTHONPATH: ${{ github.workspace }}
+jobs:
+  gen-docs:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v2
+        
+      - uses: actions/checkout@v2
+        with:
+          persist-credentials: false # otherwise, the token used is the GITHUB_TOKEN, instead of your personal access token.
+          fetch-depth: 0 # otherwise, there would be errors pushing refs to the destination repository.
+
+      - name: Regenerate documentation
+        run: |
+          cd docs
+          # This is to keep github actions happy
+          bash generate_docs
+          cd ..
+
+      - name: Commit files
+        run: |
+          git add .
+          git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
+          git config --local user.name "github-actions[bot]"
+          (git commit -m "Updated documentation") || true
+
+      - name: Push changes
+        uses: ad-m/github-push-action@master
+        with:
+          github_token: ${{ secrets.GITHUB_TOKEN }}
+          branch: ${{ github.ref }}
+
+
diff --git a/.gitignore b/.gitignore
index 454e70f0..e1ba341d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@ __pycache__/
 *~
 dist/
 asteroid_lang.egg-info/
+action-test68.png
+.vscode/
\ No newline at end of file
diff --git a/asteroid.vim b/asteroid.vim
index 49a4bc83..74a1244f 100644
--- a/asteroid.vim
+++ b/asteroid.vim
@@ -12,7 +12,7 @@ if exists("b:current_syntax")
 endif
 
 syn keyword basic with end do load let for function structure in is pattern 
-syn keyword basic throw this system data global return to step if not
+syn keyword basic throw this system data global return to stride if not
 syn keyword basic else or and
 
 syn keyword delimeter escape
diff --git a/asteroid/__init__.py b/asteroid/__init__.py
index 41e17d9e..54084cd6 100644
--- a/asteroid/__init__.py
+++ b/asteroid/__init__.py
@@ -9,6 +9,7 @@
 import sys
 import os
 from asteroid.interp import interp
+from asteroid.repl import repl
 from asteroid.version import VERSION
 
 def display_help():
@@ -25,7 +26,7 @@ def display_help():
     print(" -p    disable prologue")
     print(" -h    display help")
     print(" -r    disable redundant pattern detector")
-    print(" -e    show full exceptions")
+    print(" -e    show Python exceptions")
 
 def main():
     # defaults for the flags - when the flag is set on the command line
@@ -52,7 +53,11 @@ def main():
             sys.exit(0)
         flags[fl] = not flags[fl]
 
-    if flags['-h'] or len(sys.argv) == 1:
+    if len(sys.argv) == 1:
+        repl()
+        sys.exit(0)
+
+    if flags['-h']:
         display_help()
         sys.exit(0)
 
diff --git a/asteroid/frontend.py b/asteroid/frontend.py
index 3b2dfa55..b95fd20e 100644
--- a/asteroid/frontend.py
+++ b/asteroid/frontend.py
@@ -8,8 +8,8 @@
 import sys
 from pathlib import Path, PurePath
 
-from asteroid.globals import asteroid_file_suffix
-from asteroid.lex import Lexer
+from asteroid.globals import asteroid_file_suffix, ExpectationError
+from asteroid.lex import Lexer, token_lookup
 from asteroid.state import state, warning
 
 ###########################################################################################
@@ -44,11 +44,10 @@ def dbg_print(string):
     } | ops
 
 exp_lookahead = {
-    'QUOTE',
     'PATTERN',
     'LCONSTRAINT',} | primary_lookahead
 
-exp_lookahead_no_ops = exp_lookahead - ops - {'QUOTE'}
+exp_lookahead_no_ops = exp_lookahead - ops
 
 primary_lookahead_no_ops = exp_lookahead_no_ops
 
@@ -63,7 +62,6 @@ def dbg_print(string):
     'LET',
     'LOAD',
     'LOOP',
-    'NONLOCAL',
     'REPEAT',
     'RETURN',
     'STRUCTURE',
@@ -71,7 +69,7 @@ def dbg_print(string):
     'TRY',
     'WHILE',
     #'WITH',
-    } | primary_lookahead
+    } | exp_lookahead
 
 ###########################################################################################
 class Parser:
@@ -92,8 +90,8 @@ def prog(self):
         dbg_print("parsing PROG")
         sl = self.stmt_list()
         if not self.lexer.EOF():
-            raise SyntaxError("expected 'EOF' found '{}'." \
-                              .format(self.lexer.peek().type))
+            raise SyntaxError("expected 'EOF' found {}." \
+                              .format(token_lookup(self.lexer.peek().type)))
         else:
             dbg_print("parsing EOF")
         return sl
@@ -107,6 +105,7 @@ def stmt_list(self):
         sl = []
         while self.lexer.peek().type in stmt_lookahead:
             sl += [('lineinfo', state.lineinfo)]
+            sl += [('clear-ret-val',)]
             sl += [self.stmt()]
         return ('list', sl)
 
@@ -119,7 +118,6 @@ def stmt_list(self):
     #    : '.' // NOOP
     #    | LOAD SYSTEM? (STRING | ID) '.'?
     #    | GLOBAL id_list '.'?
-    #    | NONLOCAL id_list '.'?
     #    | ASSERT exp '.'?
     #    | STRUCTURE ID WITH struct_stmts END
     #    | TRAIT ID WITH trait_stmts END
@@ -134,7 +132,7 @@ def stmt_list(self):
     #    | TRY stmt_list (CATCH pattern DO stmt_list)+ END
     #    | THROW exp '.'?
     #    | function_def
-    #    | call_or_index '.'?
+    #    | exp '.'?
     def stmt(self):
         dbg_print("parsing STMT")
         tt = self.lexer.peek().type  # tt - Token Type
@@ -151,6 +149,8 @@ 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)
+            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))
@@ -220,13 +220,6 @@ def stmt(self):
             self.lexer.match_optional('DOT')
             return ('global', id_list)
 
-        elif tt == 'NONLOCAL':
-            dbg_print("parsing NONLOCAL")
-            self.lexer.match('NONLOCAL')
-            id_list = self.id_list()
-            self.lexer.match_optional('DOT')
-            return ('nonlocal', id_list)
-
         elif tt == 'ASSERT':
             dbg_print("parsing ASSERT")
             self.lexer.match('ASSERT')
@@ -272,7 +265,10 @@ def stmt(self):
             self.lexer.match('FOR')
             e = self.exp()
             if e[0] != 'in':
-                raise SyntaxError("expected 'in' expression in for loop")
+                raise ExpectationError(
+                        expected="'in' expression in for loop",
+                        found=token_lookup(self.lexer.peek().type))
+
             self.lexer.match('DO')
             sl = self.stmt_list()
             self.lexer.match('END')
@@ -396,10 +392,10 @@ def stmt(self):
             self.lexer.match_optional('DOT')
             return ('throw', e)
 
-        elif tt in primary_lookahead:
-            v = self.call_or_index()
+        elif tt in exp_lookahead:
+            v = self.exp()
             self.lexer.match_optional('DOT')
-            return v
+            return ('set-ret-val', v)
 
         else:
             raise SyntaxError("syntax error at '{}'"
@@ -520,41 +516,27 @@ def body_defs(self):
 
         return ('body-list', ('list', body_list))
 
-    ###########################################################################################
-    # pattern
-    #    : exp
-    def pattern(self):
-        dbg_print("parsing PATTERN")
-        e = self.exp()
-        return e
-
     ###########################################################################################
     # exp
-    #    : quote_exp
+    #    : pattern
     def exp(self):
         dbg_print("parsing EXP")
-        v = self.quote_exp()
+        v = self.pattern()
         return v
 
     ###########################################################################################
-    # quote_exp
-    #    : QUOTE exp
-    #    | PATTERN WITH? exp
+    # pattern
+    #    : PATTERN WITH? exp
     #    | '%[' exp ']%'
     #    | head_tail
-    def quote_exp(self):
-        dbg_print("parsing QUOTE_EXP")
+    def pattern(self):
+        dbg_print("parsing PATTERN")
 
-        if self.lexer.peek().type == 'QUOTE':
-            self.lexer.match('QUOTE')
-            v = self.exp()
-            return ('quote', v)
-        # 'pattern with' is just the long version of the quote char
-        elif self.lexer.peek().type == 'PATTERN':
+        if self.lexer.peek().type == 'PATTERN':
             self.lexer.match('PATTERN')
             self.lexer.match_optional('WITH')
             v = self.exp()
-            return ('quote', v)
+            return ('pattern', v)
         elif self.lexer.peek().type == 'LCONSTRAINT': #constraint-only pattern match
             self.lexer.match('LCONSTRAINT')
             v = self.exp()
@@ -643,18 +625,18 @@ def compound(self):
         elif tt == 'TO':
             self.lexer.match('TO')
             v2 = self.exp()
-            if self.lexer.peek().type == 'STEP':
-                self.lexer.match('STEP')
+            if self.lexer.peek().type == 'STRIDE':
+                self.lexer.match('STRIDE')
                 v3 = self.exp()
                 return ('raw-to-list',
                         ('start', v),
                         ('stop', v2),
-                        ('step', v3))
+                        ('stride', v3))
             else:
                 return ('raw-to-list',
                         ('start', v),
                         ('stop', v2),
-                        ('step', ('integer', '1')))
+                        ('stride', ('integer', '1')))
 
         else:
             return v
@@ -778,14 +760,14 @@ def call_or_index(self):
     #    | FALSE
     #    | NONE
     #    | ID
-    #    | '*' ID         // "dereference" a variable during pattern matching
+    #    | '*' call_or_index /* pattern dereferencing */
     #    | 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
+    #    | '(' tuple_stuff ')' /* tuple/parenthesized expr */
+    #    | '[' list_stuff ']'  /* list or list access */
     #    | function_const
     #    | TYPEMATCH // TYPEMATCH == '%'<typename>
     def primary(self):
@@ -823,8 +805,8 @@ def primary(self):
 
         elif tt == 'TIMES':
             self.lexer.match('TIMES')
-            id_tok = self.lexer.match('ID')
-            return ('deref', ('id', id_tok.value))
+            v = self.call_or_index()
+            return ('deref', v)
 
         elif tt == 'NOT':
             self.lexer.match('NOT')
@@ -884,9 +866,12 @@ def primary(self):
             return ('typematch', tok.value)
 
         else:
-            raise SyntaxError(
-                "syntax error at '{}'"
-                .format(self.lexer.peek().value))
+            raise ExpectationError(
+                expected='expression',
+                found=token_lookup(self.lexer.peek().type))
+
+            #raise SyntaxError("syntax error at '{}'"
+                # .format(self.lexer.peek().value))
 
     ###########################################################################################
     # tuple_stuff
diff --git a/asteroid/globals.py b/asteroid/globals.py
index 7644a543..98edc0bc 100644
--- a/asteroid/globals.py
+++ b/asteroid/globals.py
@@ -63,7 +63,7 @@ def __init__(self, value):
         self.value = value
 
     def __str__(self):
-        return(repr(self.value))
+        return(str(self.value))
 
 #########################################################################
 class PatternMatchFailed(Exception):
@@ -71,7 +71,7 @@ def __init__(self, value):
         self.value = "pattern match failed: " + value
 
     def __str__(self):
-        return(repr(self.value))
+        return(self.value)
 
 #########################################################################
 class NonLinearPatternError(Exception):
@@ -79,8 +79,17 @@ def __init__(self, value):
         self.value = "non-linear pattern error: " + value
 
     def __str__(self):
-        return(repr(self.value))
+        return(self.value)
+
+#########################################################################
+class ExpectationError(Exception):
+    def __init__(self, found, expected):
+        self.found_EOF = (found == 'EOF')
+        self.value = "expected {} found {}.".format(str(expected), str(found))
 
+    def __str__(self):
+        return(self.value)
+        
 ##############################################################################################
 # *** Part of the Redundant Pattern Detector ***
 #
@@ -140,3 +149,24 @@ def __str__(self):
 }
 
 ###########################################################################################
+# list of structures that constitute patterns
+
+patterns = {
+    'pattern',
+    'id',
+    'string',
+    'real',
+    'integer',
+    'list',
+    'tuple',
+    'boolean',
+    'none',
+    'object',
+    'struct',
+    'typematch',
+}
+
+###########################################################################################
+# list of structures that a pattern type-pattern will subsume/overlap
+
+pattern_subsumes = patterns - {'id'}
\ No newline at end of file
diff --git a/asteroid/grammar.txt b/asteroid/grammar.txt
index e7dd89d6..04358b89 100644
--- a/asteroid/grammar.txt
+++ b/asteroid/grammar.txt
@@ -1,141 +1,149 @@
-////////////////////////////////////////////////////////////////////////////////////////
-// Grammar for Asteroid written in EBNF/PEG format.
-// (c) University of Rhode Island
-////////////////////////////////////////////////////////////////////////////////////////
-// statements
-
-prog
-  : stmt_list
-
-stmt_list
-  : stmt*
-
-stmt
-  : '.' // NOOP
-  | LOAD SYSTEM? (STRING | ID) '.'?
-  | GLOBAL id_list '.'?
-  | NONLOCAL 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 '.'?
-  | IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE DO? stmt_list)? END
-  | MATCH exp WITH? (CASE pattern DO stmt_list)+ (OTHERWISE DO? stmt_list)? END
-  | TRY DO? stmt_list (CATCH pattern DO stmt_list)+ END
-  | THROW exp '.'?
-  | BREAK '.'?
-  | RETURN exp? '.'?
-  | function_def
-  | call_or_index '.'?
-
-function_def
-  : FUNCTION ID body_defs END
-
-body_defs
-  : WITH pattern DO stmt_list (WITH pattern DO stmt_list)*
-
-data_stmt
-  : DATA ID
-
-struct_stmt
-  : data_stmt  '.'?
-  | function_def '.'?
-  | '.'
-
-struct_stmts
-  : struct_stmt*
-
-id_list
-  : ID (',' ID)*
-
-////////////////////////////////////////////////////////////////////////////////////////
-// 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.
-
-pattern
-  : exp
-
-exp
-  : quote_exp
-
-quote_exp
-  : QUOTE exp
-  | PATTERN WITH? exp
-  | '%[' exp ']%'      // constraint-only pattern match
-  | 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.
-conditional
-  : compound (IF exp (ELSE exp)?)?
-
-compound
-  : logic_exp0
-      (
-         (IS pattern) |
-         (IN exp) |               // exp has to be a list
-         (TO exp (STEP exp)?) |   // list comprehension
-      )?
-
-logic_exp0
-  : logic_exp1 (OR logic_exp1)*
-
-logic_exp1
-  : rel_exp0 (AND rel_exp0)*
-
-rel_exp0
-  : rel_exp1 (('==' | '=/=' ) rel_exp1)*
-
-rel_exp1
-  : arith_exp0 (('<=' | '<'  | '>=' | '>') arith_exp0)*
-
-arith_exp0
-  : arith_exp1 (('+' | '-') arith_exp1)*
-
-arith_exp1
-  : call_or_index (('*' | '/') call_or_index)*
-
-call_or_index
-  : primary (primary | '@' primary)* (':' pattern)?  // named pattern when ': pattern' exists
-
-primary
-  : INTEGER
-  | REAL
-  | STRING
-  | TRUE
-  | FALSE
-  | NONE
-  | ID
-  | '*' ID         // "dereference" a variable during pattern matching
-  | 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
-  | function_const
-  | TYPEMATCH           // TYPEMATCH == '%'<typename>
-
-tuple_stuff
-  : exp (',' exp?)*
-  | empty
-
-list_stuff
-  : exp (',' exp)*
-  | empty
-
-function_const
-  : LAMBDA body_defs
+/**************************************************************************************
+ 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.
+ **************************************************************************************/
+  ////////////////////////////////////////////////////////////////////////////////////////
+  // statements
+
+  prog
+    : stmt_list
+
+  stmt_list
+    : stmt*
+
+  stmt
+    : '.' // NOOP
+    | LOAD SYSTEM? (STRING | 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 '.'?
+    | 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 '.'?
+    | BREAK '.'?
+    | RETURN exp? '.'?
+    | function_def
+    | exp '.'?
+
+  function_def
+    : FUNCTION ID body_defs END
+
+  body_defs
+    : WITH pattern DO stmt_list (WITH pattern DO stmt_list)*
+
+  data_stmt
+    : DATA ID
+
+  struct_stmt
+    : data_stmt  '.'?
+    | function_def '.'?
+    | '.'
+
+  struct_stmts
+    : struct_stmt*
+
+  id_list
+    : ID (',' ID)*
+
+  ////////////////////////////////////////////////////////////////////////////////////////
+  // 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.
+  */
+  exp
+    : pattern
+
+  pattern
+    : PATTERN WITH? exp
+    | '%[' exp ']%'      /* constraint-only pattern match */
+    | 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.
+  */
+  conditional
+    : compound (IF exp (ELSE exp)?)?
+
+  compound
+    : logic_exp0
+        (
+           (IS pattern) |
+           (IN exp) |               /* exp has to be a list */
+           (TO exp (STRIDE exp)?) |   /* list comprehension */
+        )?
+
+  logic_exp0
+    : logic_exp1 (OR logic_exp1)*
+
+  logic_exp1
+    : rel_exp0 (AND rel_exp0)*
+
+  rel_exp0
+    : rel_exp1 (('==' | '=/=' ) rel_exp1)*
+
+  rel_exp1
+    : arith_exp0 (('<=' | '<'  | '>=' | '>') arith_exp0)*
+
+  arith_exp0
+    : arith_exp1 (('+' | '-') arith_exp1)*
+
+  arith_exp1
+    : call_or_index (('*' | '/') call_or_index)*
+
+  call_or_index
+    : primary (primary | '@' primary)* (':' pattern)?  /* named pattern when ': pattern' exists */
+
+  ////////////////////////////////////////////////////////////////////////////////////////
+  // primary expressions/patterns
+
+  primary
+    : INTEGER
+    | REAL
+    | STRING
+    | TRUE
+    | FALSE
+    | NONE
+    | ID
+    | '*' call_or_index   /* 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 */
+    | function_const
+    | TYPEMATCH           // TYPEMATCH == '%'<typename>
+
+  tuple_stuff
+    : exp (',' exp?)*
+    | empty
+
+  list_stuff
+    : exp (',' exp)*
+    | empty
+
+  function_const
+    : LAMBDA body_defs
diff --git a/asteroid/interp.py b/asteroid/interp.py
index 6497f2fd..74a48b2a 100644
--- a/asteroid/interp.py
+++ b/asteroid/interp.py
@@ -1,7 +1,7 @@
 ###########################################################################################
 # Asteroid interpreter
 #
-# (c) Lutz Hamel, University of Rhode Island
+# (c) University of Rhode Island
 ###########################################################################################
 
 import os
@@ -10,7 +10,7 @@
 from asteroid.globals import *
 from asteroid.support import *
 from asteroid.frontend import Parser
-from asteroid.state import state
+from asteroid.state import state, dump_trace
 from asteroid.walk import walk
 
 # the prologue file is expected to be in the 'modules' folder
@@ -24,10 +24,12 @@ def interp(input_stream,
            symtab_dump=False,
            exceptions=False,
            redundancy=True,
-           prologue=True):
+           prologue=True,
+           initialize_state = True):
     try:
         # initialize state
-        state.initialize()
+        if initialize_state:
+            state.initialize(input_name)
 
         #lhh
         #print("path[0]: {}".format(sys.path[0]))
@@ -38,7 +40,6 @@ def interp(input_stream,
 
         # read in prologue
         if prologue:
-
             prologue_file = ''
             prologue_file_base = os.path.join('modules', prologue_name)
             module_path = os.path.join(os.path.split(os.path.abspath(__file__))[0], prologue_file_base)
@@ -74,31 +75,38 @@ def interp(input_stream,
         if symtab_dump:
             state.symbol_table.dump()
 
+    # Note: all exceptions generated by Asteroid should go through the handler
+    #       for 'Exception' unless the exception needs special handling like
+    #       'ThrowValue' or 'ReturnValue' etc.
     except ThrowValue as throw_val:
+        dump_trace()
         # handle exceptions using the standard Error constructor
         module, lineno = state.lineinfo
         if throw_val.value[0] == 'apply' and throw_val.value[1][1] == 'Error':
             (APPLY, (ID, id), (APPLY, error_obj, rest)) = throw_val.value
-            print("Error: {}: {}: {}".format(module, lineno, term2string(error_obj)))
+            print("error: {}: {}: {}".format(module, lineno, term2string(error_obj)))
         else:
-            print("Error: {}: {}: unhandled Asteroid exception: {}"
+            print("error: {}: {}: unhandled Asteroid exception: {}"
                   .format(module, lineno, term2string(throw_val.value)))
-
-        sys.exit(1)
+        # needed for REPL
+        if not exceptions:
+            sys.exit(1)
 
     except ReturnValue as inst:
+        dump_trace()
         module, lineno = state.lineinfo
-        print("Error: {}: {}: return statement used outside a function environment"
+        print("error: {}: {}: return statement used outside a function environment"
               .format(module, lineno))
-        sys.exit(1)
-
-    except RedundantPatternFound as e:
-        print("Error:  {}".format(e))
-        sys.exit(1)
+        # needed for REPL
+        if not exceptions:
+            sys.exit(1)
 
-    except NonLinearPatternError as e:
-        print("Error:  {}".format(e))
-        sys.exit(1)
+    except  KeyboardInterrupt as e:
+        dump_trace()
+        print("error: keyboard interrupt")
+        # needed for REPL
+        if not exceptions:
+            sys.exit(1)
 
     except Exception as e:
         if exceptions: # rethrow the exception so that you can see the full backtrace
@@ -106,14 +114,16 @@ def interp(input_stream,
                 state.symbol_table.dump()
             raise e
         else:
+            dump_trace()
             module, lineno = state.lineinfo
-            print("Error: {}: {}: {}".format(module, lineno, e))
-            sys.exit(1)
-
-    except  KeyboardInterrupt as e:
-            print("Error: keyboard interrupt")
-            sys.exit(1)
-
-    except  BaseException as e:
-            print("Error: {}".format(e))
+            print("error: {}: {}: {}".format(module, lineno, e))
+            # needed for REPL
+            if not exceptions:
+                sys.exit(1)
+
+    except BaseException as e:
+        dump_trace()
+        print("error: {}".format(e))
+        # needed for REPL
+        if not exceptions:
             sys.exit(1)
diff --git a/asteroid/lex.py b/asteroid/lex.py
index 63813950..61cc09ba 100644
--- a/asteroid/lex.py
+++ b/asteroid/lex.py
@@ -7,6 +7,7 @@
 import re
 
 from asteroid.state import state, warning
+from asteroid.globals import ExpectationError
 
 # table that specifies the token value and type for keywords
 keywords = {
@@ -33,14 +34,13 @@
     'let'           : 'LET',
     'load'          : 'LOAD',
     'loop'          : 'LOOP',
-    'nonlocal'      : 'NONLOCAL',
     'not'           : 'NOT',
     'or'            : 'OR',
     'orwith'        : 'ORWITH',
     'pattern'       : 'PATTERN',
     'repeat'        : 'REPEAT',
     'return'        : 'RETURN',
-    'step'          : 'STEP',
+    'stride'        : 'STRIDE',
     'structure'     : 'STRUCTURE',
     'system'        : 'SYSTEM',
     'throw'         : 'THROW',
@@ -58,41 +58,40 @@
 # this table defines tokens whose value is defined by a
 # regular expression.
 token_specs = [
-#   value:                          type:
-    (r'([0-9]*[.])?[0-9]+',         'NUMBER'),
-    (r'"([^"]|\\"|\\)*"',           'STRING'),
-    (r'(--.*)|(\#.*)',              'COMMENT'),
-    (r'[a-zA-Z_][a-zA-Z_0-9]*',     'ID'),
-    (r'\n',                         'NEWLINE'),
-    (r'[ \t]+',                     'WHITESPACE'),
-    (r'\%[a-zA-Z_][a-zA-Z_0-9]*',   'TYPEMATCH'),
-    (r'\+',                         'PLUS'),
-    (r'-',                          'MINUS'),
-    (r'\*',                         'TIMES'),
-    (r'/',                          'DIVIDE'),
-    (r'==',                         'EQ'),
-    (r'=/=',                        'NE'),
-    (r'<=',                         'LE'),
-    (r'<',                          'LT'),
-    (r'>=',                         'GE'),
-    (r'>',                          'GT'),
-    (r'@',                          'AT'),
-    (r'\%\[',                       'LCONSTRAINT'),
-    (r'\]\%',                       'RCONSTRAINT'),
-    (r'\(',                         'LPAREN'),
-    (r'\)',                         'RPAREN'),
-    (r'\[',                         'LBRACKET'),
-    (r'\]',                         'RBRACKET'),
-    (r':',                          'COLON'),
-    (r'\|',                         'BAR'),
-    (r'\.',                         'DOT'),
-    (r',',                          'COMMA'),
-    (r'=',                          'ASSIGN'),
-    (r'\'',                         'QUOTE'),
+#   value:                                        display:      type:
+    (r'[0-9]+([.][0-9]+)?((e|E)(\+|\-)?[0-9]+)?', "number",     'NUMBER'),
+    (r'"([^"]|\\"|\\)*"',                         "string",     'STRING'),
+    (r'(--.*)|(\#.*)',                            "comment",    'COMMENT'),
+    (r'[a-zA-Z_][a-zA-Z_0-9]*',                   "variable",   'ID'),
+    (r'\n',                                       "\n",         'NEWLINE'),
+    (r'[ \t]+',                                   "space/tab",  'WHITESPACE'),
+    (r'\%[a-zA-Z_][a-zA-Z_0-9]*',                 "%type",      'TYPEMATCH'),
+    (r'\+',                                       "'+'",        'PLUS'),
+    (r'-',                                        "'-'",        'MINUS'),
+    (r'\*',                                       "'*'",        'TIMES'),
+    (r'/',                                        "'/'",        'DIVIDE'),
+    (r'==',                                       "'=='",       'EQ'),
+    (r'=/=',                                      "'=/='",      'NE'),
+    (r'<=',                                       "'<='",       'LE'),
+    (r'<',                                        "'<'",        'LT'),
+    (r'>=',                                       "'>='",       'GE'),
+    (r'>',                                        "'>'",        'GT'),
+    (r'@',                                        "'@'",        'AT'),
+    (r'\%\[',                                     "'%['",       'LCONSTRAINT'),
+    (r'\]\%',                                     "']%'",       'RCONSTRAINT'),
+    (r'\(',                                       "'('",        'LPAREN'),
+    (r'\)',                                       "')'",        'RPAREN'),
+    (r'\[',                                       "'['",        'LBRACKET'),
+    (r'\]',                                       "']'",        'RBRACKET'),
+    (r':',                                        "':'",        'COLON'),
+    (r'\|',                                       "'|'",        'BAR'),
+    (r'\.',                                       "'.'",        'DOT'),
+    (r',',                                        "','",        'COMMA'),
+    (r'=',                                        "'='",        'ASSIGN'),
     # this is the catch-all pattern, it has to be
     # here do that we can report illegal characters
     # in the input.
-    (r'.',                          'MISMATCH'),
+    (r'.',                                        "unknown",    'MISMATCH'),
 ]
 
 # this table specifies token types that are used in the tokenizer
@@ -100,9 +99,29 @@
 implicit_token_types = [
     'INTEGER',
     'REAL',
-    'CMATCH',
 ]
 
+# A table that given a token type will return the expected value
+# a reverse token specification: given a type compute the value
+token_values = {}
+
+def init_token_values():
+    global token_values
+
+    # grab tokens from token_specs table
+    token_values.update({'INTEGER':'integer value'})
+    token_values.update({'REAL':'real value'})
+    token_values.update({'EOF':'EOF'})
+    for (_,display,type) in token_specs:
+        token_values.update({type:display})
+
+    # grab tokens from keywords table
+    for k in keywords:
+        token_values.update({keywords[k]:"'"+k+"'"})
+
+def token_lookup(type):
+    return token_values[type]
+
 class Token:
     def __init__(self,type,value,module,lineno):
         self.type = type
@@ -120,7 +139,7 @@ def tokenize(code):
     (module, line_num) = state.lineinfo
     # here we create a list of named patterns from the token_specs table
     # the name of the pattern is the token type
-    named_re_list = ['(?P<{}>{})'.format(type,re) for (re,type) in token_specs]
+    named_re_list = ['(?P<{}>{})'.format(type,re) for (re,_,type) in token_specs]
     # create one giant re that describes the token structure of the whole
     # language. we 'or' together all the re's on the named_re_list
     combined_re = '|'.join(named_re_list)
@@ -134,7 +153,7 @@ def tokenize(code):
         value = mo.group()
         # some special processing of tokens
         if type == 'NUMBER':
-            if '.' in value:
+            if '.' in value or 'e' in value or 'E' in value:
                 type = 'REAL'
                 value = float(value)
             else:
@@ -172,7 +191,10 @@ def tokenize(code):
         elif type == 'WHITESPACE':
             continue
         elif type == 'MISMATCH':
-            raise ValueError("unexpected character '{}'".format(value))
+            if value == '\"':
+                raise ExpectationError(expected='\"', found='EOF')
+            else:
+                raise ValueError("unexpected character '{}'".format(value))
         # put the token onto the tokens list
         tokens.append(Token(type, value, module, line_num))
     # always append an EOF token so we never run out of tokens
@@ -193,9 +215,11 @@ def __init__(self):
         # keep a set of all possible token types in our lexer
         # this let's us weed out bad match calls very easily
         self.token_types = \
-            set(type for (_,type) in token_specs) | \
+            set(type for (_,_,type) in token_specs) | \
             set(list(keywords.values())) | \
             set(implicit_token_types)
+        # init token value lookup
+        init_token_values()
 
     def input(self, input_string):
         self.tokens = tokenize(input_string)
@@ -226,8 +250,8 @@ def match(self, token_type):
         if token_type not in self.token_types:
             raise ValueError("unknown token type '{}'".format(token_type))
         elif token_type != self.curr_token.type:
-            raise ValueError("expected '{}' found '{}'."
-                             .format(token_type, self.curr_token.type))
+            raise ExpectationError(found=token_lookup(self.curr_token.type),
+                                   expected=token_lookup(token_type))
         else:
             dbg_print('matching {}'.format(token_type))
             ct = self.curr_token
diff --git a/asteroid/modules/bitwise.ast b/asteroid/modules/bitwise.ast
index c5d177a9..91bb887d 100644
--- a/asteroid/modules/bitwise.ast
+++ b/asteroid/modules/bitwise.ast
@@ -1,11 +1,18 @@
 ------------------------------------------------------------------
 -- bitwise.ast
 --
--- this module defines bitwise operations
+-- Defines bitwise operations
 --
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
+-- define the bitwise module object
+
+------------------------------------------------------------------
+structure __BITWISE_MODULE__
+------------------------------------------------------------------
+with
+
 ------------------------------------------------------------------
  -- Bitwise AND
 function band
@@ -172,3 +179,9 @@ x_val = state.symbol_table.lookup_sym('x')[1]
 __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 72a80ea5..2b341551 100644
--- a/asteroid/modules/dataframe.ast
+++ b/asteroid/modules/dataframe.ast
@@ -1,12 +1,15 @@
 ------------------------------------------------------------------
--- Asteroid DataFrames implemented using Python's Pandas lib.
+-- Defines the Asteroid DataFrames structure.
 --
 -- TODO: this is more of a proof of concept implementation
 -- demonstrating that we can have objects with escaped
 -- implementations.  DataFrames needs lots more functionality.
 ------------------------------------------------------------------
 
-structure DataFrame with
+------------------------------------------------------------------
+structure __DATAFRAME__
+------------------------------------------------------------------
+with
 
 ------------------------------------------------------------------
 data df.
@@ -156,4 +159,18 @@ this_val = state.symbol_table.lookup_sym('this')
 __retval__ = ('integer', df_val.shape[1])
 "
 end
-end -- structure
+end -- __DATAFRAME__
+
+------------------------------------------------------------------
+structure __DATAFRAME_MODULE__
+------------------------------------------------------------------
+with
+
+function dataframe with none do
+  return __DATAFRAME__().
+end
+
+end -- __DATAFRAME_MODULE__
+
+------------------------------------------------------------------
+let dataframe = __DATAFRAME_MODULE__().
diff --git a/asteroid/modules/hash.ast b/asteroid/modules/hash.ast
index 5c90bd00..07449628 100644
--- a/asteroid/modules/hash.ast
+++ b/asteroid/modules/hash.ast
@@ -7,7 +7,7 @@
 ------------------------------------------------------------------
 
 ------------------------------------------------------------------
-structure HashTable
+structure __HASHTABLE__
 ------------------------------------------------------------------
 -- Asteroid hash table implementation using Python dictionaries
 with
@@ -106,4 +106,18 @@ __retval__ = ('list', out_list)
 "
 end
 
-end -- HashTable
+end -- __HASHTABLE__
+
+------------------------------------------------------------------
+structure __HASH_MODULE__
+------------------------------------------------------------------
+with
+
+function hash with none do
+   return __HASHTABLE__().
+end
+
+end -- __HASH_MODULE__
+
+------------------------------------------------------------------
+let hash = __HASH_MODULE__().
diff --git a/asteroid/modules/io.ast b/asteroid/modules/io.ast
index fad3e5eb..8a2fe0ff 100644
--- a/asteroid/modules/io.ast
+++ b/asteroid/modules/io.ast
@@ -4,27 +4,17 @@
 -- this module implements the I/O system for Asteroid
 --
 -- (c) University of Rhode Island
-------------------------------------------------------------------
-function __raw_print__
-------------------------------------------------------------------
--- dumps the AST to screen
-with item do escape
-"
-from pprint import pprint
-item_val = state.symbol_table.lookup_sym('item')
-pprint(item_val)
-"
-return none
-end
+
+
+load system type.
 
 ------------------------------------------------------------------
 -- Basic file i/o
 ------------------------------------------------------------------
-structure FILE with
-
+structure __FILE__ with
 ------------------------------------------------------------------
+
 data fd.
-------------------------------------------------------------------
 
 ------------------------------------------------------------------
 function __init__
@@ -156,20 +146,26 @@ f_val.write(what_val[1])
 end
 
 ------------------------------------------------------------------
-end -- FILE
+end -- __FILE__
 ------------------------------------------------------------------
 
 
 
-
-
+-- define the io module object.
+------------------------------------------------------------------
+structure __IO_MODULE__ with
 ------------------------------------------------------------------
 
 -- Predefined standard stream constants
-
-let __STDIN__ = FILE("__STDIN__").
-let __STDOUT__ = FILE("__STDOUT__").
-let __STDERR__ = FILE("__STDERR__").
+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
 
 -- File I/O library functions
 ------------------------------------------------------------------
@@ -177,14 +173,14 @@ function open
 -- Open a file given a filename and mode
 ------------------------------------------------------------------
 with (name:%string, mode:%string) do
-   return FILE(name, mode).
+   return __FILE__(name, mode).
 end
 
 ------------------------------------------------------------------
 function close
 -- Close a given file
 ------------------------------------------------------------------
-with(file:%FILE) do
+with(file:%__FILE__) do
     file @close().
 end
 
@@ -192,11 +188,11 @@ end
 function read
 -- Return the contents of a given file
 ------------------------------------------------------------------
-with(file:%FILE) do
+with(file:%__FILE__) do
     return file @read().
 
 with none do
-    return __STDIN__@ read().
+    return this @__STDIN__ @ read().
 end
 
 ------------------------------------------------------------------
@@ -210,11 +206,10 @@ function readln
 -- been reached, while a blank line is represented by '\n',
 -- a string containing only a single newline.
 ------------------------------------------------------------------
-with(file:%FILE) do
+with(file:%__FILE__) do
     return file @readln().
-
 with none do
-    return __STDIN__@ readln().
+    return this @__STDIN__ @readln().
 end
 
 ------------------------------------------------------------------
@@ -222,15 +217,14 @@ function write
 -- Write to a given file
 ------------------------------------------------------------------
 with what:%string do
-
-__STDOUT__@ write(what).
+this @__STDOUT__ @write(what).
 
 escape "
 import sys
 sys.stdout.flush()
 "
 
-with(file:%FILE, what:%string) do
+with(file:%__FILE__, what:%string) do
     file @write(what).
 end
 
@@ -239,29 +233,27 @@ function writeln
 -- Write a complete line to a given file
 ------------------------------------------------------------------
 with what:%string do
-    __STDOUT__@ write(what + "\n").
+    this @__STDOUT__ @write(what + "\n").
 
-with(file:%FILE, what:%string) do
+with(file:%__FILE__, what:%string) do
     file @write(what + "\n").
 end
 ------------------------------------------------------------------
 
 -- Basic console I/O functions
 
-load system type.
-
 ------------------------------------------------------------------
 function println
 ------------------------------------------------------------------
 with item do
-    writeln(tostring item).
+    this @writeln(type @tostring item).
 end
 
 ------------------------------------------------------------------
 function print
 ------------------------------------------------------------------
 with item do
-    write(tostring item).
+    this @write(type @tostring item).
 end
 
 ------------------------------------------------------------------
@@ -269,8 +261,28 @@ function input
 ------------------------------------------------------------------
 -- input drops the trailing newline char
 with none do
-    return readln() @replace("\n","").
+    return this @readln() @replace("\n","").
 with prompt do
-    write (tostring prompt).
-    return readln() @replace("\n","").
+    this @write (type @tostring prompt).
+    return this @readln() @replace("\n","").
+end
+
+------------------------------------------------------------------
+function __raw_print__
+------------------------------------------------------------------
+-- dumps the AST to screen
+with item do escape
+"
+from pprint import pprint
+item_val = state.symbol_table.lookup_sym('item')
+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 80e6e9f2..3ac54a59 100644
--- a/asteroid/modules/math.ast
+++ b/asteroid/modules/math.ast
@@ -4,49 +4,43 @@
 -- this module implements the mathematical operators
 -- and constants.
 --
--- (c) Lutz Hamel, University of Rhode Island
-------------------------------------------------------------------
--- NOTE: escaped Python code can return a value to the parent
---       Asteroid code via the __retval__ return value register.
---       For examples see code below.
---
--- NOTE: 'promote' is the type promotion table for primitive
---       builtin types which implements the type hierarchy:
---
---             integer < real < string and list
+-- (c) University of Rhode Island
 ------------------------------------------------------------------
 
+structure __MATH_MODULE__ with
+
 ------------------------------------------------------------------
 -- Constants
 ------------------------------------------------------------------
+data pi.
+data e.
+data tau.
 
-------------------------------------------------------------------
-let pi = escape
-------------------------------------------------------------------
+function __init__ with none do
+
+let this @pi = escape
 "
 from math import pi
 global __retval__
 __retval__ = ('real',pi)
 "
 
-------------------------------------------------------------------
-let e = escape
-------------------------------------------------------------------
+let this @e = escape
 "
 from math import e
 global __retval__
 __retval__ = ('real',e)
 "
 
-------------------------------------------------------------------
-let tau = escape
-------------------------------------------------------------------
+let this @tau = escape
 "
 from math import tau
 global __retval__
 __retval__ = ('real',tau)
 "
 
+end -- __init__
+
 ------------------------------------------------------------------
 -- Power and logarithmic functions
 ------------------------------------------------------------------
@@ -107,7 +101,7 @@ val_b = state.symbol_table.lookup_sym('b')
 val_p = state.symbol_table.lookup_sym('p')
 
 if val_b[0] not in ['integer','real']:
-  raise ValueError('unsupported type {} for pow'.format(val_b[0]))
+  raise ValueError('unsupported type \'{}\' for pow'.format(val_b[0]))
 
 __retval__ = (val_b[0],val_b[1]**val_p[1])
 "
@@ -124,7 +118,7 @@ from math import sqrt
 
 val_a = state.symbol_table.lookup_sym('a')
 if val_a[0] not in ['integer','real']:
-  raise ValueError('unsupported type {} for sqrt'.format(val_a[0]))
+  raise ValueError('unsupported type \'{}\' for sqrt'.format(val_a[0]))
 __retval__ = ('real',sqrt(val_a[1]))
 "
 end
@@ -240,10 +234,10 @@ 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]))
+  raise ValueError('unsupported type \'{}\' for mod'.format(val_v[0]))
 
 if val_d[0] not in ['integer','real']:
-  raise ValueError('unsupported type {} for mod'.format(val_d[0]))
+  raise ValueError('unsupported type \'{}\' for mod'.format(val_d[0]))
 
 __retval__ = (promote(val_v[0],val_d[0]),val_v[1] % val_d[1])
 "
@@ -466,3 +460,7 @@ x_val = state.symbol_table.lookup_sym('x')
 __retval__ = ('real', math.radians(x_val[1]))
 "
 end
+
+end -- __MATH_MODULE__
+
+let math = __MATH_MODULE__()
diff --git a/asteroid/modules/pick.ast b/asteroid/modules/pick.ast
index 88f437f7..bb40b348 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 'pick'
@@ -22,7 +22,7 @@ structure Pick
   function pick with n:%integer do
       let l = [].
       for i in 1 to n do
-          let ix = randint(0, this @items @length()-1).
+          let ix = random @randint(0, this @items @length()-1).
           l @append(this @items @ix).
       end
       return l.
@@ -33,4 +33,18 @@ structure Pick
       let this @items = l.
   end
 
-end -- Pick
+end -- __PICK__
+
+------------------------------------------------------------------
+structure __PICK_MODULE__
+------------------------------------------------------------------
+with
+
+function pick 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 6acdabcf..10a72d22 100644
--- a/asteroid/modules/prologue.ast
+++ b/asteroid/modules/prologue.ast
@@ -54,14 +54,13 @@ elif item_val[0] == 'object':
 elif item_val[0] == 'struct':
     (STRUCT,
         (MEMBER_NAMES, (LIST, member_names)),
-        (STRUCT_MEMORY, (LIST, struct_memory)),
-        (STRUCT_SCOPE, t_struct_scope)) = item_val
+        (STRUCT_MEMORY, (LIST, struct_memory))) = item_val
     l = len(data_only(struct_memory))
     __retval__ = ('integer', l)
 
 else:
     raise ValueError(
-   	  'len expected a list, tuple, string, or structure got {}'
+   	  'len expected a list, tuple, string, or structure got \'{}\''
 	    .format(item_val[0]))
 "
 end
@@ -94,7 +93,7 @@ function range
   with (start:%integer,stop:%integer) do
     return [start to stop-1].
   with (start:%integer,stop:%integer,inc:%integer) do
-    return [start to stop-1 step inc].
+    return [start to stop-1 stride inc].
   with stop:%integer do
     return [0 to stop-1].
   end
@@ -228,7 +227,7 @@ this_val = state.symbol_table.lookup_sym('this')
 item_val = state.symbol_table.lookup_sym('item')
 
 if item_val[0] not in ['list', 'string', 'tuple']:
-    raise ValueError('extend expected a list, string, or tuple, got {}'
+    raise ValueError('extend expected a list, string, or tuple, got \'{}\''
                 .format(item_val[0]))
 
 __retval__ = ('list', this_val[1].extend(item_val[1]))
@@ -709,7 +708,7 @@ 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')
+    __retval__ = ('none', None)
 else:
     __retval__ = ('integer', val)
 "
diff --git a/asteroid/modules/random.ast b/asteroid/modules/random.ast
index c9aa4477..f160997e 100644
--- a/asteroid/modules/random.ast
+++ b/asteroid/modules/random.ast
@@ -6,6 +6,11 @@
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
+------------------------------------------------------------------
+structure __RANDOM_MODULE__
+------------------------------------------------------------------
+with
+
 ------------------------------------------------------------------
 function random
 ------------------------------------------------------------------
@@ -64,3 +69,8 @@ sd_val = state.symbol_table.lookup_sym('sd')
 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 d135f7fd..a3885203 100644
--- a/asteroid/modules/set.ast
+++ b/asteroid/modules/set.ast
@@ -8,6 +8,11 @@
 -- (c) Lutz Hamel, University of Rhode Island
 ------------------------------------------------------------------
 
+------------------------------------------------------------------
+structure __SET_MODULE__
+------------------------------------------------------------------
+with
+
 ------------------------------------------------------------------
 function toset
 ------------------------------------------------------------------
@@ -20,7 +25,7 @@ __retval__ = ('list', list(set(lst_val[1])))
 end
 
 ------------------------------------------------------------------
-function sdiff
+function diff
 ------------------------------------------------------------------
 with (a:%list,b:%list) do return escape
 "
@@ -32,7 +37,7 @@ __retval__ = ('list', list(set(a_val[1]) - set(b_val[1])))
 end
 
 ------------------------------------------------------------------
-function sunion
+function union
 ------------------------------------------------------------------
 with (a:%list,b:%list) do return escape
 "
@@ -44,7 +49,7 @@ __retval__ = ('list', list(set(a_val[1]) | set(b_val[1])))
 end
 
 ------------------------------------------------------------------
-function sintersection
+function intersection
 ------------------------------------------------------------------
 with (a:%list,b:%list) do return escape
 "
@@ -56,7 +61,7 @@ __retval__ = ('list', list(set(a_val[1]) & set(b_val[1])))
 end
 
 ------------------------------------------------------------------
-function sxunion
+function xunion
 -- elements in a or b but not both
 ------------------------------------------------------------------
 with (a:%list,b:%list) do return escape
@@ -67,3 +72,8 @@ b_val = state.symbol_table.lookup_sym('b')
 __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 3a0ad9eb..33c04bd2 100644
--- a/asteroid/modules/sort.ast
+++ b/asteroid/modules/sort.ast
@@ -13,6 +13,10 @@
 -- (c) University of Rhode Island
 ------------------------------------------------------------------
 
+------------------------------------------------------------------
+structure __SORT_MODULE__
+------------------------------------------------------------------
+with
 
 function sort
     with (_,[]) do
@@ -31,5 +35,9 @@ function sort
             end
         end
 
-        return sort(p,less) + [pivot] + sort(p,more).
+        return this @sort(p,less) + [pivot] + this @sort(p,more).
     end
+end -- __SORT_MODULE__
+
+------------------------------------------------------------------
+let sort = __SORT_MODULE__().
diff --git a/asteroid/modules/stream.ast b/asteroid/modules/stream.ast
index 4b4f84b6..b2c4a109 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
@@ -89,4 +89,19 @@ __retval__ = ('string', term2string(memory[0]))
 "
 end
 
-end -- Stream
+end -- __STREAM__
+
+
+------------------------------------------------------------------
+structure __STREAM_MODULE__
+------------------------------------------------------------------
+with
+
+function stream 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
index f097a4b6..91d716bf 100644
--- a/asteroid/modules/type.ast
+++ b/asteroid/modules/type.ast
@@ -6,6 +6,42 @@
 -- (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 --
 ------------------------------------------------------------------
@@ -53,31 +89,6 @@ __retval__ = ('boolean', bool(item_val[1]))
 "
 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.
-  function __init__
-    with (l:%integer,p:%integer) do
-      let this @length = l.
-      let this @precision = p.
-    with l:%integer do
-      let this @length = l.
-      let this @precision = none.
-    end
-end
-
 ------------------------------------------------------------------
 function tostring
 ------------------------------------------------------------------
@@ -85,37 +96,52 @@ function tostring
 -- if format values are given apply the
 -- formatting to the object.
 
-with (v:*TP,stringformat(w:%integer,none)) do
+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 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)) do return escape
+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)) do return escape
+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
 "
@@ -127,6 +153,19 @@ __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
+
 ------------------------------------------------------------------
 function tobase
 ------------------------------------------------------------------
@@ -190,3 +229,8 @@ else:
 __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 f0dbde25..5fd74165 100644
--- a/asteroid/modules/util.ast
+++ b/asteroid/modules/util.ast
@@ -8,6 +8,9 @@
 
 load system type.
 
+------------------------------------------------------------------
+structure __UTIL_MODULE__ with
+
 ------------------------------------------------------------------
 -- UTILITY FUNCTIONS --
 ------------------------------------------------------------------
@@ -62,7 +65,7 @@ end
 function sleep
 ------------------------------------------------------------------
 -- program sleep for secs seconds
-with secs if isscalar(secs) do escape
+with secs if type @isscalar(secs) do escape
 "
 import time
 secs_val = state.symbol_table.lookup_sym('secs')
@@ -138,3 +141,8 @@ item_val = state.symbol_table.lookup_sym('item')
 __retval__ = ('string', str(chr(item_val[1])))
 "
 end
+
+end -- __UTIL_MODULE__
+
+------------------------------------------------------------------
+let util = __UTIL_MODULE__().
diff --git a/asteroid/modules/vector.ast b/asteroid/modules/vector.ast
index bb15c80c..2f8716cd 100644
--- a/asteroid/modules/vector.ast
+++ b/asteroid/modules/vector.ast
@@ -10,7 +10,10 @@ load system util.
 load system type.
 
 ------------------------------------------------------------------
-function vop
+structure __VECTOR_MODULE__ with
+
+------------------------------------------------------------------
+function op
 ------------------------------------------------------------------
 -- worker function for actual vector arithmetic
 -- Note: it also implements vector/scalar arithmetic
@@ -18,39 +21,39 @@ 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").
   end
-  let v = zip(a,b).
+  let v = util @zip(a,b).
   return v @map(f).
-with (f:%function,a:%list,b if isscalar(b)) do
+with (f:%function,a:%list,b if type @isscalar(b)) do
   -- promote b to a vector
   let bv = [1 to a @length()] @map(lambda with _ do return b).
-  let v = zip(a,bv).
+  let v = util @zip(a,bv).
   return v @map(f).
-with (f:%function,a if isscalar(a),b:%list) do
+with (f:%function,a if type @isscalar(a),b:%list) do
   -- promote a to a vector
   let av = [1 to b @length()] @map(lambda with _ do return a).
-  let v = zip(av,b).
+  let v = util @zip(av,b).
   return v @map(f).
 end
 
 ------------------------------------------------------------------
-function vadd
+function add
 ------------------------------------------------------------------
 with (a,b) do
-  return vop(lambda with (x,y) do return x+y,a,b).
+  return this @op(lambda with (x,y) do return x+y,a,b).
 end
 
 ------------------------------------------------------------------
-function vsub
+function sub
 ------------------------------------------------------------------
 with (a,b) do
-  return vop(lambda with (x,y) do return x-y,a,b).
+  return this @op(lambda with (x,y) do return x-y,a,b).
 end
 
 ------------------------------------------------------------------
-function vmult
+function mult
 ------------------------------------------------------------------
 with (a,b) do
-  return vop(lambda with (x,y) do return x*y,a,b).
+  return this @op(lambda with (x,y) do return x*y,a,b).
 end
 
 ------------------------------------------------------------------
@@ -58,5 +61,9 @@ function dot
 -- computes the dot product of two lists
 ------------------------------------------------------------------
 with (a:%list,b:%list) do
-  return vmult(a,b) @reduce(lambda with (x,y) do return x+y).
+  return this @mult(a,b) @reduce(lambda with (x,y) do return x+y).
 end
+
+end -- __VECTOR_MODULE__
+
+let vector = __VECTOR_MODULE__().
diff --git a/asteroid/programs/calc/calc.ast b/asteroid/programs/calc/calc.ast
index 7c596f2a..bffac692 100644
--- a/asteroid/programs/calc/calc.ast
+++ b/asteroid/programs/calc/calc.ast
@@ -6,7 +6,7 @@
 -- provided input you will have to type <CR><Cntrl-D>
 -- Lutz Hamel, (c) University of Rhode Island
 
-load "io".
+load system io.
 load "lexer".
 
 -------------------------------------------------------------------------
@@ -86,7 +86,7 @@ function rootexp
 -- driver part of the script
 
 -- tokenize input
-let input = read().
+let input = io @read().
 let lexer = Lexer(tokenize(input)).
 #println lexer.
 
@@ -97,4 +97,4 @@ if not (lexer @eof()) do
 end
 
 -- print out the final value of the parsed and interpreted expression
-println val.
+io @println val.
diff --git a/asteroid/programs/calc/tokenizer.ast b/asteroid/programs/calc/tokenizer.ast
index afc36726..a30879b5 100644
--- a/asteroid/programs/calc/tokenizer.ast
+++ b/asteroid/programs/calc/tokenizer.ast
@@ -5,7 +5,7 @@
 -- Lutz Hamel, (c) University of Rhode Island
 
 load system type.
-load system "stream".
+load system stream.
 
 structure Token with
   data type.
@@ -13,18 +13,18 @@ structure Token with
   end
 
 function get_number
-  with input_stream:%Stream do
+  with input_stream do
     let number = "".
     while input_stream @peek() is "[0-9]" do
       let number = number + input_stream @get().
     end
-    return tointeger(number).
+    return type @tointeger(number).
   end
 
 function tokenize
   with input:%string do
-    let input_stream = Stream(input @explode()).
-    let output_stream = Stream([]).
+    let input_stream = stream @stream(input @explode()).
+    let output_stream = stream @stream([]).
     while not input_stream @eof() do
       let c = input_stream @peek().
       if c is "[0-9]" do
diff --git a/asteroid/programs/cls.ast b/asteroid/programs/cls.ast
index 7576e971..6f88da3a 100755
--- a/asteroid/programs/cls.ast
+++ b/asteroid/programs/cls.ast
@@ -1,11 +1,11 @@
 #!/usr/bin/env asteroid
-load "io".
-load "util".
-load "random".
+load system io.
+load system util.
+load system random.
 
-cls().
+util @cls().
 
 for i in 1 to 5 do
-    println ("Random value " + random()).
-    sleep(.5)
+    io @println ("Random value " + random @random()).
+    util @sleep(.5)
 end
diff --git a/asteroid/programs/df.ast b/asteroid/programs/df.ast
index e24d1a81..d1bbb44d 100644
--- a/asteroid/programs/df.ast
+++ b/asteroid/programs/df.ast
@@ -1,11 +1,11 @@
-load "dataframe".
-load "io".
+load system dataframe.
+load system io.
 
-let df = DataFrame().
+let df = dataframe @dataframe().
 df@read_csv("tennis.csv",true).
 
 let r = df@row(3).
-println(r).
+io @println(r).
 
 let c = df@col(3).
-println(c).
+io @println(c).
diff --git a/asteroid/programs/dogs.ast b/asteroid/programs/dogs.ast
index 53bfe2b5..3b2c4532 100644
--- a/asteroid/programs/dogs.ast
+++ b/asteroid/programs/dogs.ast
@@ -28,6 +28,6 @@ buddy @add_trick "sit stay".
 buddy @add_trick "roll over".
 
 -- print out all the dogs that know how to fetch
-for (Dog(name,tricks) if tostring(tricks) is ".*fetch.*") in [fido,buddy] do
-    println (name+" knows how to fetch").
+for (Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*") in [fido,buddy] do
+    io @println (name+" knows how to fetch").
 end
diff --git a/asteroid/programs/fact.ast b/asteroid/programs/fact.ast
index 3f8df326..077e7a74 100644
--- a/asteroid/programs/fact.ast
+++ b/asteroid/programs/fact.ast
@@ -3,7 +3,7 @@
 -- constrained inputs using pattern matching
 -- with type classes and conditional matching
 
-load "io".
+load system io.
 load "util".
 
 let POS_INT = pattern with (n:%integer) if n > 0.
@@ -19,8 +19,8 @@ function fact
     end
 
 try
-  let i = tointeger(input("Enter an integer value: ")).
-  println ("The factorial of "+i+" is: " + fact (i)).
+  let i = tointeger(io @input("Enter an integer value: ")).
+  io @println ("The factorial of "+i+" is: " + fact (i)).
 catch e do
-  println e.
+  io @println e.
 end
diff --git a/asteroid/programs/family.ast b/asteroid/programs/family.ast
index f80907d4..51c450b9 100644
--- a/asteroid/programs/family.ast
+++ b/asteroid/programs/family.ast
@@ -71,5 +71,5 @@ let f2 = construct_family(FP,"Margot","Selma",["Latisha","Rudolf"]).
 -----------------------------
 -- destructure families
 -----------------------------
-println(destructure_family(FP,f1)).
-println(destructure_family(FP,f2)).
+io @println(destructure_family(FP,f1)).
+io @println(destructure_family(FP,f2)).
diff --git a/asteroid/programs/formatted.ast b/asteroid/programs/formatted.ast
index 776d8bfc..63d08f78 100644
--- a/asteroid/programs/formatted.ast
+++ b/asteroid/programs/formatted.ast
@@ -1,2 +1,2 @@
-load "io".
-println "hello world!\n".
+load system io.
+io @println "hello world!\n".
diff --git a/asteroid/programs/guess.ast b/asteroid/programs/guess.ast
index 998fe32a..2b54d102 100644
--- a/asteroid/programs/guess.ast
+++ b/asteroid/programs/guess.ast
@@ -1,41 +1,43 @@
 -- guess that number game from http://inventwithpython.com/invent4thed/
 -- written by Lutz Hamel, (c) University of Rhode Island
 
-load "io".
-load "util".
-load "random".
-load "type".
+load system io.
+load system util.
+load system random.
+load system type.
 
-println "".
-println "     \||||||||||||||||||/".
-println "    - Guess that Number -".
-println "     /||||||||||||||||||\".
-println "".
+random @seed(42). -- make it predictable
 
+io @println "".
+io @println "     \||||||||||||||||||/".
+io @println "    - Guess that Number -".
+io @println "     /||||||||||||||||||\".
+io @println "".
 
-let name = input("Hello! What is your name? ").
+
+let name = io @input("Hello! What is your name? ").
 let guesses_made = 0.
-let number = randint(1, 20).
+let number = random @randint(1, 20).
 
-println (name + ", I am thinking of a number between 1 and 20, can you guess it?").
+io @println (name + ", I am thinking of a number between 1 and 20, can you guess it?").
 
 while guesses_made < 6 do
-    let guess = tointeger(input("Take a guess: ")).
+    let guess = type @tointeger(io @input("Take a guess: ")).
     let guesses_made = guesses_made + 1.
 
     if guess < number do
-        println "Your guess is too low."
+        io @println "Your guess is too low."
     elif guess > number do
-        println "Your guess is too high."
+        io @println "Your guess is too high."
     elif guess == number do
         break.
     end
 end
 
 if guess == number do
-    println ("Good job, " + name + "! You guessed my number in " + guesses_made + " guesses!").
+    io @println ("Good job, " + name + "! You guessed my number in " + guesses_made + " guesses!").
 else do
-    println ("Nope. The number I was thinking of was " + number).
+    io @println ("Nope. The number I was thinking of was " + number).
 end
 
-println "".
+io @println "".
diff --git a/asteroid/programs/hello.ast b/asteroid/programs/hello.ast
index 6f4ea689..5a17fd12 100644
--- a/asteroid/programs/hello.ast
+++ b/asteroid/programs/hello.ast
@@ -2,4 +2,4 @@
 
 load system io.
 
-println "Hello, World!".
+io @println "Hello, World!".
diff --git a/asteroid/programs/life.ast b/asteroid/programs/life.ast
index c2df3040..d4f55b9c 100644
--- a/asteroid/programs/life.ast
+++ b/asteroid/programs/life.ast
@@ -25,7 +25,7 @@ function display_array
             for j in 0 to (ncols-1) do
                 let row_str = row_str + ar@i@j.
             end
-            println row_str.
+            io @println row_str.
         end
     end
 
@@ -83,7 +83,7 @@ function show_map
         let (xdim,ydim) = array_shape map.
 
         -- need to do a deep copy because we are modifying the map
-        let display_map = copy map.
+        let display_map = util @copy map.
 
         for x in 0 to (xdim-1) do
             for y in 0 to (ydim-1) do
@@ -111,7 +111,7 @@ function init_map
         for x in 0 to (xdim-1) do
             let row = [].
             for y in 0 to (ydim-1) do
-                let v = 1 if random() > thresh else 0.
+                let v = 1 if random @random() > thresh else 0.
                 let row = row + [v]
             end
             let map = map + [row]
@@ -129,14 +129,14 @@ function life
         let map2 = init_map(xdim, ydim).
 
         -- show the initial map
-        cls().
-        println "initial map".
+        util @cls().
+        io @println "initial map".
         show_map map1.
 
         for gen in 0 to (maxgen-1) do
             compute_new_state(map1, map2).
-            cls().
-            println("map @ generation " + gen).
+            util @cls().
+            io @println("map @ generation " + gen).
             show_map(map2).
             -- implement double buffering
             let (map1,map2) = (map2,map1). -- swap the maps
diff --git a/asteroid/programs/peano.ast b/asteroid/programs/peano.ast
index 18e8cf05..08b209ec 100644
--- a/asteroid/programs/peano.ast
+++ b/asteroid/programs/peano.ast
@@ -1,7 +1,7 @@
 -- implements Peano addition using a lookup table for the rewrite rules
 
 load "util".
-load "io".
+load system io.
 
 structure s with -- successor function constructor
   data x.
@@ -30,4 +30,4 @@ function reduce
         return term.
     end
 
-println (reduce(add(s(s(0)),s(s(s(0)))))).
+io @println (reduce(add(s(s(0)),s(s(s(0)))))).
diff --git a/asteroid/programs/people.ast b/asteroid/programs/people.ast
index adf504c4..ed3a433f 100644
--- a/asteroid/programs/people.ast
+++ b/asteroid/programs/people.ast
@@ -1,4 +1,4 @@
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -16,5 +16,5 @@ let people = [
 
 -- print names that contain 'p'
 for Person(name:".*p.*",_,_) in people do
-  println name.
+  io @println name.
   end
diff --git a/asteroid/programs/qsort.ast b/asteroid/programs/qsort.ast
index d10baf44..dfb7a2df 100644
--- a/asteroid/programs/qsort.ast
+++ b/asteroid/programs/qsort.ast
@@ -1,7 +1,7 @@
 -- the quick sort
 -- (c) Lutz Hamel, University of Rhode Island
 
-load "io".
+load system io.
 
 function qsort
     with [] do
@@ -24,4 +24,4 @@ function qsort
     end
 
 -- print the sorted list
-println (qsort [3,2,1,0])
+io @println (qsort [3,2,1,0])
diff --git a/asteroid/programs/simple.ast b/asteroid/programs/simple.ast
index a3559d02..aef4f3f4 100644
--- a/asteroid/programs/simple.ast
+++ b/asteroid/programs/simple.ast
@@ -1,5 +1,5 @@
 -- a simple program using lambda functions
 
-load "io".
+load system io.
 
-println ((lambda with n do return n+1) 1).
+io @println ((lambda with n do return n+1) 1).
diff --git a/asteroid/programs/stream.ast b/asteroid/programs/stream.ast
index 8746ec61..fc493fef 100644
--- a/asteroid/programs/stream.ast
+++ b/asteroid/programs/stream.ast
@@ -1,18 +1,18 @@
 load system io.
-load system "stream".
+load system stream.
 
-let s = Stream([1,2,3,4]).
+let s = stream @stream([1,2,3,4]).
 
 while not s @eof() do
-  println(s @get()).
+  io @println(s @get()).
 end
 s @rewind().
 
 s @map(lambda with x do return 2*x).
 
 while not s @eof() do
-  println(s @get()).
+  io @println(s @get()).
 end
 s @rewind().
 
-println(s @__string__()).
+io @println(s @__string__()).
diff --git a/asteroid/programs/teams.ast b/asteroid/programs/teams.ast
index ded0413c..885617ed 100644
--- a/asteroid/programs/teams.ast
+++ b/asteroid/programs/teams.ast
@@ -1,12 +1,12 @@
 -- given a list of names generate
 -- and print teams of three
 
-load "util".
-load "io".
-load "dataframe".
+load system util.
+load system io.
+load system dataframe.
 
 -- team participants
-let df = DataFrame().
+let df = dataframe @dataframe().
 df @read_csv("names.csv",true).
 let names = df @col(0).
 
@@ -25,11 +25,11 @@ repeat do
 until names is [].
 
 -- print teams
-for (i,team) in zip(1 to len(teams),teams) do
+for (i,team) in util @zip(1 to len(teams),teams) do
   let team_str = "team " + i + (":  " if i < 10 else ": ").
   repeat do
     let [name|team] = team.
     let team_str = team_str + name + ("" if team is [] else ", ").
   until team is [].
-  println team_str.
+  io @println team_str.
 end
diff --git a/asteroid/repl.py b/asteroid/repl.py
new file mode 100644
index 00000000..e10557e7
--- /dev/null
+++ b/asteroid/repl.py
@@ -0,0 +1,97 @@
+from asteroid.interp import interp
+from asteroid.version import VERSION
+from asteroid.state import state
+from asteroid.globals import ExpectationError
+from asteroid.walk import function_return_value
+from asteroid.support import term2string
+
+from sys import stdin
+import readline
+
+def repl():
+    state.initialize()
+    print_repl_menu()
+    try:
+        run_repl()
+    except EOFError:
+        print()
+        pass
+
+def print_repl_menu():
+    print("Asteroid Version", VERSION)
+    print("Run \"asteroid -h\" for help")
+    print("Press CTRL+D to exit")
+
+
+def run_repl():
+
+    # The two different prompt types either > for a new statement
+    # or . for continuing one
+    arrow_prompt, continue_prompt = ("> ", ". ")
+    current_prompt = arrow_prompt
+
+    # Our line to be interpreted
+    line = ""
+    while True:
+        """
+        Line input, breaking, and exiting
+        """
+        try:
+            # Get the new input and append it to the previous line (Possibly empty)
+            # with a newline in between
+
+            # If the line is empty, just set the line
+            if line == "":
+                line = input(current_prompt)
+
+            # Otherwhise append a new line
+            else:
+                line += "\n" + input(current_prompt)
+
+        except KeyboardInterrupt:
+            line = ""
+            current_prompt = arrow_prompt
+            print()
+            continue
+
+        except EOFError:
+            print()
+            break
+
+        """
+        Interpretation, multiline input, and exception handling
+        """
+        try:
+            # Try to interpret the new statement
+            interp(line, initialize_state=False, exceptions=True)
+
+            # Try to
+            line = ""
+
+            # Check for return value
+            if function_return_value[-1]:
+                # Get the last return value (type, value)
+                (_, val) = function_return_value[-1]
+
+                # If it isn't none, print out the value
+                if val is not None:
+                    print(term2string(function_return_value[-1]))
+
+
+        except ExpectationError as e:
+            # If we expected something but found EOF, it's a continue
+            if e.found_EOF:
+                current_prompt = continue_prompt
+            else:
+                print("error: "+str(e))
+                line = ""
+                current_prompt = arrow_prompt
+
+        except Exception as e:
+            # FIX THIS
+            print("error: "+str(e))
+            line = ""
+            current_prompt = arrow_prompt
+
+        else:
+            current_prompt = arrow_prompt
diff --git a/asteroid/state.py b/asteroid/state.py
index 251a8517..605cfeac 100644
--- a/asteroid/state.py
+++ b/asteroid/state.py
@@ -1,7 +1,7 @@
 ###########################################################################################
 # Asteroid State Object
 #
-# (c) Lutz Hamel, University of Rhode Island
+# (c) University of Rhode Island
 ###########################################################################################
 
 from asteroid.symtab import SymTab
@@ -10,19 +10,31 @@ class State:
     def __init__(self):
         self.initialize()
 
-    def initialize(self):
+    def initialize(self,module="<input>"):
         self.symbol_table = SymTab()
         self.modules = [] # loaded modules
         self.AST = None
-        self.ignore_quote = False # used to evaluate quoted expressions
+        self.ignore_pattern = 0 # used to evaluate pattern expressions
         self.constraint_lvl = 0 # used to evaluate constraint-only patterns
         self.cond_warning = False # used to indicate if conditional subsumption
                                   # warning has been displayed
         self.eval_redundancy = True
-        self.lineinfo = ("<input>", 1) # tuple: module, lineno
+        self.lineinfo = (module, 1) # tuple: module, lineno
+        # stack of 3-tuples for stack trace of function
+        # calls: (module,lineno,function name)
+        self.trace_stack = [(module,1,"<toplevel>")]
 
 state = State()
 
 def warning(str):
     module, lineno = state.lineinfo
     print("Warning: {}: {}: {}".format(module, lineno, str))
+
+def dump_trace():
+    if len(state.trace_stack) == 1:
+        return
+    else:
+        print("traceback (most recent call last):")
+        for i in range(0,len(state.trace_stack)):
+            (module,lineno,fname) = state.trace_stack[i]
+            print("{}: {}: calling {}".format(module,lineno,fname))
diff --git a/asteroid/support.py b/asteroid/support.py
index 897b6131..0d4dbc2e 100644
--- a/asteroid/support.py
+++ b/asteroid/support.py
@@ -141,10 +141,10 @@ def map2boolean(value):
     elif value[0] == 'boolean':
         return value
 
-    elif value[0] in  ['integer', 'real', 'list', 'string']:
+    elif value[0] in  ['integer', 'real', 'list', 'tuple', 'string']:
         return ('boolean', bool(value[1]))
 
-    elif value[0] == 'object':
+    elif value[0] in ['object', 'function-val', 'pattern']:
         return ('boolean', True)
 
     else:
@@ -257,8 +257,8 @@ def term2string(term):
         term_string += term2string(args)
         return term_string
 
-    elif TYPE == 'quote':
-        # we are printing out a term - just ignore the quote operator
+    elif TYPE == 'pattern':
+        # we are printing out a term - just ignore the pattern operator
         val = term[1]
         return term2string(val)
 
@@ -316,180 +316,18 @@ def term2string(term):
         term_string += term2string(state.symbol_table.lookup_sym(pName))
         return term_string
 
-    elif TYPE == 'cmatch':              # Handle a conditional pattern
-
-        (CMATCH,CVALUE,CEXPRESSION) = term
-
-        #Check for a compound condtional( ANDs and ORs )
-        if (((CEXPRESSION[1])[1] == '__and__') or ((CEXPRESSION[1])[1] == '__or__')):
-            return compound_relational_to_string(term)
-
-        try:
-            (NAMED_PATTERN,ID,pattern) = CVALUE
-        except:
-            ID = CVALUE
-            pattern = CVALUE
-        (APPLY,expression_type,expressions) = CEXPRESSION
-
-        if ((expressions[0] == 'tuple')):
-
-            if ((expression_type[1])[0] == '_'): #Handle conditional prebuit operation
-                (TUPLE,[ expression_lhs , expression_rhs ]) = expressions
-
-                term_string = term2string(ID) + ':'
-                term_string += term2string(pattern)
-                term_string += " %" + "if "
-                term_string += term2string(expression_lhs)
-
-                if expression_type[1] == '__gt__':
-                    term_string += ' > '
-                elif expression_type[1] == '__lt__':
-                    term_string += ' < '
-                elif expression_type[1] == '__le__':
-                    term_string += ' <= '
-                elif expression_type[1] == '__ge__':
-                    term_string += ' >= '
-                elif expression_type[1] == '__eq__':
-                    term_string += ' == '
-                elif expression_type[1] == '__ne__':
-                    term_string += ' =/= '
-
-                term_string += term2string(expression_rhs)
-
-            else:               #Handle a function with multiple args
-                (TUPLE,EXPRESION_LIST) = expressions
-
-                term_string = term2string(ID)+ ':'
-                term_string += term2string(pattern)
-                term_string += " if "
-                term_string += expression_type[1] + '( '
-
-                for expression in EXPRESION_LIST:
-                    term_string += term2string(expression)
-                    term_string += ', '
-                term_string = term_string[:-2]
-                term_string += ' )'
-
-        elif (expressions[0] == 'none'): #Handle a function with no arguments
-            term_string = term2string(ID)+ ':'
-            term_string += term2string(pattern)
-            term_string += " if "
-            term_string += expression_type[1] + '()'
-
-        elif (expressions[0] in ['id','integer','real','sting','boolean']): #Handle a function with one arguments
-            term_string = term2string(ID)+ ':'
-            term_string += term2string(pattern)
-            term_string += " if "
-            term_string += expression_type[1] + '( '
-            term_string += str(expressions[1]) + ' )'
-
-        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...)'
 
     else:
         #lhh print(term)
         raise ValueError(
             "unknown type '{}' in term2string"
             .format(TYPE))
-##############################################################################################
-# term2string helper
-# This function takes in a relational conditional expression from a conditional pattern clause
-# and then returns that expression as a nicely formatted string
-#
-# Ths realtional expression is expected to come in its raw nested tuple/AST form from the Asteroid
-# Interpreter.
-def walk_relational_expr(term):
-
-    # Unpack
-    (APPLY,expression_type,args) = term
-    (TUPLE,arg_list) = args
-
-    term_string = ''
-    term_string += term2string(arg_list[0])
-
-    # Parse and write the argument type
-    if expression_type[1] == '__gt__':
-        term_string += ' > '
-    elif expression_type[1] == '__lt__':
-        term_string += ' < '
-    elif expression_type[1] == '__le__':
-        term_string += ' <= '
-    elif expression_type[1] == '__ge__':
-        term_string += ' >= '
-    elif expression_type[1] == '__eq__':
-        term_string += ' == '
-    elif expression_type[1] == '__ne__':
-        term_string += ' =/= '
-    else:
-        return ''
-
-    term_string += term2string(arg_list[1])
-
-    return term_string
-
-##############################################################################################
-# term2string helper
-#
-# This function helps construct a string from a compound relational conditional pattern clause.
-# The and/or nodes are walked down as the string is constructed.
-# This function takes in the raw term/AST from the compound relational conditional pattern clause
-# in the nested tuple/AST form.
-#
-# Example clause:
-#               with (x) if x <= 10 and x > 1 or x > 2 and x < 9 or x < 7 do
-# Example output:
-#               x: if x <= 10 and x > 1 or x > 2 and x < 9 or x < 7
-def compound_relational_to_string(term):
-
-    #Check if we have passed by the relation type before
-    not_first_pass_and = False
-    not_first_pass_or = False
-
-    # If its the first time we have seen this we need to write the header/pattern name
-    # before recursing
-    if (term[0] == 'cmatch'):
-        (CMATCH,pattern,apply_list) = term
-        term_string = term2string(pattern)
-        term_string += ': if '
-        term_string += compound_relational_to_string(apply_list)
-        return term_string
-
-    # Else we just unpack the node and peek at the upcoming operation
-    else:
-        (APPLY,operation,apply_list) = term
-        term_string = ''
-        op_name = operation[1]
-
-    # Walk down the tree, constucting the string along the way
-    if ( op_name == '__or__' ):
-
-        for expr in apply_list[1]:
-
-            # Add seperator if appropriate
-            if not_first_pass_or:
-                term_string += " or "
-            else:
-                not_first_pass_or = True
-
-            #write the current term to string
-            term_string += compound_relational_to_string(expr)
-    elif ( op_name == '__and__'):
-
-        for expr in apply_list[1]:
-
-            # Add seperator if appropriate
-            if not_first_pass_and:
-                term_string += " and "
-            else:
-                not_first_pass_and = True
-
-            #write the current term to string
-            if (expr[1])[1] in ['__and__','__or__']:
-                term_string += compound_relational_to_string(expr)
-            term_string += walk_relational_expr(expr)
-    else:
-        term_string += walk_relational_expr(term)
 
-    return term_string
 ##############################################################################################
 # 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.
diff --git a/asteroid/symtab.py b/asteroid/symtab.py
index 8c11498e..bb032d32 100644
--- a/asteroid/symtab.py
+++ b/asteroid/symtab.py
@@ -68,7 +68,7 @@ def enter_global(self, sym):
         self.globals[CURR_SCOPE].append(sym)
 
     def lookup_sym(self, sym, strict=True):
-        dict = self.find_sym(sym)
+        dict = self.find_sym_dict(sym)
         if not dict:
             if strict:
                 raise ValueError("'{}' is not defined".format(sym))
@@ -81,7 +81,7 @@ def update_sym(self, sym, value):
         # find the first occurence of sym
         # and update the associated value
 
-        dict = self.find_sym(sym)
+        dict = self.find_sym_dict(sym)
         if not dict:
             raise ValueError("'{}' is not defined".format(sym))
         else:
@@ -100,7 +100,7 @@ def is_global(self, sym):
         else:
             return False
 
-    def find_sym(self, sym):
+    def find_sym_dict(self, sym):
         n_scopes = len(self.scoped_symtab)
         for scope in range(n_scopes):
             if sym in self.scoped_symtab[scope]:
diff --git a/asteroid/version.py b/asteroid/version.py
index 73a54da2..e46b3352 100644
--- a/asteroid/version.py
+++ b/asteroid/version.py
@@ -5,4 +5,4 @@
 # (c) University of Rhode Island
 ##########################################################################################
 
-VERSION = "0.1.0"
+VERSION = "1.0.0"
diff --git a/asteroid/walk.py b/asteroid/walk.py
index 6a56dafd..8bbb81e1 100644
--- a/asteroid/walk.py
+++ b/asteroid/walk.py
@@ -26,6 +26,12 @@
 #########################################################################
 __retval__ = None  # return value register for escaped code
 
+#########################################################################
+# return values for function computed by the last expression executed
+# in the context of a function.  note that we consider global code
+# to be part of the 'top-level' function
+function_return_value = [None]
+
 ###########################################################################################
 # check if the two type tags match
 def match(tag1, tag2):
@@ -76,7 +82,7 @@ def unify(term, pattern, unifying = True ):
             return [] # return empty unifier
         else:
             raise PatternMatchFailed(
-                "regular expression {} did not match {}"
+                "regular expression '{}' did not match '{}'"
                 .format(pattern, term))
 
     elif isinstance(term, (int, float, bool)):
@@ -84,7 +90,7 @@ def unify(term, pattern, unifying = True ):
             return [] # return an empty unifier
         else:
             raise PatternMatchFailed(
-                "{} is not the same as {}"
+                "'{}' is not the same as '{}'"
                 .format(term, pattern))
 
     elif isinstance(term, list) or isinstance(pattern, list):
@@ -110,9 +116,8 @@ def unify(term, pattern, unifying = True ):
     elif ((not unifying) and (term[0] == 'deref')):
 
         # Unpack a term-side first-class pattern if evaluating redundant clauses
-        (ID, sym) = term[1]
-        term = state.symbol_table.lookup_sym(sym)
-        return unify(term[1], pattern, unifying)
+        term_pattern = walk(term[1])
+        return unify(term_pattern, pattern, unifying)
 
     ### Asteroid value level matching
     elif pattern[0] == 'object' and term[0] == 'object':
@@ -124,7 +129,7 @@ def unify(term, pattern, unifying = True ):
         (OBJECT, (STRUCT_ID, (ID, tid)), (OBJECT_MEMORY, (LIST, tl))) = term
         if pid != tid:
             raise PatternMatchFailed(
-                "pattern type {} and term type {} do not agree"
+                "pattern type '{}' and term type '{}' do not agree"
                 .format(pid,tid))
         return unify(data_only(tl),data_only(pl))
 
@@ -153,7 +158,7 @@ def unify(term, pattern, unifying = True ):
         (IF_EXP, cond_exp, pexp, else_exp) = pattern
 
         if else_exp[0] != 'null':
-            raise ValueError("conditional patterns do not support else clauses")
+            raise PatternMatchFailed("conditional patterns do not support 'else' clauses")
 
         unifiers = unify(term, pexp, unifying)
 
@@ -183,9 +188,13 @@ def unify(term, pattern, unifying = True ):
         (IF_EXP, cond_exp, pexp, else_exp) = term
 
         if else_exp[0] != 'null':
-            raise ValueError("conditional patterns do not support else clauses")
+            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.")
 
-        return unify(pexp,pattern,False)
 
     elif pattern[0] == 'typematch':
         typematch = pattern[1]
@@ -208,7 +217,7 @@ def unify(term, pattern, unifying = True ):
                 return []
             else:
                 raise PatternMatchFailed(
-                    "expected typematch {} got a term of type {}"
+                    "expected type '{}' got a term of type '{}'"
                     .format(typematch, term[nextIndex]))
 
         elif typematch == 'function':
@@ -217,18 +226,42 @@ def unify(term, pattern, unifying = True ):
                 return []
             else:
                 raise PatternMatchFailed(
-                    "expected typematch {} got a term of type {}"
+                    "expected type '{}' got a term of type '{}'"
                     .format(typematch, term[0]))
 
         elif typematch == 'pattern':
-            if term[0] == 'quote':
-                return []
-            else:
-                raise PatternMatchFailed(
-                                    "expected typematch {} got a term of type {}"
-                                    .format(typematch, term[0]))
+            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:
+                    return []
+                else:
+                    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')):
+                        return []
+
+                if term[nextIndex] in pattern_subsumes:
+                    return []
+                else:
+                    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) )
+
             (OBJECT,
                 (STRUCT_ID, (ID, struct_id)),
                 (OBJECT_MEMORY, LIST)) = term
@@ -236,26 +269,15 @@ def unify(term, pattern, unifying = True ):
                     return []
             else:
                 raise PatternMatchFailed(
-                    "expected typematch {} got an object of type {}"
+                    "expected type '{}' got an object of type '{}'"
                     .format(typematch, struct_id))
 
         else:
-            # Check if the typematch is in the symbol table
-            in_symtab = state.symbol_table.find_sym(typematch)
-
-            # If not, then it is not a vaid type fot typematch
-            if not in_symtab:
-                raise PatternMatchFailed( "{} is not a valid type for typematch".format(typematch))
-
-            # If it is in the symbol table but not a struct, it cannot be typematched
-            # because it is not a type
-            elif in_symtab and state.symbol_table.lookup_sym(typematch)[0] != 'struct':
-                raise PatternMatchFailed( "{} is not a type".format(typematch) )
-
-            # Otherwhise, the typematch has failed
+            if state.symbol_table.lookup_sym(typematch)[0] != 'struct':
+                raise PatternMatchFailed( "'{}' is not a type".format(typematch) )
             else:
                 raise PatternMatchFailed(
-                    "expected typematch {} got an object of type {}"
+                    "expected type '{}' got an object of type '{}'"
                     .format(typematch, term[0]))
 
 
@@ -285,16 +307,16 @@ def unify(term, pattern, unifying = True ):
             "pattern of type '{}' not allowed in pattern matching"
             .format(pattern[0]))
 
-    elif pattern[0] == 'quote':
-        # quotes on the pattern side can always be ignored
+    elif pattern[0] == 'pattern':
+        # pattern operator on the pattern side can always be ignored
         # --TODO double check - ttc
-        if term[0] == 'quote':
+        if term[0] == 'pattern':
             return unify(term[1], pattern[1], unifying)
         else:
             return unify(term, pattern[1], unifying)
 
-    elif term[0] == 'quote' and pattern[0] not in ['id', 'index']:
-        # ignore quote on the term if we are not trying to unify term with
+    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)
 
@@ -307,6 +329,10 @@ def unify(term, pattern, unifying = True ):
         (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))
@@ -322,10 +348,12 @@ def unify(term, pattern, unifying = True ):
         unifier = (pattern, term)
         return [unifier]
 
-    elif term[0] == 'id' and unifying: # variable in term not allowed
-        raise PatternMatchFailed(      # when unifying
-            "variable '{}' in term not allowed"
-            .format(term[1]))
+# 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]
@@ -391,9 +419,10 @@ def unify(term, pattern, unifying = True ):
                 check_repeated_symbols(unifier) #Ensure we have no non-linear patterns
                 return unifier
 
-    elif pattern[0] == 'deref':  # ('deref', ('id', sym))
-        (ID, sym) = pattern[1]
-        p = state.symbol_table.lookup_sym(sym)
+    elif pattern[0] == 'deref':  # ('deref', v)
+        # v can be an AST representing any computation
+        # that produces a pattern.
+        p = walk(pattern[1])
 
         #lhh
         #print("unifying \nterm:{}\npattern:{}\n".format(term,p))
@@ -404,7 +433,7 @@ def unify(term, pattern, unifying = True ):
     elif pattern[0] == 'apply':
         if term[0] != pattern[0]: # make sure both are applys
             raise PatternMatchFailed(
-                "term and pattern disagree on 'apply' node")
+                "term and pattern disagree on structure")
 
         # unpack the apply structures
         (APPLY, (ID, t_id), t_arg) = term
@@ -456,9 +485,8 @@ def declare_formal_args(unifiers):
 
     for u in unifiers:
         (pattern, term) = u
-        (ID, sym) = pattern
-        if ID != 'id':
-            raise ValueError("no pattern match possible in function call")
+        (ID, sym) = pattern # in unifiers the pattern is always a variable
+        assert_match(ID,'id')
         if sym == 'this':
             raise ValueError("'this' is a reserved word")
         state.symbol_table.enter_sym(sym, term)
@@ -496,7 +524,7 @@ def check_repeated_symbols( unifiers ):
 
         elif sym in symbols: # We have found a non-linear pattern
             raise NonLinearPatternError(
-            "multiple instances of {} found within a pattern.".format(sym))
+            "multiple instances of '{}' found within pattern.".format(sym))
 
         else: # Else we have never seen this before so we record it.
             symbols[sym] = term
@@ -553,14 +581,20 @@ def read_at_ix(structure_val, ix):
         # unpack the struct value
         (STRUCT,
          (MEMBER_NAMES, (LIST, member_names)),
-         (STRUCT_MEMORY, (LIST, struct_memory)),
-         (STRUCT_SCOPE, struct_scope)) = struct_val
-        state.symbol_table.push_scope(struct_scope)
-        ix_val = walk(ix)
-        state.symbol_table.pop_scope()
+         (STRUCT_MEMORY, (LIST, struct_memory))) = struct_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] == 'pattern':
+        # simple patterns are just structures - skip the pattern operator
+        return read_at_ix(structure_val[1], ix)
 
     else:
-        raise ValueError("'{}' is not indexable".format(structure_val[0]))
+        raise ValueError("term '{}' is not indexable"
+                         .format(term2string(structure_val)))
 
     # index into memory and get value(s)
     if ix_val[0] == 'integer':
@@ -618,14 +652,20 @@ def store_at_ix(structure_val, ix, value):
         # unpack the struct value
         (STRUCT,
          (MEMBER_NAMES, (LIST, member_names)),
-         (STRUCT_MEMORY, (LIST, struct_memory)),
-         (STRUCT_SCOPE, struct_scope)) = struct_val
-        state.symbol_table.push_scope(struct_scope)
-        ix_val = walk(ix)
-        state.symbol_table.pop_scope()
+         (STRUCT_MEMORY, (LIST, struct_memory))) = struct_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] == 'pattern':
+        # simple patterns are just structures - skip the pattern operator
+        return store_at_ix(structure_val[1], ix, value)
 
     else:
-        raise ValueError("'{}' is not a mutable structure".format(structure_val[0]))
+        raise ValueError("term '{}' is not a mutable structure"
+                         .format(term2string(structure_val)))
 
     # Next, we do the actual memory storage operation
 
@@ -640,9 +680,9 @@ def store_at_ix(structure_val, ix, value):
 
         # Make sure the rval is a list
         if value[0] != 'list':
-            raise ValueError('Pattern slicing needs values to be a list')
+            raise ValueError('pattern slicing needs values to be a list')
         elif value[0] == 'list' and (len(ix_val[1]) != len(value[1])):
-            raise ValueError('Pattern slicing needs indexes and values of equal length')
+            raise ValueError('pattern slicing needs indexes and values of equal length')
 
         # Get the l/rval
         (LIST, lval) = ix_val
@@ -680,13 +720,13 @@ def handle_builtins(node):
             elif type == 'string':
                 return (type, term2string(val_a) + term2string(val_b))
             else:
-                raise ValueError('unsupported type {} in +'.format(type))
+                raise ValueError("unsupported type '{}' in +".format(type))
         elif opname == '__minus__':
             type = promote(val_a[0], val_b[0])
             if type in ['integer', 'real']:
                 return (type, val_a[1] - val_b[1])
             else:
-                raise ValueError('unsupported type {} in -'.format(type))
+                raise ValueError("unsupported type '{}' in -".format(type))
         elif opname == '__times__':
             type = promote(val_a[0], val_b[0])
             if type in ['integer', 'real']:
@@ -754,7 +794,7 @@ def handle_builtins(node):
             else:
                 raise ValueError('unsupported type in >')
         else:
-            raise ValueError('unknown builtin binary opname {}'.format(opname))
+            raise ValueError("unknown builtin binary operation '{}'".format(opname))
 
     elif opname in unary_operators:
         arg_val = walk(args)
@@ -766,23 +806,23 @@ def handle_builtins(node):
             elif val[1] == True:
                 return ('boolean', False)
             else:
-                raise ValueError('not a boolean value in not')
+                raise ValueError("not a boolean value in 'not'")
         elif opname == '__uminus__':
             if arg_val[0] in ['integer', 'real']:
                 return (arg_val[0], - arg_val[1])
             else:
                 raise ValueError(
-                    'unsupported type {} in unary minus'
+                    "unsupported type '{}' in unary minus"
                     .format(arg_val[0]))
         elif opname == '__uplus__':
             if arg_val[0] in ['integer', 'real']:
                 return (arg_val[0], + arg_val[1])
             else:
                 raise ValueError(
-                    'unsupported type {} in unary plus'
+                    "unsupported type '{}' in unary plus"
                     .format(arg_val[0]))
         else:
-            raise ValueError('unknown builtin unary opname {}'.format(opname))
+            raise ValueError("unknown builtin unary operation '{}'".format(opname))
 
 #########################################################################
 def handle_call(obj_ref, fval, actual_val_args, fname):
@@ -790,6 +830,10 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
     (FUNCTION_VAL, body_list, closure) = fval
     assert_match(FUNCTION_VAL, 'function-val')
 
+    state.trace_stack.append((state.lineinfo[0],
+                              state.lineinfo[1],
+                              fname))
+
     # static scoping for functions
     # Note: we have to do this here because unifying
     # over the body patterns can introduce variable declarations,
@@ -827,7 +871,8 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
             break
 
     if not unified:
-        raise ValueError("none of the function bodies unified with actual parameters")
+        raise ValueError("actual argument '{}' not recognized by function '{}'"
+                         .format(term2string(actual_val_args),fname))
 
     declare_formal_args(unifiers)
 
@@ -844,18 +889,27 @@ def handle_call(obj_ref, fval, actual_val_args, fname):
     # function calls transfer control - save our caller's lineinfo
     old_lineinfo = state.lineinfo
 
+    global function_return_value
     try:
+        function_return_value.append(None)
         walk(stmts)
+        val = function_return_value.pop()
+        if val:
+            return_value = val
+        else:
+            return_value = ('none', None)
     except ReturnValue as val:
+        # we got here because a return statement threw a return object
+        function_return_value.pop()
         return_value = val.value
-    else:
-        return_value = ('none', None) # need that in case function has no return statement
 
     # coming back from a function call - restore caller's env
     state.lineinfo = old_lineinfo
     state.symbol_table.pop_scope()
     state.symbol_table.set_config(save_symtab)
 
+    state.trace_stack.pop()
+
     return return_value
 
 #########################################################################
@@ -903,7 +957,7 @@ def global_stmt(node):
     for id_tuple in id_list:
         (ID, id_val) = id_tuple
         if state.symbol_table.is_symbol_local(id_val):
-            raise ValueError("{} is already local, cannot be declared global"
+            raise ValueError("'{}' is already local, cannot be declared global"
                              .format(id_val))
         state.symbol_table.enter_global(id_val)
 
@@ -1150,7 +1204,7 @@ def if_stmt(node):
     assert_match(LIST, 'list')
 
     for i in range(0,len(if_list),2):
-        
+
         lineinfo = if_list[ i ]
         process_lineinfo(lineinfo)
 
@@ -1178,19 +1232,15 @@ def struct_def_stmt(node):
     # in a struct object
     struct_memory = [] # this will serve as a template for instanciating objects
     member_names = []
-    struct_scope = {}
-    state.symbol_table.push_scope(struct_scope)
 
     for member_ix in range(len(member_list)):
         member = member_list[member_ix]
         if member[0] == 'data':
             (DATA, (ID, member_id)) = member
-            state.symbol_table.enter_sym(member_id, ('integer', member_ix))
             struct_memory.append(('none', None))
             member_names.append(member_id)
         elif member[0] == 'unify':
             (UNIFY, (ID, member_id), function_exp) = member
-            state.symbol_table.enter_sym(member_id, ('integer', member_ix))
             # Note: we have to bind a function VALUE into the structure memory
             function_val = walk(function_exp)
             struct_memory.append(function_val)
@@ -1200,12 +1250,9 @@ def struct_def_stmt(node):
         else:
             raise ValueError("unsupported struct member '{}'".format(member[0]))
 
-    state.symbol_table.pop_scope()
-
     struct_type = ('struct',
                   ('member-names', ('list', member_names)),
-                  ('struct-memory', ('list', struct_memory)),
-                  ('struct-scope', struct_scope))
+                  ('struct-memory', ('list', struct_memory)))
 
     state.symbol_table.enter_sym(struct_id, struct_type)
 
@@ -1229,11 +1276,11 @@ def eval_exp(node):
     #lhh
     #print("after expand: {}".format(exp_val_expand))
     # now walk the actual term
-    state.ignore_quote = True
+    state.ignore_pattern += 1
     exp_val = walk(exp_val_expand)
     #lhh
     #print("after walk: {}".format(exp_val))
-    state.ignore_quote = False
+    state.ignore_pattern -= 1
     return exp_val
 
 #########################################################################
@@ -1247,15 +1294,32 @@ def apply_exp(node):
         return handle_builtins(node)
 
     # handle function application
+    # retrieve the function name from the AST
+    if f[0] in ['function-exp','apply']:
+        # cannot use the function expression as a name,
+        # could be a very complex computation. the apply
+        # node means that the lambda function has to still be
+        # computed.
+        f_name = 'lambda'
+    elif f[0] == 'index':
+        # object member 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)
+    else:
+        # just a regular function call
+        (ID, f_name) = f
+
+    # evaluate the function expression and the arguments
     f_val = walk(f)
-    f_name = f[1]
     arg_val = walk(arg)
 
     # object member function
     # NOTE: object member functions are passed an object reference.
     if f_val[0] == 'member-function-val':
         (MEMBER_FUNCTION_VAL, obj_ref, function_val) = f_val
-        # Note: lists and tuples are objects/mutable data structures, they
+        # Note: lists and strings are objects/mutable data structures, they
         # have member functions defined in the Asteroid prologue.
         result = handle_call(obj_ref,
                              function_val,
@@ -1271,28 +1335,25 @@ def apply_exp(node):
         (ID, struct_id) = f
         (STRUCT,
          (MEMBER_NAMES, (LIST, member_names)),
-         (STRUCT_MEMORY, (LIST, struct_memory)),
-         (STRUCT_SCOPE, struct_scope)) = f_val
+         (STRUCT_MEMORY, (LIST, struct_memory))) = f_val
 
         # create our object memory - memory cells now have initial values
-        # TODO: why is this not shared among objects?
+        # we use structure memory as an init template
         object_memory = struct_memory.copy()
         # create our object
         obj_ref = ('object',
-                  ('struct-id', ('id', struct_id)),
-                  ('object-memory', ('list', object_memory)))
+                   ('struct-id', ('id', struct_id)),
+                   ('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.
         if '__init__' in member_names:
             slot_ix = member_names.index('__init__')
             init_fval = struct_memory[slot_ix]
             # calling a member function - push struct scope
-            state.symbol_table.push_scope(struct_scope)
             handle_call(obj_ref,
                         init_fval,
                         arg_val,
                         f_name)
-            state.symbol_table.pop_scope()
         # 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
@@ -1305,8 +1366,10 @@ def apply_exp(node):
             data_memory = data_only(object_memory)
             if len(data_memory) != len(arg_array):
                 raise ValueError(
-                    "default constructor expected {} arguments got {}"
-                    .format(len(data_memory), len(arg_array)))
+                    "default constructor expected {} argument{} got {}"
+                    .format(len(data_memory),
+                            "" if len(data_memory) else "s",
+                            len(arg_array)))
             # copy initializers into object memory
             data_ix = data_ix_list(object_memory)
             for (i,k) in zip(data_ix, range(0,len(data_memory))):
@@ -1316,7 +1379,8 @@ def apply_exp(node):
         result = obj_ref
 
     else:
-        raise ValueError("unknown apply term '{}'".format(f_val[0]))
+        raise ValueError("term '{}' is not a function, did you forget the end-of-line period?"
+                         .format(term2string(f_val)))
 
     return result
 
@@ -1402,7 +1466,7 @@ def in_exp(node):
     (EXP_LIST_TYPE, exp_list_val, *_) = walk(exp_list)
 
     if EXP_LIST_TYPE != 'list':
-        raise ValueError("right argument to in operator has to be a list")
+        raise ValueError("right argument to 'in' operator has to be a list")
 
     # we simply map our in operator to the Python in operator
     if exp_val in exp_list_val:
@@ -1419,7 +1483,7 @@ def if_exp(node):
     # if expressions without an else clause are only allowed in
     # conditional patterns.
     if else_exp[0] == 'null':
-        raise ValueError("if expressions need an else clause")
+        raise ValueError("if expressions need an 'else' clause")
 
     (BOOLEAN, cond_val) = map2boolean(walk(cond_exp))
 
@@ -1437,41 +1501,54 @@ def to_list_exp(node):
     (TOLIST,
      (START, start),
      (STOP, stop),
-     (STEP, step)) = node
+     (STRIDE, stride)) = node
 
     assert_match(TOLIST, 'to-list')
     assert_match(START, 'start')
     assert_match(STOP, 'stop')
-    assert_match(STEP, 'step')
+    assert_match(STRIDE, 'stride')
 
     (START_TYPE, start_val, *_) = walk(start)
     (STOP_TYPE, stop_val, *_) = walk(stop)
-    (STEP_TYPE, step_val, *_) = walk(step)
+    (STRIDE_TYPE, stride_val, *_) = walk(stride)
 
-    if START_TYPE != 'integer' or STOP_TYPE != 'integer' or STEP_TYPE != 'integer':
-        raise ValueError("only integer values allowed in start, stop, or step")
+    if START_TYPE != 'integer' or STOP_TYPE != 'integer' or STRIDE_TYPE != 'integer':
+        raise ValueError("only integer values allowed in start, stop, or stride")
 
     out_list_val = []
 
-    # TODO: check out the behavior with step -1 -- is this what we want?
-    # the behavior is start and stop included
-    if int(step_val) > 0: # generate the list
+    # If our stride val is > 0
+    if int(stride_val) > 0: # generate the list
+        # Get the [i]nitial inde[x] and [e]nd inde[x]
         ix = int(start_val)
-        while ix <= int(stop_val):
-            out_list_val.append(('integer', ix))
-            ix += int(step_val)
+        ex = int(stop_val)
 
-    elif int(step_val) == 0: # error
-        raise ValueError("step size of 0 not supported")
+        # Get the stride_val
+        stride_val = int(stride_val)
 
-    elif int(step_val) < 0: # generate the list
-        ix = int(start_val)
-        while ix >= int(stop_val):
-            out_list_val.append(('integer', ix))
-            ix += int(step_val)
+        # Change the direction of the stride value based on the
+        # ends of the range. I.e. 5->1 has an implicit direction
+        # of -1, 1->5 has a direction of +1
+        direction = (1 if ix < ex else -1)
+        stride_val *= direction
+
+        # We need to modify the ending index to acccount for python
+        # ranges. For example, for 1->10 we want range(1, 10 + 1).
+        # Or, for the opposite, we want range(10, 1 - 1) to give
+        # us the full inclusive range. Thus, we can just add our
+        # direction
+        new_ex = ex + direction
+        for i in range(ix, new_ex, stride_val):
+            out_list_val.append( ('integer', i) )
+
+    elif int(stride_val) == 0: # error
+        raise ValueError("stride size of 0 not supported")
+
+    elif int(stride_val) < 0: # generate the list
+        raise ValueError("negative stride sizes are not supported")
 
     else:
-        raise ValueError("{} not a valid step value".format(step_val))
+        raise ValueError("'{}' not a valid stride value".format(stride_val))
 
     return ('list', out_list_val)
 
@@ -1488,7 +1565,7 @@ def head_tail_exp(node):
 
     if TAIL_TYPE != 'list':
         raise ValueError(
-            "unsupported tail type {} in head-tail operator".
+            "unsupported tail type '{}' in head-tail operator".
             format(TAIL_TYPE))
 
     return ('list', [head_val] + tail_val)
@@ -1546,8 +1623,21 @@ def constraint_exp(node):
     # A constraint-only pattern match AST cannot be walked and therefor
     # we raise an error.
     raise ValueError(
-        "constraint pattern: {} cannot be used as a constructor.".
-        format(term2string(node)))
+        "constraint pattern: '{}' cannot be used as a constructor."
+        .format(term2string(node)))
+
+#########################################################################
+def set_ret_val(node):
+
+    (SET_RET_VAL, exp) = node
+    assert_match(SET_RET_VAL,'set-ret-val')
+
+    global function_return_value
+    val = walk(exp)
+    function_return_value.pop()
+    function_return_value.append(val)
+
+    return
 
 #########################################################################
 # walk
@@ -1556,16 +1646,23 @@ def walk(node):
     # node format: (TYPE, [child1[, child2[, ...]]])
     type = node[0]
 
-    if type in dispatch_dict:
+    if type == 'clear-ret-val':
+        # implemented here instead of dictionary for efficiency reasons
+        global function_return_value
+        function_return_value.pop()
+        function_return_value.append(None)
+        return
+    elif type in dispatch_dict:
         node_function = dispatch_dict[type]
         return node_function(node)
     else:
-        raise ValueError("feature {} not yet implemented".format(type))
+        raise ValueError("feature '{}' not yet implemented".format(type))
 
 # a dictionary to associate tree nodes with node functions
 dispatch_dict = {
     # statements - statements do not produce return values
     'lineinfo'      : process_lineinfo,
+    'set-ret-val'   : set_ret_val,
     'noop'          : lambda node : None,
     'assert'        : assert_stmt,
     'unify'         : unify_stmt,
@@ -1587,7 +1684,6 @@ def walk(node):
     'head-tail'     : head_tail_exp,
     'raw-to-list'   : lambda node : walk(('to-list', node[1], node[2], node[3])),
     'raw-head-tail' : lambda node : walk(('head-tail', node[1], node[2])),
-    'seq'           : lambda node : ('seq', walk(node[1]), walk(node[2])),
     'none'          : lambda node : node,
     'nil'           : lambda node : node,
     'function-exp'  : function_exp,
@@ -1597,12 +1693,10 @@ def walk(node):
     'boolean'       : lambda node : node,
     'object'        : lambda node : node,
     'eval'          : eval_exp,
-    # quoted code should be treated like a constant if not ignore_quote
-    'quote'         : lambda node : walk(node[1]) if state.ignore_quote else node,
+    # 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,
-    # the following is now handled with an if-exp
-    #'cmatch'        : constraint_exp,
     'typematch'     : constraint_exp,
     # type tag used in conjunction with escaped code in order to store
     # foreign objects in Asteroid data structures
diff --git a/docs/Asteroid in Action.rst b/docs/Asteroid in Action.rst
index 06930fbb..6f668fa9 100644
--- a/docs/Asteroid in Action.rst
+++ b/docs/Asteroid in Action.rst
@@ -1,12 +1,26 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+..
+   *** DO NOT EDIT; MACHINE GENERATED ***
+
 .. highlight:: none
 
 Asteroid in Action
-##################
+==================
 
-This document was inspired by Andrew Shitov's excellent book `Using Raku: 100 Programming Challenges Solved with the Brand-New Raku Programming Language <https://andrewshitov.com/wp-content/uploads/2020/01/Using-Raku.pdf>`_.  Here we use Asteroid to solve these programming challenges. 
-..
-  Chapter: Strings
-  ----------------
+This document was inspired by Andrew Shitov's excellent book `Using Raku: 100 Programming Challenges Solved with the Brand-New Raku Programming Language <https://andrewshitov.com/wp-content/uploads/2020/01/Using-Raku.pdf>`_.  Here we use Asteroid to solve these programming challenges.
 
 Section: Using Strings
 ----------------------
@@ -16,14 +30,14 @@ Challenge: Hello, World!
 
 > Print ‘Hello, World!’
 
-The canonical `Hello, World!` program.  The easiest way to write this in Asteroid is,
+The canonical ``Hello, World!`` program.  The easiest way to write this in Asteroid is,
 ::
-    load system io.
+  load system io.
 
-    println "Hello, World!".
+  io @println "Hello, World!".
+
+Output::
 
-Output:
-::
     Hello, World!
 
 
@@ -35,50 +49,51 @@ Challenge: Greet a person
 
 Here is our first solution using a separate function for each of the steps,
 ::
-    load system io.
+  load system io.
 
-    print ("Enter your name: ").
-    let name = input().
-    print ("Hello, "+name+"!").
+  io @print ("Enter your name: ").
+  let name = io @input().
+  io @print ("Hello, "+name+"!").
 
 
-Letting the function `input` do the prompting,
+Letting the function ``input`` do the prompting,
 ::
-    load system io.
-
-    let name = input("Enter your name: ").
-    print ("Hello, "+name+"!").
+  load system io.
 
+  let name = io @input("Enter your name: ").
+  io @println ("Hello, "+name+"!").
 
 Doing everything in one step,
 ::
-    load system io.
+  load system io.
 
-    print ("Hello, "+input("Enter your name: ")+"!").
+  io @println ("Hello, "+io @input("Enter your name: ")+"!").
 
 Challenge: String length
 ^^^^^^^^^^^^^^^^^^^^^^^^
 
 > Print the length of a string.
 
-In order to print the length of a string we can use the function `len` available in the `util` module,
+In order to print the length of a string we can use the function ``len`` available in the ``util`` module,
 ::
-    load system io.
-    load system util.
+  load system io.
+
+  load "util".
+  io @println (len("Hello!")).
+
+Output::
 
-    println (len("Hello!")).
-Output:
-::
     6
 
 
-We can also use the string member function `length` in order to compute the length of the string,
+We can also use the string member function ``length`` in order to compute the length of the string,
 ::
-    load system io.
+  load system io.
+
+  io @println ("Hello!" @length()).
+
+Output::
 
-    println ("Hello!" @length()).
-Output:
-::
     6
 
 
@@ -87,31 +102,31 @@ Challenge: Unique digits
 
 > Print unique digits from a given integer number.
 
-In order to accomplish this we take advantage of the string `explode` function and the `sort` function on lists.
-Finally we use the `reduce` function to map a list with repeated digits to a list with unique digits,
+In order to accomplish this we take advantage of the string ``explode`` function and the ``sort`` function on lists.
+Finally we use the ``reduce`` function to map a list with repeated digits to a list with unique digits,
 ::
-    load system io.
+  load system io.
 
-    function unique with (x,y) do
-        if not (x @member(y)) do
-            return x @append(y).
-        else do
-            return x.
-        end
-    end
+  function unique with (x,y) do
+      if not (x @member(y)) do
+          return x @append(y).
+      else do
+          return x.
+      end
+  end
 
-    let digits = "332211" @explode()
-                          @sort()
-                          @reduce(unique,[]).
-    println digits.
+  let digits = "332211" @explode()
+                        @sort()
+                        @reduce(unique,[]).
+  io @println digits.
+  assert(digits == ["1","2","3"]).
+
+Output::
 
-    assert(digits == ["1","2","3"]).
-Output:
-::
     [1,2,3]
 
 
-Probably the most noteworthy characteric about this program is the `reduce` function.  The `reduce` function applies a binary function to a list.  The first argument of the binary function acts like an accumulator, and the second argument gets instantiated with the elements of the list to be processed.  In our function `unique`, the variable `x` is the accumulator with an initial value of `[]`.  The function tests whether the element `y` is in the list.  If it is not, then it adds it to the list. Otherwise, it just returns the accumulator unchanged.
+Probably the most noteworthy characteric about this program is the ``reduce`` function.  The ``reduce`` function applies a binary function to a list.  The first argument of the binary function acts like an accumulator, and the second argument gets instantiated with the elements of the list to be processed.  In our function ``unique``, the variable ``x`` is the accumulator with an initial value of ``[]``.  The function tests whether the element ``y`` is in the list.  If it is not, then it adds it to the list. Otherwise, it just returns the accumulator unchanged.
 
 Section: Modifying String Data
 ------------------------------
@@ -121,18 +136,18 @@ Challenge: Reverse a string
 
 > Print a string in the reversed order from right to left.
 
-We use the `explode` function to turn a string into a list of characters. Then, we reverse the list and turn it back into a string using the `join` function,
+We use the ``explode`` function to turn a string into a list of characters. Then, we reverse the list and turn it back into a string using the ``join`` function,
 ::
-    load system io.
+  load system io.
 
-    let str = "Hello, World!" @explode()
-                              @reverse()
-                              @join("").
-    println str.
+  let str = "Hello, World!" @explode()
+                            @reverse()
+                            @join("").
+  io @println str.
+  assert(str == "!dlroW ,olleH").
+
+Output::
 
-    assert(str == "!dlroW ,olleH").
-Output:
-::
     !dlroW ,olleH
 
 
@@ -141,15 +156,14 @@ Challenge: Removing blanks from a string
 
 > Remove leading, trailing, and double spaces from a given string.
 ::
-    load system io.
+  load system io.
+  let str = "   Hello  ,   World    !   " @trim()
+                                          @replace("  ","").
+  io @println str.
+  assert(str == "Hello, World!").
 
-    let str = "   Hello  ,   World    !   " @trim()
-                                            @replace("  ","").
-    println str.
+Output::
 
-    assert(str == "Hello, World!").
-Output:
-::
     Hello, World!
 
 
@@ -158,34 +172,34 @@ Challenge: Camel case
 
 > Create a camel-case identifier from a given phrase.
 
-In this task, we will form the `CamelCase` variable for names from a given phrase.
+In this task, we will form the ``CamelCase`` variable for names from a given phrase.
 Names created in this style are built of several words, each of which starts
 with a capital letter.
 ::
-    load system io.
-
-    function title with w do
-        let letter_list = w @tolower()
-                            @explode().
-        let first_letter = letter_list @0
-                                       @toupper().
-        if letter_list @length() > 1 do
-            let title_case = ([first_letter] + letter_list @[1 to letter_list@length()-1]) @join("").
-        else
-            let title_case = first_letter.
-        end
-        return title_case.
-    end
-
-    let str = "once upon a time".
-    let camel_str = str @split()
-                        @map(title)
-                        @join("").
-    println camel_str.
+  load system io.
+
+  function title with w do
+      let letter_list = w @tolower()
+                          @explode().
+      let first_letter = letter_list @0
+                                     @toupper().
+      if letter_list @length() > 1 do
+          let title_case = ([first_letter] + letter_list @[1 to letter_list@length()-1]) @join("").
+      else
+          let title_case = first_letter.
+      end
+      return title_case.
+  end
+
+  let str = "once upon a time".
+  let camel_str = str @split()
+                      @map(title)
+                      @join("").
+  io @println camel_str.
+  assert(camel_str == "OnceUponATime").
+
+Output::
 
-    assert(camel_str == "OnceUponATime").
-Output:
-::
     OnceUponATime
 
 
@@ -194,16 +208,17 @@ Challenge: Incrementing filenames
 
 > Generate a list of filenames like file1.txt, file2.txt, etc.
 ::
-    load system io.
+  load system io.
 
-    let root = "file".
-    let ext = ".txt".
+  let root = "file".
+  let ext = ".txt".
+
+  for i in 1 to 5 do
+      io @println (root+i+ext).
+  end
+
+Output::
 
-    for i in 1 to 5 do
-        println (root+i+ext).
-    end
-Output:
-::
     file1.txt
     file2.txt
     file3.txt
@@ -216,30 +231,33 @@ Challenge: Random passwords
 
 > Generate a random string that can be used as a password.
 
-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.
+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 util.
-    load system pick.
+  load system io.
+  load system type.
+  load system util.
+  load system pick.
+  load system random.
 
-    seed(42).
+  random @seed(42).
 
-    -- make up lists of symbols useful for password construction
-    let int_list = [0 to 9] @map(tostring).
-    let lc_list = [97 to 122] @map(achar). -- lower case characters
-    let uc_list = [65 to 90] @map(achar). --upper case characters
-    let sp_list = ["!","_","#","$","%","*"].
-    -- build the overall pick list of symbols
-    let pick_list = int_list+lc_list+uc_list+sp_list.
+  -- make up lists of symbols useful for password construction
+  let int_list = [0 to 9] @map(type @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 = ["!","_","#","$","%","*"].
+  -- build the overall pick list of symbols
+  let pick_list = int_list+lc_list+uc_list+sp_list.
 
-    -- generate the password and print it.
-    let pwd = Pick pick_list @pick(15)
-                             @join("").
-    println pwd.
+  -- generate the password and print it.
+  let pwd = pick @pick pick_list @pick(15)
+                           @join("").
+  io @println pwd.
+
+  assert (pwd == "e3zvshdbS43brt#")
+
+Output::
 
-    assert (pwd == "e3zvshdbS43brt#")
-Output:
-::
     e3zvshdbS43brt#
 
 
@@ -252,37 +270,41 @@ We’ll not dig deep into the biology aspect of the problem. For us, it is impor
 and the RNA is a string of A, C, G, and U. The transformation from DNA
 to RNA happens according to the following table:
 ::
+
     DNA: A C G T
     RNA: U G C A
 
 We will solve this programming problem using Asteroid's first-class patterns. We could have solved this with just testing equality on DNA characters. However, using first-class patterns is more general and can be applied to problems with a more structured mapping relationship.
 ::
-    load system io.
-
-    let dna2rna_table =
-        [("A","U"),
-         ("C","G"),
-         ("G","C"),
-         ("T","A")].
-
-    function dna2rna with x do
-        for (dna,rna) in dna2rna_table do
-            if x is *dna do
-                return rna.
-            end
-        end
-        throw Error("unknown dna char "+x).
-    end
-
-    let dna_seq = "ACCATCAGTC".
-    let rna_seq = dna_seq @explode()
-                          @map(dna2rna)
-                          @join("").
-    println rna_seq.
-
-    assert(rna_seq == "UGGUAGUCAG").
-Output:
-::
+  load system io.
+
+  let dna2rna_table =
+      [
+        ("A","U"),
+        ("C","G"),
+        ("G","C"),
+        ("T","A")
+      ].
+
+  function dna2rna with x do
+      for (dna,rna) in dna2rna_table do
+          if x is *dna do
+              return rna.
+          end
+      end
+      throw Error("unknown dna char "+x).
+  end
+
+  let dna_seq = "ACCATCAGTC".
+  let rna_seq = dna_seq @explode()
+                        @map(dna2rna)
+                        @join("").
+  io @println rna_seq.
+
+  assert(rna_seq == "UGGUAGUCAG").
+
+Output::
+
     UGGUAGUCAG
 
 
@@ -298,45 +320,49 @@ For example, if N is 4, then the letter e becomes a, f is transformed to b,
 etc. The alphabet is looped so that z becomes v, and letters a to d become
 w to z.
 ::
-    load system io.
-    load system util.
-
-    let encode_table = [119 to 122] @map(achar) + [97 to 118] @map(achar).
-
-    function encode with (v:%string) if len(v) == 1 do
-        -- only lowercase letters are encoded
-        if not (ascii(v) in [97 to 122]) do
-            return v.
-        else
-            return encode_table @(ascii(v)-ascii("a")).
-        end
-    end
-
-    function decode with (v:%string) if len(v) == 1 do
-        -- only lowercase letters are decoded
-        if not (ascii(v) in [97 to 122]) do
-            return v.
-        else
-            return encode_table @(ascii(v)-ascii("w")+4).
-        end
-    end
-
-    let message = "hello, world!"
-    let secret = message @explode()
-                         @map(encode)
-                         @join("").
-    println secret.
-
-    assert (secret == "dahhk, sknhz!")
-
-    let decoded_msg = secret @explode()
-                             @map(decode)
-                             @join("").
-    println decoded_msg.
-
-    assert (decoded_msg == "hello, world!")
-Output:
-::
+  load system io.
+  load system util.
+
+  let achar = util @achar.
+  let ascii = util @ascii.
+
+  let encode_table = [119 to 122] @map(achar) + [97 to 118] @map(achar).
+
+  function encode with (v:%string) if len(v) == 1 do
+      -- only lowercase letters are encoded
+      if not (ascii(v) in [97 to 122]) do
+          return v.
+      else
+          return encode_table @(ascii(v)-ascii("a")).
+      end
+  end
+
+  function decode with (v:%string) if len(v) == 1 do
+      -- only lowercase letters are decoded
+      if not (ascii(v) in [97 to 122]) do
+          return v.
+      else
+          return encode_table @(ascii(v)-ascii("w")+4).
+      end
+  end
+
+  let message = "hello, world!"
+  let secret = message @explode()
+                       @map(encode)
+                       @join("").
+  io @println secret.
+
+  assert (secret == "dahhk, sknhz!")
+
+  let decoded_msg = secret @explode()
+                           @map(decode)
+                           @join("").
+  io @println decoded_msg.
+
+  assert (decoded_msg == "hello, world!")
+
+Output::
+
     dahhk, sknhz!
     hello, world!
 
@@ -349,19 +375,20 @@ Challenge: Plural endings
 
 > Put a noun in the correct form — singular or plural — depending on the number next to it.
 
-In program outputs, it is often required to print some number followed by a noun, for example:
-::
+In program outputs, it is often required to print some number followed by a noun, for example::
+
     10 files found
 
-If there is only one file, then the phrase should be `1 file found` instead.
+If there is only one file, then the phrase should be ``1 file found`` instead.
 ::
-    load system io.
+  load system io.
+
+  for n in 0 to 5 do
+      io @println (n+" file"+("s " if n>1 or n==0 else " ")+"found").
+  end
+
+Output::
 
-    for n in 0 to 5 do
-        println (n+" file"+("s " if n>1 or n==0 else " ")+"found").
-    end
-Output:
-::
     0 files found
     1 file found
     2 files found
@@ -375,46 +402,69 @@ Challenge: The most frequent word
 
 > Find the most frequent word in the given text.
 
-In our solution we use a hash table to count the number of word occurances.
-::
-    load system io.
-    load system util.
-    load system hash.
-
-    -- text generated at 'https://www.lipsum.com/'
-    let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed accumsan magna quis risus commodo, et pellentesque dui cursus. Sed quis risus libero. Cras et mattis libero, eget varius nisi. Phasellus ultrices, augue non dictum eleifend, nunc elit blandit velit, a viverra risus enim in tellus. Maecenas quis ante eget turpis rhoncus rhoncus eget ut mauris. Suspendisse nec erat sed nunc tempus hendrerit. Nunc dictum nunc molestie eleifend tempus. Praesent cursus lorem diam, sed mattis velit vehicula scelerisque. Nunc iaculis rhoncus ante. Etiam quam nisi, fermentum et euismod a, vulputate eu elit. Suspendisse tincidunt ligula quis interdum blandit. Quisque sed aliquam tellus. Pellentesque ac lacus pulvinar, ornare purus ac, viverra ex. Donec quis pharetra dolor.
+In our solution we use a hash table to count the number of word occurences.
+::
+
+  load system io.
+  load system util.
+  load system hash.
+
+  -- text generated at 'https://www.lipsum.com/'
+  let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
+  accumsan magna quis risus commodo, et pellentesque dui cursus. Sed quis risus
+  libero. Cras et mattis libero, eget varius nisi. Phasellus ultrices, augue non
+  dictum eleifend, nunc elit blandit velit, a viverra risus enim in tellus.
+  Maecenas quis ante eget turpis rhoncus rhoncus eget ut mauris. Suspendisse nec
+  erat sed nunc tempus hendrerit. Nunc dictum nunc molestie eleifend tempus.
+  Praesent cursus lorem diam, sed mattis velit vehicula scelerisque. Nunc iaculis
+  rhoncus ante. Etiam quam nisi, fermentum et euismod a, vulputate eu elit.
+  Suspendisse tincidunt ligula quis interdum blandit. Quisque sed aliquam tellus.
+  Pellentesque ac lacus pulvinar, ornare purus ac, viverra ex. Donec quis pharetra
+  dolor.
+
+  In ac massa tortor. Cras sagittis luctus scelerisque. Morbi a neque sed tortor
+  ultrices dapibus. Mauris pretium vitae massa non auctor. Cras egestas ex ante,
+  ac ullamcorper ante dignissim eget. Fusce bibendum justo ut enim luctus, id
+  volutpat diam lacinia. Mauris sit amet ante risus.
+
+  Nullam rhoncus ultricies dui. Etiam vel metus vehicula, pellentesque felis ut,
+  suscipit nunc. Sed nec interdum lorem. Maecenas odio erat, vestibulum nec
+  dapibus id, commodo vitae libero. Nulla sed urna sit amet nunc commodo finibus
+  sed vel elit. Aliquam euismod feugiat nisi quis placerat. Aliquam libero nisl,
+  ultrices non est at, sagittis hendrerit dui. Quisque id sem lorem. Nam ultricies
+  metus id ultrices molestie. Pellentesque elementum consequat nibh, nec convallis
+  lorem ullamcorper in. Etiam vitae mi tellus. Etiam accumsan massa sit amet dolor
+  tincidunt iaculis. Nam ullamcorper blandit sem id bibendum. Quisque elementum
+  ipsum ac sapien blandit vehicula."
+
+  -- get rid of punctuation, turn to lower case, and split into words.
+  -- Note: we could have employed richer regular expressions to clean up the text here
+  let wl = text @replace("\.","")
+                @replace(",","")
+                @tolower()
+                @split().
+
+  -- 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
+          ht @insert(w,1).
+      else do
+          ht @insert(w,ht @get(w)+1).
+      end
+  end
+
+  -- get the contents of hash table and find the most frequent word
+  let (keys,values) = util @unzip(ht@aslist()).
+  let values_sorted = values @copy()
+                             @sort(true).
+  let most_frequent_word = keys @(values @index(values_sorted @0)).
+  io @println most_frequent_word.
+
+  assert (most_frequent_word == "sed").
+
+Output::
 
-    In ac massa tortor. Cras sagittis luctus scelerisque. Morbi a neque sed tortor ultrices dapibus. Mauris pretium vitae massa non auctor. Cras egestas ex ante, ac ullamcorper ante dignissim eget. Fusce bibendum justo ut enim luctus, id volutpat diam lacinia. Mauris sit amet ante risus.
-
-    Nullam rhoncus ultricies dui. Etiam vel metus vehicula, pellentesque felis ut, suscipit nunc. Sed nec interdum lorem. Maecenas odio erat, vestibulum nec dapibus id, commodo vitae libero. Nulla sed urna sit amet nunc commodo finibus sed vel elit. Aliquam euismod feugiat nisi quis placerat. Aliquam libero nisl, ultrices non est at, sagittis hendrerit dui. Quisque id sem lorem. Nam ultricies metus id ultrices molestie. Pellentesque elementum consequat nibh, nec convallis lorem ullamcorper in. Etiam vitae mi tellus. Etiam accumsan massa sit amet dolor tincidunt iaculis. Nam ullamcorper blandit sem id bibendum. Quisque elementum ipsum ac sapien blandit vehicula."
-
-    -- get rid of punctuation, turn to lower case, and split into words.
-    -- Note: we could have employed richer regular expressions to clean up the text here
-    let wl = text @replace("\.","")
-                  @replace(",","")
-                  @tolower()
-                  @split().
-
-    -- put the words into a hash table, the value is the count of the words
-    let ht = HashTable().
-    for w in wl do
-        if not ht @get(w) do
-            ht @insert(w,1).
-        else do
-            ht @insert(w,ht @get(w)+1).
-        end
-    end
-
-    -- get the contents of hash table and find the most frequent word
-    let (keys,values) = unzip(ht@aslist()).
-    let values_sorted = values @copy()
-                               @sort(true).
-    let most_frequent_word = keys @(values @index(values_sorted @0)).
-    println most_frequent_word.
-
-    assert (most_frequent_word == "sed").
-Output:
-::
     sed
 
 
@@ -426,33 +476,34 @@ Challenge: The longest common substring
 Let us limit ourselves with finding only the first longest substring. If there
 are more common substrings of the same length, then the rest are ignored.
 There are two loops (see also Task 17, The longest palindrome) over the first
-string (`stra`). These use the index method to search for the substring in the
-second string (`strb`).
-::
-    load system io.
-
-    let stra = "the quick brown fox jumps over the lazy dog".
-    let strb = "what does the fox say?".
-    let common = "".
-
-    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
-                let common = s.
-            end
-        end
-    end
-
-    if common do
-        println ("The longest common substring is '"+common+"'.").
-    else do
-        println ("There are no common substrings.").
-    end
-
-    assert (common == " fox ").
-Output:
+string (``stra``). These use the index method to search for the substring in the
+second string (``strb``).
 ::
+  load system io.
+
+  let stra = "the quick brown fox jumps over the lazy dog".
+  let strb = "what does the fox say?".
+  let common = "".
+
+  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
+              let common = s.
+          end
+      end
+  end
+
+  if common do
+      io @println ("The longest common substring is '"+common+"'.").
+  else do
+      io @println ("There are no common substrings.").
+  end
+
+  assert (common == " fox ").
+
+Output::
+
     The longest common substring is ' fox '.
 
 
@@ -461,28 +512,29 @@ Challenge: Anagram test
 
 > Tell if the two words are anagrams of each other.
 
-An anagram is a word, phrase, or name formed by rearranging the letters of another, such as `cinema`, formed from `iceman`.
+An anagram is a word, phrase, or name formed by rearranging the letters of another, such as ``cinema``, formed from ``iceman``.
 ::
-    load system io.
+  load system io.
 
-    let str1 = "cinema".
-    let str2 = "iceman".
+  let str1 = "cinema".
+  let str2 = "iceman".
 
-    function normalize with str do
-        return str @explode()
-                   @sort()
-                   @join("").
-    end
+  function normalize with str do
+      return str @explode()
+                 @sort()
+                 @join("").
+  end
 
-    if normalize(str1) == normalize(str2) do
-        println "Anagrams".
-    else do
-        println "Not anagrams".
-    end
+  if normalize(str1) == normalize(str2) do
+      io @println "Anagrams".
+  else do
+      io @println "Not anagrams".
+  end
+
+  assert (normalize(str1) == normalize(str2)).
+
+Output::
 
-    assert (normalize(str1) == normalize(str2)).
-Output:
-::
     Anagrams
 
 
@@ -494,28 +546,29 @@ Challenge: Palindrome test
 A palindrome is a string that can be read from both ends: left to right or right
 to left.
 ::
-    load system io.
+  load system io.
 
-    let str = "Was it a rat I saw?".
+  let str = "Was it a rat I saw?".
 
-    function clean with str:%string do
-        return str @tolower()
-                   @replace("[^a-z]","").
-    end
+  function clean with str:%string do
+      return str @tolower()
+                 @replace("[^a-z]","").
+  end
 
-    -- only keep lower case letters
-    let clean_str = clean(str).
+  -- only keep lower case letters
+  let clean_str = clean(str).
 
-    -- check if it is palidromic
-    if clean_str == clean_str @flip() do
-        println "Palindromic".
-    else do
-        println "Not palindromic".
-    end
+  -- check if it is palidromic
+  if clean_str == clean_str @flip() do
+      io @println "Palindromic".
+  else do
+      io @println "Not palindromic".
+  end
+
+  assert (clean_str == clean_str @flip()).
+
+Output::
 
-    assert (clean_str == clean_str @flip()).
-Output:
-::
     Palindromic
 
 
@@ -532,98 +585,170 @@ Now, extract the substring and do the check similar to the solution of Task
 without taking into account the non-letter characters, but saving the result as
 part of the original string.
 ::
-    load system io.
-
-    let str = "Hello, World!".
-
-    function clean with str:%string do
-        return str @tolower()
-                   @replace("[^a-z]","").
-    end
-
-    function palindrome_test with str:%string do
-        let clean_str = clean(str).
-        if clean_str == clean_str @flip() do
-            return true.
-        else do
-            return false.
-        end
-    end
-
-    -- create the moving window over the string
-    let longest_palindrome = "".
-
-    for i in 0 to str @length()-2 do
-        for j in i+1 to str @length()-1 do
-            let str1 = str @[i to j].
-            if palindrome_test(str1) and
-            str1 @length() > longest_palindrome @length() do
-                let longest_palindrome = str1.
-            end
-        end
-    end
-
-    println longest_palindrome.
-Output:
-::
-    o, Wo
-
+  load system io.
 
-Challenge: Finding duplicate texts
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-> Find duplicate fragments in the same text.
-
-We do this by finding and hashing N-grams after the appropriate preprocessing.  We will use `N=3`.
-::
-    load system io.
-    load system hash.
+  let str = "Hello, World!".
 
-    -- text from "www.lipsum.com"
+  function clean with str:%string do
+      return str @tolower()
+                 @replace("[^a-z]","").
+  end
 
-    let str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada sapien nec neque suscipit, non rutrum arcu scelerisque. Nam feugiat sapien porta ipsum accumsan, eget maximus diam volutpat. Pellentesque elementum in orci quis pretium. Donec dignissim nunc lectus, id ornare urna varius ut. Praesent semper faucibus vehicula. Aliquam luctus sapien at lorem malesuada, eget suscipit felis facilisis. Suspendisse velit lectus, mollis sit amet tempor eget, faucibus ut nulla. Vestibulum et elementum dolor, a vehicula ipsum. Morbi ut fringilla nisi. Fusce congue rutrum orci nec porta. Ut laoreet justo vel turpis sodales vehicula. Nulla porttitor nisl id odio eleifend sodales.
+  function palindrome_test with str:%string do
+      let clean_str = clean(str).
+      if clean_str == clean_str @flip() do
+          return true.
+      else do
+          return false.
+      end
+  end
 
-    Suspendisse blandit tristique enim id laoreet. Etiam vel aliquet dui, quis tempus magna. Donec blandit volutpat felis egestas tincidunt. Integer placerat luctus mi non pharetra. Donec aliquet nisl orci, egestas elementum nunc bibendum a. Morbi nec risus aliquet, viverra nunc in, molestie odio. Curabitur pellentesque, ante eget dictum aliquam, felis leo bibendum libero, vel bibendum lorem velit eget ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pretium tellus quis ante vulputate, pretium tincidunt ipsum dapibus. Praesent congue, ipsum ut sagittis tempus, lacus nisi dapibus dui, aliquam porta metus odio ut neque. Aliquam vitae faucibus dolor. Nulla iaculis lorem non mauris viverra, ut malesuada nibh aliquam. Nam bibendum sit amet massa in dignissim. Nam posuere nunc ante, at viverra diam rhoncus vel.
+  -- create the moving window over the string
+  let longest_palindrome = "".
 
-    Aliquam mollis sagittis nulla. Maecenas faucibus eu dui eget accumsan. Suspendisse sit amet fermentum sapien. Nunc vitae mi nibh. Mauris condimentum vestibulum imperdiet. Quisque at vehicula dui. Integer sit amet volutpat arcu. Maecenas efficitur leo tortor, non ullamcorper magna tempor non. Sed efficitur quis metus ut pulvinar. Proin nunc felis, congue sit amet nibh placerat, tincidunt mattis nunc. Duis efficitur lacus a orci porttitor, sed molestie risus tempor.
+  for i in 0 to str @length()-2 do
+      for j in i+1 to str @length()-1 do
+          let str1 = str @[i to j].
+          if palindrome_test(str1) and
+             str1 @length() > longest_palindrome @length() do
+              let longest_palindrome = str1.
+          end
+      end
+  end
 
-    Sed tincidunt ipsum at urna sollicitudin feugiat. Ut mollis orci quis massa dictum facilisis. Maecenas non elementum mauris. Sed rutrum orci faucibus, tristique nunc nec, mattis ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Morbi pellentesque dolor sit amet nunc tincidunt, ut rutrum ante vulputate. Nullam pretium, mi sed condimentum luctus, ipsum nunc dictum lorem, vel ultricies nibh mi ut sem. Nam volutpat id libero eget mollis.
+  io @println longest_palindrome.
 
-    Vestibulum eget velit eros. Phasellus sit amet vestibulum odio, vel malesuada quam. Mauris dictum erat eu ligula mollis laoreet. Phasellus ut ante auctor, hendrerit ipsum et, fermentum magna. Etiam nec eros elementum, consectetur nibh ac, ullamcorper ligula. Aliquam sed porttitor sapien. Nulla tincidunt, turpis vitae venenatis aliquet, quam purus elementum diam, in tincidunt orci diam sed nulla. Cras pellentesque non diam quis sollicitudin. Duis suscipit lectus dui, eu varius metus pretium sit amet.
+Output::
 
-    Nulla eu ex velit. Ut non justo semper, gravida erat quis, vehicula est. Suspendisse nunc dui, iaculis id purus sit amet, rutrum commodo lacus. Aenean consequat turpis a est vestibulum, ac accumsan nibh dapibus. Nam blandit scelerisque lectus, eu pellentesque arcu ornare non. Fusce ac gravida diam. Ut in fringilla eros. Sed metus augue, porta quis vehicula at, pellentesque et mauris. Duis sodales lacus sit amet condimentum placerat. In blandit tristique nulla eget malesuada. Sed congue finibus neque at semper. Etiam pellentesque egestas urna, ut lobortis odio euismod et. Phasellus aliquet quam purus, quis ullamcorper sem mollis eu.
-
-    Mauris quis ullamcorper nisi. Aenean quam nulla, sodales eu faucibus in, mattis a nulla. Nullam pulvinar pretium justo eu mattis. Aliquam rutrum ipsum vitae leo maximus ultrices. Donec ut pulvinar nisi. Sed pharetra, turpis dictum lobortis egestas, quam massa venenatis enim, dapibus efficitur dolor mauris eu felis. Donec vulputate ultrices justo sit amet condimentum. Donec id posuere nulla. In vestibulum mi in lectus commodo dignissim. Quisque vestibulum egestas arcu sit amet finibus. Proin commodo aliquet neque quis maximus.
-
-    Nulla facilisi. Sed gravida aliquet diam in congue. Mauris vehicula justo ac sollicitudin laoreet. Mauris enim mi, auctor id magna eget, feugiat sollicitudin leo. Vivamus ornare ornare commodo. Suspendisse ut dui quis enim porta pretium. Praesent vitae lacus fermentum, posuere orci ac, imperdiet massa. Nulla hendrerit id nisl sed maximus. Vivamus commodo lacus eu condimentum bibendum. Suspendisse porttitor sem eget dolor aliquet congue. Pellentesque tristique augue at quam hendrerit dignissim. Aenean a congue dui. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer ante lacus, commodo et enim sed, auctor egestas metus.
-
-    Aliquam a urna id risus tincidunt rutrum. Nunc facilisis, tortor ac suscipit aliquam, ante neque tincidunt mi, nec ullamcorper lectus ligula vel urna. Suspendisse lobortis at felis sit amet facilisis. Pellentesque velit lacus, porttitor vitae eros rutrum, convallis blandit erat. Pellentesque nec mi viverra, volutpat dui in, rutrum lacus. Ut non venenatis leo. Praesent sollicitudin magna porttitor lorem elementum molestie non a turpis. Suspendisse potenti.
+    o, Wo
 
-    Donec malesuada iaculis laoreet. Nunc ut volutpat ante, ut consequat tortor. Phasellus posuere, ipsum quis dignissim iaculis, nisl felis ullamcorper ligula, quis placerat sem sapien nec ante. Cras suscipit ut magna nec lacinia. Donec ipsum nibh, imperdiet non aliquam eu, maximus id ante. Pellentesque vitae felis felis. Aliquam et diam sed nulla volutpat vestibulum molestie non lacus. Praesent porta et lacus auctor fermentum. In hac habitasse platea dictumst. Aliquam erat volutpat. Etiam at ligula orci. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos."
 
+Challenge: Finding duplicate texts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-    let word_list = str @tolower()
-                        @replace("[^a-z0-9_]"," ")
-                        @split().
-    let ht = HashTable().
+> Find duplicate fragments in the same text.
 
-    -- create N-grams
-    for i in 0 to word_list @length()-3 do
-        -- 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
-            ht @insert(n_gram,1).
-        else do
-            ht @insert(n_gram,ht @get(n_gram)+1).
-        end
-    end
+We do this by finding and hashing N-grams after the appropriate preprocessing.  We will use ``N=3``.
+::
+  load system io.
+  load system hash.
+
+  -- text from "www.lipsum.com"
+
+  let str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
+  malesuada sapien nec neque suscipit, non rutrum arcu scelerisque. Nam feugiat
+  sapien porta ipsum accumsan, eget maximus diam volutpat. Pellentesque elementum
+  in orci quis pretium. Donec dignissim nunc lectus, id ornare urna varius ut.
+  Praesent semper faucibus vehicula. Aliquam luctus sapien at lorem malesuada,
+  eget suscipit felis facilisis. Suspendisse velit lectus, mollis sit amet tempor
+  eget, faucibus ut nulla. Vestibulum et elementum dolor, a vehicula ipsum. Morbi
+  ut fringilla nisi. Fusce congue rutrum orci nec porta. Ut laoreet justo vel
+  turpis sodales vehicula. Nulla porttitor nisl id odio eleifend sodales.
+
+  Suspendisse blandit tristique enim id laoreet. Etiam vel aliquet dui, quis
+  tempus magna. Donec blandit volutpat felis egestas tincidunt. Integer placerat
+  luctus mi non pharetra. Donec aliquet nisl orci, egestas elementum nunc bibendum
+  a. Morbi nec risus aliquet, viverra nunc in, molestie odio. Curabitur
+  pellentesque, ante eget dictum aliquam, felis leo bibendum libero, vel bibendum
+  lorem velit eget ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+  Vestibulum pretium tellus quis ante vulputate, pretium tincidunt ipsum dapibus.
+  Praesent congue, ipsum ut sagittis tempus, lacus nisi dapibus dui, aliquam porta
+  metus odio ut neque. Aliquam vitae faucibus dolor. Nulla iaculis lorem non
+  mauris viverra, ut malesuada nibh aliquam. Nam bibendum sit amet massa in
+  dignissim. Nam posuere nunc ante, at viverra diam rhoncus vel.
+
+  Aliquam mollis sagittis nulla. Maecenas faucibus eu dui eget accumsan.
+  Suspendisse sit amet fermentum sapien. Nunc vitae mi nibh. Mauris condimentum
+  vestibulum imperdiet. Quisque at vehicula dui. Integer sit amet volutpat arcu.
+  Maecenas efficitur leo tortor, non ullamcorper magna tempor non. Sed efficitur
+  quis metus ut pulvinar. Proin nunc felis, congue sit amet nibh placerat,
+  tincidunt mattis nunc. Duis efficitur lacus a orci porttitor, sed molestie risus
+  tempor.
+
+  Sed tincidunt ipsum at urna sollicitudin feugiat. Ut mollis orci quis massa
+  dictum facilisis. Maecenas non elementum mauris. Sed rutrum orci faucibus,
+  tristique nunc nec, mattis ante. Pellentesque habitant morbi tristique senectus
+  et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst.
+  Morbi pellentesque dolor sit amet nunc tincidunt, ut rutrum ante vulputate.
+  Nullam pretium, mi sed condimentum luctus, ipsum nunc dictum lorem, vel
+  ultricies nibh mi ut sem. Nam volutpat id libero eget mollis.
+
+  Vestibulum eget velit eros. Phasellus sit amet vestibulum odio, vel malesuada
+  quam. Mauris dictum erat eu ligula mollis laoreet. Phasellus ut ante auctor,
+  hendrerit ipsum et, fermentum magna. Etiam nec eros elementum, consectetur nibh
+  ac, ullamcorper ligula. Aliquam sed porttitor sapien. Nulla tincidunt, turpis
+  vitae venenatis aliquet, quam purus elementum diam, in tincidunt orci diam sed
+  nulla. Cras pellentesque non diam quis sollicitudin. Duis suscipit lectus dui,
+  eu varius metus pretium sit amet.
+
+  Nulla eu ex velit. Ut non justo semper, gravida erat quis, vehicula est.
+  Suspendisse nunc dui, iaculis id purus sit amet, rutrum commodo lacus. Aenean
+  consequat turpis a est vestibulum, ac accumsan nibh dapibus. Nam blandit
+  scelerisque lectus, eu pellentesque arcu ornare non. Fusce ac gravida diam. Ut
+  in fringilla eros. Sed metus augue, porta quis vehicula at, pellentesque et
+  mauris. Duis sodales lacus sit amet condimentum placerat. In blandit tristique
+  nulla eget malesuada. Sed congue finibus neque at semper. Etiam pellentesque
+  egestas urna, ut lobortis odio euismod et. Phasellus aliquet quam purus, quis
+  ullamcorper sem mollis eu.
+
+  Mauris quis ullamcorper nisi. Aenean quam nulla, sodales eu faucibus in, mattis
+  a nulla. Nullam pulvinar pretium justo eu mattis. Aliquam rutrum ipsum vitae leo
+  maximus ultrices. Donec ut pulvinar nisi. Sed pharetra, turpis dictum lobortis
+  egestas, quam massa venenatis enim, dapibus efficitur dolor mauris eu felis.
+  Donec vulputate ultrices justo sit amet condimentum. Donec id posuere nulla. In
+  vestibulum mi in lectus commodo dignissim. Quisque vestibulum egestas arcu sit
+  amet finibus. Proin commodo aliquet neque quis maximus.
+
+  Nulla facilisi. Sed gravida aliquet diam in congue. Mauris vehicula justo ac
+  sollicitudin laoreet. Mauris enim mi, auctor id magna eget, feugiat sollicitudin
+  leo. Vivamus ornare ornare commodo. Suspendisse ut dui quis enim porta pretium.
+  Praesent vitae lacus fermentum, posuere orci ac, imperdiet massa. Nulla
+  hendrerit id nisl sed maximus. Vivamus commodo lacus eu condimentum bibendum.
+  Suspendisse porttitor sem eget dolor aliquet congue. Pellentesque tristique
+  augue at quam hendrerit dignissim. Aenean a congue dui. Vestibulum ante ipsum
+  primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer ante
+  lacus, commodo et enim sed, auctor egestas metus.
+
+  Aliquam a urna id risus tincidunt rutrum. Nunc facilisis, tortor ac suscipit
+  aliquam, ante neque tincidunt mi, nec ullamcorper lectus ligula vel urna.
+  Suspendisse lobortis at felis sit amet facilisis. Pellentesque velit lacus,
+  porttitor vitae eros rutrum, convallis blandit erat. Pellentesque nec mi
+  viverra, volutpat dui in, rutrum lacus. Ut non venenatis leo. Praesent
+  sollicitudin magna porttitor lorem elementum molestie non a turpis. Suspendisse
+  potenti.
+
+  Donec malesuada iaculis laoreet. Nunc ut volutpat ante, ut consequat tortor.
+  Phasellus posuere, ipsum quis dignissim iaculis, nisl felis ullamcorper ligula,
+  quis placerat sem sapien nec ante. Cras suscipit ut magna nec lacinia. Donec
+  ipsum nibh, imperdiet non aliquam eu, maximus id ante. Pellentesque vitae felis
+  felis. Aliquam et diam sed nulla volutpat vestibulum molestie non lacus.
+  Praesent porta et lacus auctor fermentum. In hac habitasse platea dictumst.
+  Aliquam erat volutpat. Etiam at ligula orci. Class aptent taciti sociosqu ad
+  litora torquent per conubia nostra, per inceptos himenaeos."
+
+  let word_list = str @tolower()
+                      @replace("[^a-z0-9_]"," ")
+                      @split().
+  let ht = hash @hash().
+
+  -- create N-grams
+  for i in 0 to word_list @length()-3 do
+      -- 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
+          ht @insert(n_gram,1).
+      else do
+          ht @insert(n_gram,ht @get(n_gram)+1).
+      end
+  end
+
+  for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
+      io @println (n_gram+": "+cnt).
+  end
+
+Output::
 
-    for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
-        println (n_gram+": "+cnt).
-    end
-Output:
-::
     lorem ipsum dolor: 2
     ipsum dolor sit: 2
     dolor sit amet: 3
@@ -638,9 +763,6 @@ Output:
     sit amet condimentum: 2
 
 
-..
-  Chapter: Numbers
-  ----------------
 
 Section: Using Numbers
 ----------------------
@@ -650,24 +772,27 @@ Challenge: Pi
 
 > Print the value of pi.
 ::
-    load system io.
-    load system math. -- definition of pi
+  load system io.
+  load system math. -- definition of pi
 
-    println pi.
-Output:
-::
-    3.141592653589793
+  io @println (math @pi).
 
+Output::
+
+    3.141592653589793
 
 Other constants are also available.
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
+
+  io @println (math @e).
+  io @println (math @tau). -- tau=2*pi
+
+  assert (math @tau == 2 * math @pi)
+
+Output::
 
-    println e.
-    println tau. -- tau=2*pi
-Output:
-::
     2.718281828459045
     6.283185307179586
 
@@ -677,47 +802,50 @@ Challenge: Factorial!
 
 > Print the factorial of a given number.
 
-By definition, the factorial of a positive integer number N is a product of all the integers numbering from 1 to N, including N. Our first solution is based on the direct implementation of the definition above using the list `reduce` function.
+By definition, the factorial of a positive integer number N is a product of all the integers numbering from 1 to N, including N. Our first solution is based on the direct implementation of the definition above using the list ``reduce`` function.
 ::
-    load system io.
+  load system io.
+
+  let n = 3.
+  let fact = [1 to n] @reduce(lambda with (a,b) do return a*b).
+  io @println fact.
+  assert (fact == 6).
+
+Output::
 
-    let n = 3.
-    let fact = [1 to n] @reduce(lambda with (a,b) do return a*b).
-    println fact.
-    assert (fact == 6).
-Output:
-::
     6
 
 
 Our second solution uses the recursive definition of factorial,
 ::
+
          | 1       if  x = 0,
     x! = | x(x-1)! if  x > 0,
          | undef   if  x < 0,
 
-where `x in Int`.
+where :math:`x \in Int`.
 Here, each case specifies what value the function should return if
 the predicate applied to the input is true.  The last case is of some interest because it states that the function is undefined for negative integers.
 ::
-    load system io.
+  load system io.
 
-    let POS_INT = pattern with (x:%integer) if x > 0.
-    let NEG_INT = pattern with (x:%integer) if x < 0.
+  let POS_INT = pattern with (x:%integer) if x > 0.
+  let NEG_INT = pattern with (x:%integer) if x < 0.
 
-    function fact
-        with 0 do
-            return 1
-        with n:*POS_INT do
-            return n * fact (n-1).
-        with n:*NEG_INT do
-            throw Error("factorial is not defined for "+n).
-        end
+  function fact
+      with 0 do
+          return 1
+      with n:*POS_INT do
+          return n * fact (n-1).
+      with n:*NEG_INT do
+          throw Error("factorial is not defined for "+n).
+      end
+
+  io @println ("The factorial of 3 is: " + fact (3)).
+  assert (fact(3) == 6).
+
+Output::
 
-    println ("The factorial of 3 is: " + fact (3)).
-    assert (fact(3) == 6).
-Output:
-::
     The factorial of 3 is: 6
 
 
@@ -728,25 +856,27 @@ Challenge: Fibonacci numbers
 
 Fibonacci numbers are defined by the recurring formula:
 ::
+
     f_n = f_{n-1} + f_{n-2}
 
 You can assign two values at a time (**Challenge: Swap two values**). You can use that technique for calculating the next Fibonacci number from the previous two. To bootstrap the algorithm, the two first values are needed. In one of the definitions of the Fibonacci row, the first two values are both 1.
 
 Here we give an iterative solutions.  It is clear that there exists a trivial recursive solution by implementing the above formula.
 ::
-    load system io.
+  load system io.
 
-    let n = 10. -- compute the 10th Fib number
+  let n = 10. -- compute the 10th Fib number
 
-    let (f_1,f_2) = (1,1).
-    for i in 3 to n do
-        let (f_1,f_2) = (f_1+f_2,f_1).
-    end
+  let (f_1,f_2) = (1,1).
+  for i in 3 to n do
+      let (f_1,f_2) = (f_1+f_2,f_1).
+  end
+
+  io @println f_1.
+  assert (f_1 == 55)
+
+Output::
 
-    println f_1.
-    assert (f_1 == 55)
-Output:
-::
     55
 
 
@@ -755,17 +885,18 @@ Challenge: Print squares
 
 > Print the squares of the numbers 1 through 10.
 
-Of course this is straightforward, with a `for-loop` over a list.  Here we show another solution using the list `map` function.
+Of course this is straightforward, with a ``for-loop`` over a list.  Here we show another solution using the list ``map`` function.
 ::
-    load system io.
+  load system io.
 
-    let sq = [1 to 10] @map(lambda with x do return x*x).
+  let sq = [1 to 10] @map(lambda with x do return x*x).
 
-    println sq.
+  io @println sq.
+
+  assert (sq == [1,4,9,16,25,36,49,64,81,100])
+
+Output::
 
-    assert (sq == [1,4,9,16,25,36,49,64,81,100])
-Output:
-::
     [1,4,9,16,25,36,49,64,81,100]
 
 
@@ -774,18 +905,19 @@ Challenge: Powers of two
 
 > Print the first ten powers of two.
 
-Just as in the previous challenge, we skip the naive loop solution and give a solution using the `map` function.
+Just as in the previous challenge, we skip the naive loop solution and give a solution using the ``map`` function.
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    let p2 = [0 to 9] @map(lambda with x do return pow(2,x)).
+  let p2 = [0 to 9] @map(lambda with x do return math @pow(2,x)).
 
-    println p2.
+  io @println p2.
+
+  assert (p2 == [1,2,4,8,16,32,64,128,256,512])
+
+Output::
 
-    assert (p2 == [1,2,4,8,16,32,64,128,256,512])
-Output:
-::
     [1,2,4,8,16,32,64,128,256,512]
 
 
@@ -796,36 +928,38 @@ Challenge: Odd and even numbers
 
 We start with printing the first ten odd numbers,
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    let odd = []
-    for (n if mod(n,2) =/= 0) in 1 to 10 do
-        let odd = odd + [n].
-    end
+  let odd = []
+  for (n if math @mod(n,2) =/= 0) in 1 to 10 do
+      let odd = odd + [n].
+  end
+
+  io @println odd.
+  assert(odd == [1,3,5,7,9])
+
+Output::
 
-    println odd.
-    assert(odd == [1,3,5,7,9])
-Output:
-::
     [1,3,5,7,9]
 
 
 Now the even numbers,
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    let even = []
-    for (n if mod(n,2) == 0) in 1 to 10 do
-        let even = even + [n].
-    end
+  let even = []
+  for (n if math @mod(n,2) == 0) in 1 to 10 do
+      let even = even + [n].
+  end
 
-    println even.
+  io @println even.
+  assert(even == [2,4,6,8,10])
 
-    assert(even == [2,4,6,8,10])
 Output:
 ::
+
     [2,4,6,8,10]
 
 
@@ -834,16 +968,16 @@ Challenge: Compare numbers approximately
 
 > Compare the two non-integer values approximately.
 
-Comparing non-integer numbers (which are represented as floating-point numbers) is often a task that requires approximate comparison.  In Asteroid this can be accomplished with the `isclose` function availabel in the `math` module.
+Comparing non-integer numbers (which are represented as floating-point numbers) is often a task that requires approximate comparison.  In Asteroid this can be accomplished with the ``isclose`` function availabel in the ``math`` module.
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    -- not equal under the default tolerance of 1E-09
-    assert (not isclose(2.0,2.00001)).
+  -- not equal under the default tolerance of 1E-09
+  assert (not math @isclose(2.0,2.00001)).
 
-    -- equal under the user defined tolerance of 0.0001
-    assert (isclose(2.0,2.00001,0.0001)).
+  -- equal under the user defined tolerance of 0.0001
+  assert (math @isclose(2.0,2.00001,0.0001)).
 
 
 Challenge: Prime numbers
@@ -853,29 +987,31 @@ Challenge: Prime numbers
 
 Prime numbers are those that can be divided only by 1, and by themselves.
 ::
-    load system io.
-    load system math.
-
-    function isprime with x do
-        if x >= 2 do
-            for y in range(2,x) do
-                if not mod(x,y) do
-                    return false.
-                end
-            end
-        else do
-            return false.
-        end
-        return true.
-    end
-
-    println (isprime 17).
-    println (isprime 15).
-
-    assert (isprime(17)).
-    assert (not isprime(15)).
+  load system io.
+  load system math.
+
+  function isprime with x do
+      if x >= 2 do
+          for y in range(2,x) do
+              if not math @mod(x,y) do
+                  return false.
+              end
+          end
+      else do
+          return false.
+      end
+      return true.
+  end
+
+  io @println (isprime 17).
+  io @println (isprime 15).
+
+  assert (isprime(17)).
+  assert (not isprime(15)).
+
 Output:
 ::
+
     true
     false
 
@@ -885,32 +1021,34 @@ Challenge: List of prime numbers
 
 > Print the list of the first ten prime numbers.
 ::
-    load system io.
-    load system math.
-
-    function isprime with x do
-        if x >= 2 do
-            for y in range(2,x) do
-                if not mod(x,y) do
-                    return false.
-                end
-            end
-        else do
-            return false.
-        end
-        return true.
-    end
-
-    let cnt = 0.
-    for (n if isprime(n)) in 1 to 1000000 do
-        println n.
-        let cnt = cnt+1.
-        if cnt == 10 do
-            break.
-        end
-    end
+  load system io.
+  load system math.
+
+  function isprime with x do
+      if x >= 2 do
+          for y in range(2,x) do
+              if not math @mod(x,y) do
+                  return false.
+              end
+          end
+      else do
+          return false.
+      end
+      return true.
+  end
+
+  let cnt = 0.
+  for (n if isprime(n)) in 1 to 1000000 do
+      io @println n.
+      let cnt = cnt+1.
+      if cnt == 10 do
+          break.
+      end
+  end
+
 Output:
 ::
+
     2
     3
     5
@@ -930,49 +1068,51 @@ Challenge: Prime factors
 
 Prime factors are the prime numbers that divide the given integer number exactly.
 ::
-    load system io.
-    load system math.
-
-    function isprime with x do
-        if x >= 2 do
-            for y in range(2,x) do
-                if not mod(x,y) do
-                    return false.
-                end
-            end
-        else do
-            return false.
-        end
-        return true.
-    end
-
-    function primes with x do
-        let lp = [].
-        for (n if isprime(n)) in 1 to x do
-            let lp = lp+[n].
-        end
-        return lp.
-    end
-
-    let n = 165.
-    let factors = [].
-    let primes_list =  primes(n).
-    let ix = 0.
-
-    while n > 1 do
-        let factor = primes_list @ix.
-        let ix = ix+1.
-        if not mod(n,factor) do
-            let ix = 0.
-            let n = n/factor.
-            let factors = factors+[factor].
-        end
-    end
-    println factors.
-
-    assert (factors == [3,5,11])
+  load system io.
+  load system math.
+
+  function isprime with x do
+      if x >= 2 do
+          for y in range(2,x) do
+              if not math @mod(x,y) do
+                  return false.
+              end
+          end
+      else do
+          return false.
+      end
+      return true.
+  end
+
+  function primes with x do
+      let lp = [].
+      for (n if isprime(n)) in 1 to x do
+          let lp = lp+[n].
+      end
+      return lp.
+  end
+
+  let n = 165.
+  let factors = [].
+  let primes_list =  primes(n).
+  let ix = 0.
+
+  while n > 1 do
+      let factor = primes_list @ix.
+      let ix = ix+1.
+      if not math @mod(n,factor) do
+          let ix = 0.
+          let n = n/factor.
+          let factors = factors+[factor].
+      end
+  end
+  io @println factors.
+
+  assert (factors == [3,5,11])
+
 Output:
 ::
+
     [3,5,11]
 
 
@@ -981,26 +1121,28 @@ Challenge: Reducing a fraction
 
 > Compose a fraction from the two given integers — numerator and denominator — and reduce it to lowest terms.
 
-5/15 and 16/280 are examples of fractions that can be reduced. The final results of this task are 1/3 and 2/35. Generally, the algorithm of reducing a fraction requires searching for the greatest common divisor, and then dividing both numerator and denominator by that number.  For our solution we use the function `gcd` available in the `math` module.
+5/15 and 16/280 are examples of fractions that can be reduced. The final results of this task are 1/3 and 2/35. Generally, the algorithm of reducing a fraction requires searching for the greatest common divisor, and then dividing both numerator and denominator by that number.  For our solution we use the function ``gcd`` available in the ``math`` module.
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    -- fraction a/b
-    let a = 16.
-    let b = 280.
+  -- fraction a/b
+  let a = 16.
+  let b = 280.
 
-    -- reduce fraction
-    let gcd_val = gcd(a,b).
-    let numerator = a/gcd_val.
-    let denominator = b/gcd_val.
-    println numerator.
-    println denominator.
+  -- reduce fraction
+  let gcd_val = math @gcd(a,b).
+  let numerator = a/gcd_val.
+  let denominator = b/gcd_val.
+  io @println numerator.
+  io @println denominator.
+
+  -- show that original and reduced fraction are the same value
+  assert (a/b == numerator/denominator).
 
-    -- show that original and reduced fraction are the same value
-    assert (a/b == numerator/denominator).
 Output:
 ::
+
     2
     35
 
@@ -1012,16 +1154,18 @@ Challenge: Divide by zero
 
 Asteroid is an eager language, that is, expressions are evaluated as early as possible.  We can trap division-by-zero errors using a try-catch block.
 ::
-    load system io.
+  load system io.
+
+  try
+      io @println (42/0).
+  catch Exception(_,m) do
+      io @println m.
+  end
+  io @println "We are still alive...".
 
-    try
-        println (42/0).
-    catch (type,m) do
-        println m.
-    end
-    println "We are still alive...".
 Output:
 ::
+
     integer division or modulo by zero
     We are still alive...
 
@@ -1034,24 +1178,29 @@ Challenge: Generating random numbers
 
 > Generate a random number between 0 and N.
 
-Asteroid has two random number generation functions: `random()` generates a random real value in the interval $[0.0,1.0)$ and `randint(a,b)` that generates a random value in the interval $[a,b]$.  The type of the random value generated depends on the type of the values a and b specifying the interval.
+Asteroid has two random number generation functions: ``random()`` generates a random real value in the interval $[0.0,1.0)$ and ``randint(a,b)`` that generates a random value in the interval $[a,b]$.  The type of the random value generated depends on the type of the values a and b specifying the interval.
 ::
-    load system io.
-    load system random.
-    load system util.
+  load system io.
+  load system random.
+  load system util.
+  load system type.
+
+  let randint = random @randint.
 
-    seed(42).
+  random @seed(42).
 
-    println (random()).          -- random value in [0.0,1.0)
-    println (randint(0.0,1.0)).  -- random value in [0.0,1.0]
-    println (randint(0,1)).      -- always 0 or 1
+  io @println (random @random()).          -- random value in [0.0,1.0)
+  io @println (randint(0.0,1.0)).  -- random value in [0.0,1.0]
+  io @println (randint(0,1)).      -- always 0 or 1
+
+  -- generating a random number in the appropriate interval
+  let n = 10.
+  io @println (randint(0.0,type @toreal(n))).
+  io @println (randint(0,n)).
 
-    -- generating a random number in the appropriate interval
-    let n = 10.
-    println (randint(0.0,toreal(n))).
-    println (randint(0,n)).
 Output:
 ::
+
     0.6394267984578837
     0.025010755222666936
     1
@@ -1074,24 +1223,27 @@ This algorithm is a simple method of generating short sequences of four-digit ra
 
 To illustrate it with an example, let’s take the number 1234 as the seed. On step 2, it becomes 1522756; after step 3, 01522756. Finally, step 4 extracts the number 5227.
 ::
-    load system io.
-    load system util.
-
-    let n = 1234.
-    let sq = n*n.
-    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 = tointeger(rstr).
-    println rval.
-
-    assert (rval == 5227)
+  load system io.
+  load system util.
+  load system type.
+
+  let n = 1234.
+  let sq = n*n.
+  let sq_str = type @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).
+  io @println rval.
+
+  assert (rval == 5227)
+
 Output:
 ::
+
     5227
 
 
@@ -1104,19 +1256,21 @@ The quality of the built-in generator of random numbers fully depends on the alg
 
 In our solution, we generate 10 random integers between 0 and 9. We then count how many times each of the integers have been generated.  If it is a decent random number generator, all numbers should have been generated roughly an equal number of times.
 ::
-    load system io.
-    load system random.
+  load system io.
+  load system random.
 
-    let hist = [0 to 9] @map(lambda with _ do return 0).
+  let hist = [0 to 9] @map(lambda with _ do return 0).
 
-    for _ in range(10000) do
-        let ix = randint(0,9).
-        let hist @ix = hist @ix +1
-    end
+  for _ in range(10000) do
+      let ix = random @randint(0,9).
+      let hist @ix = hist @ix +1
+  end
+
+  io @println hist.
 
-    println hist.
 Output:
 ::
+
     [944,1032,1015,968,981,986,1014,1058,989,1013]
 
 
@@ -1131,40 +1285,45 @@ Challenge: Distance between two points
 There are two points on a surface, each with their own coordinates, x and y. The task is to find the distance between these two points.
 A straightforward solution would be to use the Pythagorean theorem:
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
+
+  let x = [10, 3].
+  let y = [9, 1].
+  let d = (math @sqrt(math @pow(x@0-y@0,2) + math @pow(x@1-y@1,2))).
+  io @println d.
 
-    let x = [10, 3].
-    let y = [9, 1].
-    let d = (sqrt(pow(x@0-y@0,2) + pow(x@1-y@1,2))).
-    println d.
+  assert (d == 2.23606797749979)
 
-    assert (d == 2.23606797749979)
 Output:
 ::
+
     2.23606797749979
 
 
 Another approach is using the math identity,
 ::
+
     ||a|| = sqrt(a . a)
 
 
-where `.` represents the dot product. In our case `a` would be the distance vector between points `x` and `y`,
+where ``.`` represents the dot product. In our case ``a`` would be the distance vector between points ``x`` and ``y``,
 ::
-    load system io.
-    load system math.
-    load system vector.
+  load system io.
+  load system math.
+  load system vector.
 
-    let x = [10, 3].
-    let y = [9, 1].
-    let a = vsub(x,y).
-    let d = sqrt(dot(a,a)).
-    println d.
+  let x = [10, 3].
+  let y = [9, 1].
+  let a = vector @sub(x,y).
+  let d = math @sqrt(vector @dot(a,a)).
+  io @println d.
+
+  assert (d == 2.23606797749979)
 
-    assert (d == 2.23606797749979)
 Output:
 ::
+
     2.23606797749979
 
 
@@ -1176,26 +1335,30 @@ Challenge: Standard deviation
 > For the given data, calculate the standard deviation value (sigma).
 
 Standard deviation is a statistical term that shows how compact data distribution is. The formula is the following:
-::
-    sigma = sqrt(Sum(x_i - avg_x)^2/(N - 1))
 
-where `N` is the number of elements in the array `x`; `avg_x` is the average value (**Challenge: Average on an array**).
+.. math::
+
+    \sigma = \sqrt\frac{1}{n-1}\sum_i(\bar{x} - x_i)^2
+
+where :math:`n` is the number of elements in the array :math:`x`; :math:`\bar{x}` is its average value (**Challenge: Average on an array**).
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
+
+  let values = [727.7, 1086.5, 1091.0, 1361.3, 1490.5, 1956.1].
 
-    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 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).
+  io @println sigma.
 
-    let avg = values @reduce(lambda with (x,y) do return x+y) / values @length().
-    let diff_sq = values @map(lambda with x do return pow(x-avg,2)).
-    let numerator = diff_sq @reduce(lambda with (x,y) do return x+y).
-    let denominator = values @length() -1.
-    let sigma = sqrt(numerator/denominator).
-    println sigma.
+  assert (sigma == 420.96248961952256)
 
-    assert (sigma == 420.96248961952256)
 Output:
 ::
+
     420.96248961952256
 
 
@@ -1205,8 +1368,9 @@ Challenge: Polar coordinates
 > Convert the Cartesian coordinates to polar and backward.
 
 Polar coordinates are a convenient way of representing points on a surface with the two values: distance from the centre of coordinates, and the angle between the vector and the pole axis.
-The conversion formulae between the Cartesian and polar systems, which is valid for **positive** `x` and `y`, are the following:
+The conversion formulae between the Cartesian and polar systems, which is valid for **positive** ``x`` and ``y``, are the following:
 ::
+
     x = r cos(psi)
     y = r sin(psi)
     r = sqrt(x^2 + y^2)
@@ -1214,74 +1378,97 @@ The conversion formulae between the Cartesian and polar systems, which is valid
 
 These expressions can be implemented as-is in the code:
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
+
+  -- define common math functions locally so the
+  -- formulas are easy to read
+  let cos = math @cos.
+  let sin = math @sin.
+  let sqrt = math @sqrt.
+  let pow = math @pow.
+  let atan = math @atan.
 
-    function polar_to_cartesian with (r,psi) do
-        -- return a tuple: (x,y)
-        return (r*cos(psi),r*sin(psi)).
-    end
+  function polar_to_cartesian with (r,psi) do
+      -- return a tuple: (x,y)
+      return (r*cos(psi),r*sin(psi)).
+  end
 
-    function cartesian_to_polar with (x,y) do
-        -- return a tuple: (r,psi)
-        return (sqrt(pow(x,2)+pow(y,2)),atan(y/x)).
-    end
+  function cartesian_to_polar with (x,y) do
+      -- return a tuple: (r,psi)
+      return (sqrt(pow(x,2)+pow(y,2)),atan(y/x)).
+  end
 
-    let (r,psi) = cartesian_to_polar(1,2).
-    let (x,y) = polar_to_cartesian(r,psi).
+  let (r,psi) = cartesian_to_polar(1,2).
+  let (x,y) = polar_to_cartesian(r,psi).
 
-    println (x,y).
+  io @println (x,y).
+
+  -- show that the recovered coordinates are the same
+  -- we started with
+  assert (math @isclose(1,x,0.0001) and math @isclose(2,y,0.0001)).
 
-    -- show that the recovered coordinates are the same
-    -- we started with
-    assert (isclose(1,x,0.0001) and isclose(2,y,0.0001)).
 Output:
 ::
+
     (1.0000000000000002,2.0)
 
 
-For the **negative** `x` and `y`, the Cartesian-to-polar conversion is a bit more complicated. Depending on the quadrant of the point, the `psi` value is bigger
-or smaller than `pi`. When `x` is zero, it is either `-pi/2` or `pi/2`.
-All these variants can be implemented by using `with`/`with` clauses and conditional matching, as demonstrated below:
-::
-    load system io.
-    load system math.
-    load system util.
-
-    function polar_to_cartesian with (r,psi) do
-        -- return a tuple: (x,y)
-        return (r*cos(psi),r*sin(psi)).
-    end
-
-    function cartesian_to_polar with (x,y) do
-        return (sqrt(pow(x,2)+pow(y,2)),cartesian_to_psi(x,y)).
-    end
-
-    function cartesian_to_psi
-        with (x,y) if x > 0  do
-            return atan(toreal(y)/x).
-        with (x,y) if x < 0 and y >= 0 do
-            return atan(toreal(y)/x)+pi.
-        with (x,y) if x < 0 and y < 0 do
-            return atan(toreal(y)/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
-            return -pi/2.
-        with (x,y) if x == 0 and y == 0 do
-            return none.
-        end
-
-    let (r,psi) = cartesian_to_polar(-3,5).
-    let (x,y) = polar_to_cartesian(r,psi).
-
-    println (x,y).
-
-    -- show that the recovered coordinates are the same
-    -- we started with
-    assert (isclose(-3,x,0.0001) and isclose(5,y,0.0001)).
+For the **negative** ``x`` and ``y``, the Cartesian-to-polar conversion is a bit more complicated. Depending on the quadrant of the point, the ``psi`` value is bigger
+or smaller than ``pi``. When ``x`` is zero, it is either ``-pi/2`` or ``pi/2``.
+All these variants can be implemented by using ``with`` clauses and conditional matching, as demonstrated below:
+::
+  load system io.
+  load system math.
+  load system util.
+  load system type.
+
+  -- define common math functions locally so the
+  -- formulas are easy to read
+  let cos = math @cos.
+  let sin = math @sin.
+  let sqrt = math @sqrt.
+  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)
+      return (r*cos(psi),r*sin(psi)).
+  end
+
+  function cartesian_to_polar with (x,y) do
+      return (sqrt(pow(x,2)+pow(y,2)),cartesian_to_psi(x,y)).
+  end
+
+  function cartesian_to_psi
+      with (x,y) if x > 0  do
+          return atan(toreal(y)/x).
+      with (x,y) if x < 0 and y >= 0 do
+          return atan(toreal(y)/x)+pi.
+      with (x,y) if x < 0 and y < 0 do
+          return atan(toreal(y)/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
+          return -pi/2.
+      with (x,y) if x == 0 and y == 0 do
+          return none.
+      end
+
+  let (r,psi) = cartesian_to_polar(-3,5).
+  let (x,y) = polar_to_cartesian(r,psi).
+
+  io @println (x,y).
+
+  -- show that the recovered coordinates are the same
+  -- we started with
+  assert (math @isclose(-3,x,0.0001) and math @isclose(5,y,0.0001)).
+
 Output:
 ::
+
     (-2.999999999999999,5.000000000000001)
 
 
@@ -1294,26 +1481,32 @@ The Monte Carlo method is a statistical method of calculating data whose formula
 
 To calculate the area of a circle with a radius of 1, pairs of random numbers between −1 and 1 are generated. These pairs represent the points in the square in the center of coordinates with sides of length 2. The area of the square is thus 4. If the distance between the random point and the center of the square is less than 1, then this point is located inside the circle of that radius. Counting the number of points that landed inside the circle and the number of points outside the circle gives the approximate value of the area of the circle, as soon as the area of the square is known. Here is the program.
 ::
-    load system io.
-    load system math.
-    load system random.
+  load system io.
+  load system math.
+  load system random.
+
+  let sqrt = math @sqrt.
+  let pow = math @pow.
+  let randint = random @randint.
 
-    seed(42).
+  random @seed(42).
 
-    let inside = 0.
-    let n = 10000.
-    for _ in 1 to n do
-        let point = (randint(-1.0,1.0),randint(-1.0,1.0)).
-        if sqrt(pow(point@0,2)+pow(point@1,2)) <= 1.0 do
-            let inside = inside+1.
-        end
-    end
-    let area = 4.0 * inside / n.
-    println area.
+  let inside = 0.
+  let n = 10000.
+  for _ in 1 to n do
+      let point = (randint(-1.0,1.0),randint(-1.0,1.0)).
+      if sqrt(pow(point@0,2)+pow(point@1,2)) <= 1.0 do
+          let inside = inside+1.
+      end
+  end
+  let area = 4.0 * inside / n.
+  io @println area.
+
+  assert (area == 3.1392).
 
-    assert (area == 3.1392).
 Output:
 ::
+
     3.1392
 
 
@@ -1325,39 +1518,44 @@ Challenge: Guess the number
 First, a random number needs to be generated. Then the program must
 ask for the initial guess and enter the loop, which compares the guess with the generated number.
 ::
-    load system io.
-    load system random.
-    load system util.
-
-    let n = randint(0,10).
-    let guess = tointeger(input("Guess my number between 0 and 10: ")).
-    while guess =/= n do
-        if guess < n do
-            println "Too small.".
-        elif guess > n  do
-            println "Too big.".
-        end
-        let guess = tointeger(input("Try again: ")).
-    end
-    println "Yes, this is it!".
+  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: ")).
+  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: ")).
+  end
+  io @println "Yes, this is it!".
 
 Challenge: Binary to integer
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 > Convert a binary number to a decimal integer.
 
-In Asteroid this is straightforward using the built-in `tointeger` function, passing it a string representation of the binary number and the base.
+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 util.
+  load system io.
+  load system type.
+
+  let bin = "101101".
+  let int = type @tointeger(bin,2).
+  io @println int.
 
-    let bin = "101101".
-    let int = tointeger(bin,2).
-    println int.
+  assert (int == 45).
 
-    assert (int == 45).
 Output:
 ::
+
     45
 
 
@@ -1366,23 +1564,28 @@ Challenge: Integer as binary, octal, and hex
 
 > Print a given integer number in the binary, octal, and hexadecimal representations.
 
-In Asteroid this is easily done with the `tobase` function.
+In Asteroid this is easily done with the ``tobase`` function.
 ::
-    load system io.
-    load system util.
+  load system io.
+  load system type.
+
+  let tobase = type @tobase.
+  let tointeger = type @tointeger.
 
-    let val = 42.
+  let val = 42.
 
-    println (tobase(val,2)).  -- bin
-    println (tobase(val,8)).  -- oct
-    println (tobase(val,16)). -- hex
+  io @println (tobase(val,2)).  -- bin
+  io @println (tobase(val,8)).  -- oct
+  io @println (tobase(val,16)). -- hex
+
+  -- make sure that conversions are correct in both directions
+  assert (tointeger(tobase(val,2),2) == val).
+  assert (tointeger(tobase(val,8),8) == val).
+  assert (tointeger(tobase(val,16),16) == val).
 
-    -- make sure that conversions are correct in both directions
-    assert (tointeger(tobase(val,2),2) == val).
-    assert (tointeger(tobase(val,8),8) == val).
-    assert (tointeger(tobase(val,16),16) == val).
 Output:
 ::
+
     101010
     52
     2A
@@ -1395,20 +1598,22 @@ Challenge: Sum of digits
 
 Pretty straightforward using string and list manipulation.
 ::
-    load system io.
-    load system util.
+  load system io.
+  load system type.
+
+  let number = 139487854.
 
-    let number = 139487854.
 
+  let s = type @tostring number @explode()
+                                @map(type @tointeger)
+                                @reduce(lambda with (x,y) do return x+y).
+  io @println s.
 
-    let s = tostring number @explode()
-                            @map(tointeger)
-                            @reduce(lambda with (x,y) do return x+y).
-    println s.
+  assert (s == 49).
 
-    assert (s == 49).
 Output:
 ::
+
     49
 
 
@@ -1417,36 +1622,40 @@ Challenge: Bit counter
 
 > Count the number of bits set to 1 in a binary representation of a positive integer number.
 
-If we remove all the zeros from a binary number, then we are left with only `1` characters which we can then count.
+If we remove all the zeros from a binary number, then we are left with only ``1`` characters which we can then count.
 ::
-    load system io.
+  load system io.
+
+  let bits = "1010101" @replace("0","")
+                       @length().
+  io @println bits.
 
-    let bits = "1010101" @replace("0","")
-                         @length().
-    println bits.
+  assert (bits == 4).
 
-    assert (bits == 4).
 Output:
 ::
+
     4
 
 
 Challenge: Compose the largest number
-^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 > Given the list of integers, compose the largest possible number by concatenating them.
 
 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 util.
+  load system io.
+  load system type.
 
-    let a = tointeger([67, 8, 1, 5, 45] @map(tostring) @sort(true) @join("")).
-    println a.
+  let a = type @tointeger([67, 8, 1, 5, 45] @map(type @tostring) @sort(true) @join("")).
+  io @println a.
+
+  assert (a == 8675451).
 
-    assert (a == 8675451).
 Output:
 ::
+
     8675451
 
 
@@ -1459,35 +1668,38 @@ Roman numbers are not a direct translation of the decimal system. In this task,
 
 Let’s use the algorithm that keeps the table of pre-calculated sequences of Roman letters. This is so that we don’t have to check when III becomes IV, or when another I appears after V, etc.
 
-In the program below, there are four such sequences: for thousands, hundreds, tens, and ones. The program iterates over the digits of the number in the decimal representation and chooses one of the values from the array of lists stored in the `roman_hash` table.
-::
-    load system io.
-    load system math.
-    load system util.
-    load system hash.
-
-    let roman_hash = HashTable().
-    roman_hash @insert(1000,["","M","MM","MMM"]).
-    roman_hash @insert(100,["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]).
-    roman_hash @insert(10,["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"]).
-    roman_hash @insert(1,["","I","II","III","IV","V","VI","VII","VIII","IX"]).
-
-    let n = 2018.
-    let p10 = range(tostring n @length()) @map(lambda with x do return pow(10,x))
-                                        @reverse().
-    let digits = tostring n @explode()
-                            @map(tointeger).
-    let z = zip(digits, p10).
-    println z.
-    let roman = "".
-    for (d,p) in z do
-        let roman = roman + roman_hash @get(p) @d.
-    end
-    println roman.
-
-    assert (roman == "MMXVIII")
+In the program below, there are four such sequences: for thousands, hundreds, tens, and ones. The program iterates over the digits of the number in the decimal representation and chooses one of the values from the array of lists stored in the ``roman_hash`` table.
+::
+  load system io.
+  load system math.
+  load system util.
+  load system hash.
+  load system type.
+
+  let roman_hash = hash @hash().
+  roman_hash @insert(1000,["","M","MM","MMM"]).
+  roman_hash @insert(100,["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]).
+  roman_hash @insert(10,["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"]).
+  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).
+  io @println z.
+  let roman = "".
+  for (d,p) in z do
+      let roman = roman + roman_hash @get(p) @d.
+  end
+  io @println roman.
+
+  assert (roman == "MMXVIII")
+
 Output:
 ::
+
     [(2,1000),(0,100),(1,10),(8,1)]
     MMXVIII
 
@@ -1511,49 +1723,49 @@ For the larger numbers (21 to 99), there are two cases. If the number is dividab
 
 The zero name appears only in the case when the given number is zero.
 ::
-    load system io.
-    load system math.
-
-    let names = ["zero","one","two","three","four","five","six","seven","eight","nine",
-                 "ten","eleven","twelve","thirteen","fourteen","fifteen",
-                 "sixteen","seventeen","eighteen","nineteen","twenty","thirty",
-                 "forty","fifty","sixty","seventy","eighty","ninety"].
-
-    function spell_number
-        with (n:%integer) if n < 20 do
-            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 "".
-            return r.
-        with (n:%integer) if n < 1000 do
-            return spell_part(n,100,"hundred").
-        with (n:%integer) if n < 1000000 do
-            return spell_part(n,1000,"thousand").
-        end
-
-    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.
-        end
-
-    println (spell_number 15).
-    println (spell_number 75).
-    println (spell_number 987654).
-    println (spell_number 1001).
+  load system io.
+  load system math.
+
+  let mod = math @mod.
+
+  let names = ["zero","one","two","three","four","five","six","seven","eight","nine",
+               "ten","eleven","twelve","thirteen","fourteen","fifteen",
+               "sixteen","seventeen","eighteen","nineteen","twenty","thirty",
+               "forty","fifty","sixty","seventy","eighty","ninety"].
+
+  function spell_number
+      with (n:%integer) if n < 20 do
+          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 "".
+          return r.
+      with (n:%integer) if n < 1000 do
+          return spell_part(n,100,"hundred").
+      with (n:%integer) if n < 1000000 do
+          return spell_part(n,1000,"thousand").
+      end
+
+  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.
+      end
+
+  io @println (spell_number 15).
+  io @println (spell_number 75).
+  io @println (spell_number 987654).
+  io @println (spell_number 1001).
+
 Output:
 ::
+
     fifteen
     seventy-five
     nine hundred eighty-seven thousand six hundred fifty-four
     one thousand one
 
 
-..
-  Chapter: Aggregate Data Types
-  -----------------------------
-
 Section: Manipulating Lists and Arrays
 --------------------------------------
 
@@ -1564,37 +1776,43 @@ Challenge: Swap two values
 
 In Asteroid, there is no need to use temporary variables to swap the values of two variables. Just use tuples on both sides of the equation:
 ::
+
     let (b,a) = (a,b).
 
 Consider the complete program:
 ::
-load system io.
+  load system io.
 
-    let (a,b) = (10,20).
-    let (b,a) = (a,b).
-    println ("a = "+a,"b = "+b).
+  let (a,b) = (10,20).
+  let (b,a) = (a,b).
+  io @println ("a = "+a,"b = "+b).
+
+  assert ((a,b) is (20,10)).
 
-    assert ((a,b) is (20,10)).
 Output:
 ::
+
     (a = 20,b = 10)
 
 
 This program prints the swapped values:
 ::
+
     (a = 20,b = 10)
 
 This approach also works with elements of an array:
 ::
-    load system io.
+  load system io.
+
+  let a = [3,5,7,4].
+  let (a@2,a@3) = (a@3,a@2).
+  io @println a.
 
-    let a = [3,5,7,4].
-    let (a@2,a@3) = (a@3,a@2).
-    println a.
+  assert (a is [3,5,4,7]).
 
-    assert (a is [3,5,4,7]).
 Output:
 ::
+
     [3,5,4,7]
 
 
@@ -1603,14 +1821,16 @@ Challenge: Reverse a list
 
 > Print the given list in reverse order.
 ::
-    load system io.
+  load system io.
 
-    let a = [10, 20, 30, 40, 50].
-    println (a @reverse()).
+  let a = [10, 20, 30, 40, 50].
+  io @println (a @reverse()).
+
+  assert(a == [50,40,30,20,10]).
 
-    assert(a == [50,40,30,20,10]).
 Output:
 ::
+
     [50,40,30,20,10]
 
 
@@ -1619,50 +1839,54 @@ Challenge: Rotate a list
 
 > Move all elements of an array N positions to the left or to the right.
 
-Asteroid does not have a built-in `rotate` function. However, such a function is easily constructed through slicing lists (see `vix` below).
+Asteroid does not have a built-in ``rotate`` function. However, such a function is easily constructed through slicing lists (see ``vix`` below).
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
+
+  function rotate with (l:%list,i:%integer) do
+      let n = l @length().
+      let vix = range n @map(lambda with x do return math @mod(x+i,n)).
+      return l @vix.
+  end
 
-    function rotate with (l:%list,i:%integer) do
-        let n = l @length().
-        let vix = range n @map(lambda with x do return mod(x+i,n)).
-        return l @vix.
-    end
 
+  let a = [1, 3, 5, 7, 9, 11, 13, 15].
+  let b = rotate(a,3).
+  let c = rotate(a,-3).
+  io @println a.
+  io @println b.
+  io @println c.
 
-    let a = [1, 3, 5, 7, 9, 11, 13, 15].
-    let b = rotate(a,3).
-    let c = rotate(a,-3).
-    println a.
-    println b.
-    println c.
+  assert(b == [7,9,11,13,15,1,3,5] and c == [11,13,15,1,3,5,7,9]).
 
-    assert(b == [7,9,11,13,15,1,3,5] and c == [11,13,15,1,3,5,7,9]).
 Output:
 ::
+
     [1,3,5,7,9,11,13,15]
     [7,9,11,13,15,1,3,5]
     [11,13,15,1,3,5,7,9]
 
 
-Challenge: Randomise an array
+Challenge: Randomize an array
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 > Shuffle the elements of an array in random order.
 
-This is easily accomplished with the built-in `shuffle`.
+This is easily accomplished with the built-in ``shuffle``.
 ::
-    load system io.
-    load system random.
+  load system io.
+  load system random.
+
+  random @seed(42).
+  let b = [1 to 20] @shuffle().
+  io @println b.
 
-    seed(42).
-    let b = [1 to 20] @shuffle().
-    println b.
+  assert(b == [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]).
 
-    assert(b == [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]).
 Output:
 ::
+
     [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]
 
 
@@ -1671,18 +1895,20 @@ Challenge: Incrementing array elements
 
 > Increment each element in an array.
 
-For this we use Asteroid's `vector` module, which can handle incrementing a vector with a scalar.
+For this we use Asteroid's ``vector`` module, which can handle incrementing a vector with a scalar.
 ::
-    load system io.
-    load system vector.
+  load system io.
+  load system vector.
+
+  let a = [1 to 10].
+  let b = vector @add(a,1).
+  io @println b.
 
-    let a = [1 to 10].
-    let b = vadd(a,1).
-    println b.
+  assert(b == [2,3,4,5,6,7,8,9,10,11]).
 
-    assert(b == [2,3,4,5,6,7,8,9,10,11]).
 Output:
 ::
+
     [2,3,4,5,6,7,8,9,10,11]
 
 
@@ -1691,54 +1917,60 @@ Challenge: Adding up two arrays
 
 > Take two arrays and create a new one whose elements are the sums of the corresponding items of the initial arrays.
 
-Again, here we take advantage of Asteroid's `vector` module.  Note that the two vectors have to be of the same length in order to add them together.
+Again, here we take advantage of Asteroid's ``vector`` module.  Note that the two vectors have to be of the same length in order to add them together.
 ::
-    load system io.
-    load system vector.
+  load system io.
+  load system vector.
 
-    let a = [10 to 20].
-    let b = [30 to 40].
-    let c = vadd(a,b).
-    println c.
+  let a = [10 to 20].
+  let b = [30 to 40].
+  let c = vector @add(a,b).
+  io @println c.
+
+  assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
 
-    assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
 Output:
 ::
+
     [40,42,44,46,48,50,52,54,56,58,60]
 
 
-The vector module defines a function called `vop` that allows you to combine two vectors using any arbitrary binary function.  Rewriting the above program using `vop`,
+The vector module defines a function called ``op`` that allows you to combine two vectors using any arbitrary binary function.  Rewriting the above program using ``op``,
 ::
-    load system io.
-    load system vector.
+  load system io.
+  load system vector.
 
-    let a = [10 to 20].
-    let b = [30 to 40].
-    let c = vop((lambda with (x,y) do return x+y),a,b).
-    println c.
+  let a = [10 to 20].
+  let b = [30 to 40].
+  let c = vector @op((lambda with (x,y) do return x+y),a,b).
+  io @println c.
+
+  assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
 
-    assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
 Output:
 ::
+
     [40,42,44,46,48,50,52,54,56,58,60]
 
 
-As I said above, any arbitrary binary function. Consider the relational operator `<` expressed as a lambda function,
+As we said above, any arbitrary binary function. Consider the relational operator ``<`` expressed as a lambda function,
 ::
-    load system io.
-    load system vector.
-    load system random.
+  load system io.
+  load system vector.
+  load system random.
+
+  random @seed(42).
 
-    seed(42).
+  let a = [1 to 10] @shuffle().
+  let b = [1 to 10] @shuffle().
+  let c = vector @op((lambda with (x,y) do return x<y),a,b).
+  io @println c.
 
-    let a = [1 to 10] @shuffle().
-    let b = [1 to 10] @shuffle().
-    let c = vop((lambda with (x,y) do return x<y),a,b).
-    println c.
+  assert(c == [false,true,false,false,false,true,false,false,true,true]).
 
-    assert(c == [false,true,false,false,false,true,false,false,true,true]).
 Output:
 ::
+
     [false,true,false,false,false,true,false,false,true,true]
 
 
@@ -1748,19 +1980,21 @@ Challenge: Exclusion of two arrays
 > From the given two arrays, find the elements of the first array which do not
 appear in the second one.
 
-Here we use Asteroid's `set` module.
+Here we use Asteroid's ``set`` module.
 ::
-    load system io.
-    load system set.
+  load system io.
+  load system set.
+
+  let a = [1 to 10].
+  let b = [5 to 15].
+  let c = set @diff(a,b).
+  io @println c.
 
-    let a = [1 to 10].
-    let b = [5 to 15].
-    let c = sdiff(a,b).
-    println c.
+  assert(c @sort() == [1,2,3,4]).
 
-    assert(c @sort() == [1,2,3,4]).
 Output:
 ::
+
     [2,3,1,4]
 
 
@@ -1772,30 +2006,34 @@ Challenge: Sum of the elements of an array
 
 > Find the sum of the elements of an array of integers.
 ::
-    load system io.
+  load system io.
+
+  let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
+  let s = a @reduce(lambda with (x,y) do return x+y).
+  io @println s.
 
-    let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
-    let s = a @reduce(lambda with (x,y) do return x+y).
-    println s.
+  assert (s == 125).
 
-    assert (s == 125).
 Output:
 ::
+
     125
 
 
 If summing up elements that are greater than 10,
 ::
-    load system io.
+  load system io.
 
-    let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
-    let f = (lambda with (x,y) do return x+(y if y > 10 else 0)).
-    let s = a @reduce(f,0).
-    println s.
+  let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
+  let f = (lambda with (x,y) do return x+(y if y > 10 else 0)).
+  let s = a @reduce(f,0).
+  io @println s.
+
+  assert (s == 92).
 
-    assert (s == 92).
 Output:
 ::
+
     92
 
 
@@ -1804,121 +2042,53 @@ Challenge: Average of an array
 
 > Find the average value of the given array of numbers.
 ::
-    load system io.
+  load system io.
 
-    let a = [7, 11, 34, 50, 200].
-    let avg = a @reduce(lambda with (x,y) do return x+y)/a @length().
-    println avg.
+  let a = [7, 11, 34, 50, 200].
+  let avg = a @reduce(lambda with (x,y) do return x+y)/a @length().
+  io @println avg.
 
-    assert (avg == 60).
-Output:
-::
-    60
-
-
-Challenge: Moving average
-^^^^^^^^^^^^^^^^^^^^^^^^^
+  assert (avg == 60).
 
-> Calculate the moving average for the given array of numbers.
-
-Compute the moving average over 100 random values, using a window of size 7 (3 values below, 3 values above, and the current values).
+Output:
 ::
-    load system io.
-    load system random.
-
-    seed(42).
-
-    -- Asteroid allows the user to escape to the Python
-    -- ecosystem.  Here we use this to construct a
-    -- plot of the moving average
-    function plot with (dt,avg) do escape
-    "
-    import pandas as pd
-    import matplotlib.pyplot as plt
-    plt.style.use('seaborn')
-
-    # import parameters from Asteroid into Python
-    dt_val = state.symbol_table.lookup_sym('dt')
-    avg_val = state.symbol_table.lookup_sym('avg')
-
-    # convert from Asteroid lists to Python lists
-    dt_plot = []
-    for (_,v) in dt_val[1]:
-        dt_plot.append(v)
-
-    avg_plot = []
-    for (_,v) in avg_val[1]:
-        avg_plot.append(v)
-
-    # construct a dataframe to plot
-    df = pd.DataFrame(data={'Data':dt_plot,'Average':avg_plot})
-
-    # colors for the line plot
-    colors = ['steelblue', 'red']
-
-    # line plot
-    df.plot(color=colors, linewidth=3, figsize=(12,6))
-
-    # modify ticks size
-    plt.xticks(fontsize=14)
-    plt.yticks(fontsize=14)
-    plt.legend(labels =['Data', 'Moving Average'], fontsize=14)
-
-    # title and labels
-    plt.title('Moving Average', fontsize=20)
-    plt.xlabel('Instance', fontsize=16)
-    plt.ylabel('Value', fontsize=16)
-    plt.show()
-    "
-    end
-
-    -- compute the window on lst
-    function window with (lst:%list,i:%integer) if i >= 3 and i <= lst @length()-4 do
-        return lst @[i-3,i-2,i-1,i,i+1,i+2,i+3].
-    end
-
-    -- sum the values of lst
-    function sum with lst:%list do
-        return lst @reduce(lambda with (x,y) do return x+y).
-    end
-
-    let dt = [1 to 100] @map(lambda with _ do return random()).
-    let mavg = [3 to 96] @map(lambda with i do return sum(window(dt,i))/7).
-
-    plot(dt @[3 to 96],mavg).
 
+    60
 
-.. image:: moving-avg.png
 
 Challenge: Is an element in a list?
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 > Tell if the given value is in the list.
 ::
-    load system io.
+  load system io.
+
+  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")).
 
-    let array = [10, 14, 0, 15, 17, 20, 30, 35].
-    let x = 17.
-    println ((x+" is in the list") if array @member(x) else (x+" is not in the list")).
 Output:
 ::
+
     17 is in the list
 
 
 We can also use a reduction function to solve this,
 ::
-    load system io.
+  load system io.
 
-    let array = [10, 14, 0, 15, 17, 20, 30, 35].
-    let x = 17.
+  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").
+  else
+      io @println (x+" is not in the list").
+  end
 
-    if array @reduce(lambda with (acc,i) do return true if i==x else acc,false) do
-        println (x+" is in the list").
-    else
-        println (x+" is not in the list").
-    end
 Output:
 ::
+
     17 is in the list
 
 
@@ -1929,14 +2099,20 @@ Challenge: First odd number
 
 The easiest way to do this is with a reduction,
 ::
-    load system io.
-    load system math.
+  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).
+  io @println odd.
 
-    let array = [2, 4, 18, 9, 16, 7, 10].
-    let odd = array @reduce(lambda with (acc,i) do return i if isnone(acc) and mod(i,2) else acc,none).
-    println odd.
 Output:
 ::
+
     9
 
 
@@ -1945,30 +2121,34 @@ Challenge: Take every second element
 
 > Form a new array by picking every second element from the original array.
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    let array = [20 to 30] @filter(lambda with x do return mod(x,2)).
-    println array.
+  let array = [20 to 30] @filter(lambda with x do return math @mod(x,2)).
+  io @println array.
+
+  assert (array == [21,23,25,27,29]).
 
-    assert (array == [21,23,25,27,29]).
 Output:
 ::
+
     [21,23,25,27,29]
 
 
 We can use an index vector to accomplish  the same thing,
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
 
-    let a = [20 to 30].
-    let array = a @[1 to a @length()-1 step 2] .
-    println array.
+  let a = [20 to 30].
+  let array = a @[1 to a @length()-1 stride 2] .
+  io @println array.
+
+  assert (array == [21,23,25,27,29]).
 
-    assert (array == [21,23,25,27,29]).
 Output:
 ::
+
     [21,23,25,27,29]
 
 
@@ -1977,16 +2157,28 @@ Challenge: Number of occurrences in an array
 
 > Count how many times a particular element appears in the array.
 ::
-    load system io.
-    load system math.
+  load system io.
+  load system math.
+
+  let dt = ["apple",
+            "pear",
+            "grape",
+            "lemon",
+            "peach",
+            "apple",
+            "banana",
+            "grape",
+            "pineapple",
+            "avocado"].
+            
+  let cnt = dt @count("grape").
+  io @println cnt.
 
-    let dt = ["apple","pear","grape","lemon","peach","apple","banana","grape","pineapple","avocado"].
-    let cnt = dt @count("grape").
-    println cnt.
+  assert (cnt == 2).
 
-    assert (cnt == 2).
 Output:
 ::
+
     2
 
 
@@ -1997,20 +2189,22 @@ Challenge: Finding unique elements
 
 Converting a list to a set will remove all duplicate elements in the list.
 ::
-    load system io.
-    load system set.
+  load system io.
+  load system set.
+
+  function unique with lst:%list do
+      return set @toset lst @sort().
+  end
 
-    function unique with lst:%list do
-        return toset lst @sort().
-    end
+  let a = unique([2, 3, 7, 4, 5, 5, 6, 2, 10, 7]).
 
-    let a = unique([2, 3, 7, 4, 5, 5, 6, 2, 10, 7]).
+  io @println a.
 
-    println a.
+  assert (a == [2,3,4,5,6,7,10])
 
-    assert (a == [2,3,4,5,6,7,10])
 Output:
 ::
+
     [2,3,4,5,6,7,10]
 
 
@@ -2019,26 +2213,29 @@ Challenge: Minimum and maximum
 
 > Find the minimum and the maximum numbers in the given list of integers.
 ::
-    load system io.
+  load system io.
 
-    function max with lst:%list do
-        return lst @sort(true) @0.
-    end
+  function max with lst:%list do
+      return lst @sort(true) @0.
+  end
 
-    function min with lst:%list do
-        return lst @sort() @0.
-    end
+  function min with lst:%list do
+      return lst @sort() @0.
+  end
 
-    let a = max [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
-    let b = min [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
+  let v = [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
+  
+  let a = max v.
+  let b = min v.
 
+  io @println a.
+  io @println b.
 
-    println a.
-    println b.
+  assert (a == 15 and b == 2).
 
-    assert (a == 15 and b == 2).
 Output:
 ::
+
     15
     2
 
@@ -2048,17 +2245,19 @@ Challenge: Increasing sequences
 
 > Check if the given array contains increasing (or decreasing) numbers.
 ::
-    load system io.
-    load system util.
+  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 a = [3, 7, 19, 20, 34].
-    let b = toboolean(a @reduce(lambda with (x,y) do return y if x<y else false)).
+  io @println b.
 
-    println b.
+  assert (b).
 
-    assert (b).
 Output:
 ::
+
     true
 
 Section: Multi-Dimensional Data
@@ -2071,87 +2270,94 @@ Challenge: Transpose a matrix
 
 In Asteroid a matrix can be represented by nested lists, like so,
 ::
+
     let m = [[1,2],
              [3,4]].
 
 The transpose of this matrix is,
 ::
+
     let m = [[1,3],
              [2,4]].
 
 In a square matrix computing the transpose is just a matter of swapping around the elements.  However, here we will solve the more general problem for non-square matrices,
 ::
+
     let m = [[1,2],
              [3,4],
              [5,6]].
 
 with its transpose,
 ::
+
     let m = [[1,3,5],
              [2,4,6]].
+
 The procedure:
 ::
-    load system io.
-
-    function transpose with m do
-        -- figure out the dimensions
-        let xdim = m @0 @length().
-        let ydim = m @length().
-
-        -- reserve space for the transpose
-        -- first we do the ydim of new matrix
-        let mt = range(xdim).
-        for y in mt do
-            let mt @y = range(ydim).
-        end
-
-        -- swap the elements
-        for x in range(xdim) do
-            for y in range(ydim) do
-                let mt @x @y = m @y @x.
-            end
-        end
-
-        return mt.
-    end
-
-    function print_matrix with m do
-        println "".
-        for r in m do
-            for e in r do
-                print (e + " ").
-            end
-            println ("").
-        end
-        println "".
-    end
+  load system io.
 
-    let m = [[1,2],
-             [3,4]].
+  function transpose with m do
+      -- figure out the dimensions
+      let xdim = m @0 @length().
+      let ydim = m @length().
 
-    let mt = transpose(m).
+      -- reserve space for the transpose
+      -- first we do the ydim of new matrix
+      let mt = range(xdim).
+      for y in mt do
+          let mt @y = range(ydim).
+      end
 
-    println ("The transpose of:").
-    print_matrix m.
-    println ("is:").
-    print_matrix mt.
-    println ("").
+      -- swap the elements
+      for x in range(xdim) do
+          for y in range(ydim) do
+              let mt @x @y = m @y @x.
+          end
+      end
 
-    let m = [[1,2],
-             [3,4],
-             [5,6]].
+      return mt.
+  end
+
+  function print_matrix with m do
+      io @println "".
+      for r in m do
+          for e in r do
+              io @print (e + " ").
+          end
+          io @println ("").
+      end
+      io @println "".
+  end
+
+  let m = [[1,2],
+           [3,4]].
 
-    let mt = transpose(m).
+  let mt = transpose(m).
 
-    println ("The transpose of:").
-    print_matrix m.
-    println ("is:").
-    print_matrix mt.
-    println ("").
+  io @println ("The transpose of:").
+  print_matrix m.
+  io @println ("is:").
+  print_matrix mt.
+  io @println ("").
+
+  let m = [[1,2],
+           [3,4],
+           [5,6]].
+
+  let mt = transpose(m).
+
+  io @println ("The transpose of:").
+  print_matrix m.
+  io @println ("is:").
+  print_matrix mt.
+  io @println ("").
+
+  assert(mt == [[1,3,5],[2,4,6]]).
 
-    assert(mt == [[1,3,5],[2,4,6]]).
 Output:
 ::
+
     The transpose of:
 
     1 2
@@ -2175,8 +2381,6 @@ Output:
     2 4 6
 
 
-
-
 Challenge: Sort hashes by parameter
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
@@ -2184,36 +2388,40 @@ Challenge: Sort hashes by parameter
 
 This task is commonly performed to sort items where the sortable parameter is one of the values in the hash. For example, sorting a list of people by age.
 ::
-    load system io.
-    load system hash.
-    load system sort.
-    load system random.
+  load system io.
+  load system hash.
+  load system sort.
+  load system random.
+
+  let randint = random @randint.
 
-    seed(42).
+  random @seed(42).
 
-    -- hash of names with ages
-    let ht = HashTable().
-    ht @insert("Billie",randint(20,50)).
-    ht @insert("Joe",randint(20,50)).
-    ht @insert("Pete",randint(20,50)).
-    ht @insert("Brandi",randint(20,50)).
+  -- hash of names with ages
+  let ht = hash @hash().
+  ht @insert("Billie",randint(20,50)).
+  ht @insert("Joe",randint(20,50)).
+  ht @insert("Pete",randint(20,50)).
+  ht @insert("Brandi",randint(20,50)).
 
-    -- export the hash as a list of pairs
-    let lst = ht @aslist().
+  -- export the hash as a list of pairs
+  let lst = ht @aslist().
 
-    -- define our order predicate on a
-    -- list of pairs where the second
-    -- component holds the order info
-    function pairs with ((_,x),(_,y)) do
-        return true if x < y else false.
-    end
+  -- define our order predicate on a
+  -- list of pairs where the second
+  -- component holds the order info
+  function pairs with ((_,x),(_,y)) do
+      return true if x < y else false.
+  end
 
-    -- print out the sorted list
-    println (sort(pairs,lst)).
+  -- print out the sorted list
+  io @println (sort @sort(pairs,lst)).
+
+  assert (sort @sort(pairs,lst) == [("Pete",20),("Joe",23),("Billie",40),("Brandi",43)])
 
-    assert (sort(pairs,lst) == [("Pete",20),("Joe",23),("Billie",40),("Brandi",43)])
 Output:
 ::
+
     [(Pete,20),(Joe,23),(Billie,40),(Brandi,43)]
 
 
@@ -2224,41 +2432,43 @@ Challenge: Count hash values
 
 For example, a hash is a collection mapping a car’s license plate to the colour of the car or a passport number to the name of the street where the person lives. In the first example, the task is to count how many cars of each colour there are. In the second example, we have to say how many people live on each street. But let’s simply count the colours of fruit.
 ::
-    load system io.
-    load system hash.
-    load system sort.
-
-    let fruit_hash = HashTable().
-    fruit_hash @insert("apple","red").
-    fruit_hash @insert("avocado","green").
-    fruit_hash @insert("banana","yellow").
-    fruit_hash @insert("grapefruit","orange").
-    fruit_hash @insert("grapes","green").
-    fruit_hash @insert("kiwi","green").
-    fruit_hash @insert("lemon","yellow").
-    fruit_hash @insert("orange","orange").
-    fruit_hash @insert("pear","green").
-    fruit_hash @insert("plum","purple").
-
-    let fruit_lst = fruit_hash @aslist().
-
-    let color_hash = HashTable().
-    for (_,color) in fruit_lst do
-        if not color_hash @get(color) do
-            color_hash @insert(color,1).
-        else
-            color_hash @insert(color, color_hash @get(color) +1).
-        end
-    end
-    let color_lst = color_hash @aslist().
-
-    function pairs with ((_,x),(_,y)) do
-        return true if x < y else false.
-    end
-
-    println (sort(pairs,color_lst)).
+  load system io.
+  load system hash.
+  load system sort.
+
+  let fruit_hash = hash @hash().
+  fruit_hash @insert("apple","red").
+  fruit_hash @insert("avocado","green").
+  fruit_hash @insert("banana","yellow").
+  fruit_hash @insert("grapefruit","orange").
+  fruit_hash @insert("grapes","green").
+  fruit_hash @insert("kiwi","green").
+  fruit_hash @insert("lemon","yellow").
+  fruit_hash @insert("orange","orange").
+  fruit_hash @insert("pear","green").
+  fruit_hash @insert("plum","purple").
+
+  let fruit_lst = fruit_hash @aslist().
+
+  let color_hash = hash @hash().
+  for (_,color) in fruit_lst do
+      if not color_hash @get(color) do
+          color_hash @insert(color,1).
+      else
+          color_hash @insert(color, color_hash @get(color) +1).
+      end
+  end
+  let color_lst = color_hash @aslist().
+
+  function pairs with ((_,x),(_,y)) do
+      return true if x < y else false.
+  end
+
+  io @println (sort @sort(pairs,color_lst)).
+
 Output:
 ::
+
     [(red,1),(purple,1),(yellow,2),(orange,2),(green,4)]
 
 
@@ -2267,22 +2477,24 @@ Challenge: Product table
 
 > Generate and print the product table for the values from 1 to 10.
 
-We will do this with an outer loop  and a `map` function.
+We will do this with an outer loop  and a ``map`` function.
 ::
-    load system io.
-    load system util.
+  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.
+  end
 
-    function format with v do
-        let maxlen = 3.
-        let vstr = tostring v.
-        return [1 to maxlen-len(vstr)] @map(lambda with _ do return " ") @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(" ")).
+  end
 
-    for i in 1 to 10 do
-        println ([1 to 10] @map(lambda with x do return format(i*x)) @join(" ")).
-    end
 Output:
 ::
+
       1   2   3   4   5   6   7   8   9  10
       2   4   6   8  10  12  14  16  18  20
       3   6   9  12  15  18  21  24  27  30
@@ -2302,6 +2514,7 @@ Challenge: Pascal triangle
 
 The Pascal triangle is a sequence of rows of integers. It starts with a single 1 on the top row, and each following row has one number more, starting and ending with 1, while all of the other items are the sums of the two elements above it in the previous row. It is quite obvious from the illustration:
 ::
+
            1
           1 1
          1 2 1
@@ -2313,51 +2526,58 @@ The Pascal triangle is a sequence of rows of integers. It starts with a single 1
 To calculate the values of the next row, you may want to iterate over the values of the current row and make the sums with the numbers next to it. Let us use the functional style that the language offers.
 Consider the fourth row, for example: 1 3 3 1. To make the fifth row, you can shift all the values by one position to the right and add them up to the current row:
 ::
+
       13310
     + 01331
     -------
     14641
 
-We can easily accomplish this with our `vector` module. Given the vector of the fourth row,
+We can easily accomplish this with our ``vector`` module. Given the vector of the fourth row,
 ::
+
     [1,3,3,1]
 
 we create two new vectors,
 ::
+
     [1,3,3,1,0]
 
 and
 ::
+
     [0,1,3,3,1]
 
 We then add them together,
 ::
-    vadd([1,3,3,1,0],[0,1,3,3,1]) = [1,4,6,4,1]
+
+    vector @add([1,3,3,1,0],[0,1,3,3,1]) = [1,4,6,4,1]
 
 The only thing that is left to do is to iterate appropiately and format the output.
 ::
-    load system io.
-    load system vector.
-    load system util.
+  load system io.
+  load system vector.
+  load system util.
+  load system type.
 
-    let triangle = [[1]].
-    let ix = 0.
+  let triangle = [[1]].
+  let ix = 0.
 
-    for i in 1 to 6 do
-        let v = triangle @ix.
-        let v1 = [0] + v.
-        let v2 = v + [0].
-        let new_v = vadd(v1,v2).
-        let triangle = triangle + [new_v].
-        let ix = ix + 1.
-    end
+  for i in 1 to 6 do
+      let v = triangle @ix.
+      let v1 = [0] + v.
+      let v2 = v + [0].
+      let new_v = vector @add(v1,v2).
+      let triangle = triangle + [new_v].
+      let ix = ix + 1.
+  end
 
-    for r in triangle do
-        println (r @map(lambda with v do return tostring v) @join(" ")).
-    end
+  for r in triangle do
+      io @println (r @map(lambda with v do return type @tostring v) @join(" ")).
+  end
 
 Output:
 ::
+
     1
     1 1
     1 2 1
diff --git a/docs/Asteroid in Action.txt b/docs/Asteroid in Action.txt
new file mode 100644
index 00000000..10f419db
--- /dev/null
+++ b/docs/Asteroid in Action.txt
@@ -0,0 +1,1361 @@
+/******************************************************************
+  This is the source file from which the action doc is generated.
+  We use cpp to insert live code snippets into the document.
+  In order to generate the action doc run the following command
+  on a Unix-like system:
+
+  cpp -w -P "Asteroid in Action.txt" > "Asteroid in Action.rst"
+
+ ******************************************************************/
+#include "header.txt"
+
+.. highlight:: none
+
+Asteroid in Action
+==================
+
+This document was inspired by Andrew Shitov's excellent book `Using Raku: 100 Programming Challenges Solved with the Brand-New Raku Programming Language <https://andrewshitov.com/wp-content/uploads/2020/01/Using-Raku.pdf>`_.  Here we use Asteroid to solve these programming challenges.
+
+Section: Using Strings
+----------------------
+
+Challenge: Hello, World!
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print ‘Hello, World!’
+
+The canonical ``Hello, World!`` program.  The easiest way to write this in Asteroid is,
+::
+#include "../asteroid/test-suites/action-tests/test001.ast"
+
+Output::
+
+    Hello, World!
+
+
+
+Challenge: Greet a person
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Ask a user for their name and greet them by printing ‘Hello, <Name\>!’
+
+Here is our first solution using a separate function for each of the steps,
+::
+#include "../asteroid/test-suites/action-tests/test003.ast"
+
+
+Letting the function ``input`` do the prompting,
+::
+#include "../asteroid/test-suites/action-tests/test004.ast"
+
+Doing everything in one step,
+::
+#include "../asteroid/test-suites/action-tests/test005.ast"
+
+Challenge: String length
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the length of a string.
+
+In order to print the length of a string we can use the function ``len`` available in the ``util`` module,
+::
+#include "../asteroid/test-suites/action-tests/test006.ast"
+
+Output::
+
+    6
+
+
+We can also use the string member function ``length`` in order to compute the length of the string,
+::
+#include "../asteroid/test-suites/action-tests/test007.ast"
+
+Output::
+
+    6
+
+
+Challenge: Unique digits
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print unique digits from a given integer number.
+
+In order to accomplish this we take advantage of the string ``explode`` function and the ``sort`` function on lists.
+Finally we use the ``reduce`` function to map a list with repeated digits to a list with unique digits,
+::
+#include "../asteroid/test-suites/action-tests/test008.ast"
+
+Output::
+
+    [1,2,3]
+
+
+Probably the most noteworthy characteric about this program is the ``reduce`` function.  The ``reduce`` function applies a binary function to a list.  The first argument of the binary function acts like an accumulator, and the second argument gets instantiated with the elements of the list to be processed.  In our function ``unique``, the variable ``x`` is the accumulator with an initial value of ``[]``.  The function tests whether the element ``y`` is in the list.  If it is not, then it adds it to the list. Otherwise, it just returns the accumulator unchanged.
+
+Section: Modifying String Data
+------------------------------
+
+Challenge: Reverse a string
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print a string in the reversed order from right to left.
+
+We use the ``explode`` function to turn a string into a list of characters. Then, we reverse the list and turn it back into a string using the ``join`` function,
+::
+#include "../asteroid/test-suites/action-tests/test009.ast"
+
+Output::
+
+    !dlroW ,olleH
+
+
+Challenge: Removing blanks from a string
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Remove leading, trailing, and double spaces from a given string.
+::
+#include "../asteroid/test-suites/action-tests/test010.ast"
+
+Output::
+
+    Hello, World!
+
+
+Challenge: Camel case
+^^^^^^^^^^^^^^^^^^^^^
+
+> Create a camel-case identifier from a given phrase.
+
+In this task, we will form the ``CamelCase`` variable for names from a given phrase.
+Names created in this style are built of several words, each of which starts
+with a capital letter.
+::
+#include "../asteroid/test-suites/action-tests/test011.ast"
+
+Output::
+
+    OnceUponATime
+
+
+Challenge: Incrementing filenames
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Generate a list of filenames like file1.txt, file2.txt, etc.
+::
+#include "../asteroid/test-suites/action-tests/test012.ast"
+
+Output::
+
+    file1.txt
+    file2.txt
+    file3.txt
+    file4.txt
+    file5.txt
+
+
+Challenge: Random passwords
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Generate a random string that can be used as a password.
+
+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.
+::
+#include "../asteroid/test-suites/action-tests/test013.ast"
+
+Output::
+
+    e3zvshdbS43brt#
+
+
+Challenge: DNA-to-RNA transcription
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Convert the given DNA sequence to a compliment RNA.
+
+We’ll not dig deep into the biology aspect of the problem. For us, it is important that the DNA is a string containing the four letters A, C, G, and T,
+and the RNA is a string of A, C, G, and U. The transformation from DNA
+to RNA happens according to the following table:
+::
+
+    DNA: A C G T
+    RNA: U G C A
+
+We will solve this programming problem using Asteroid's first-class patterns. We could have solved this with just testing equality on DNA characters. However, using first-class patterns is more general and can be applied to problems with a more structured mapping relationship.
+::
+#include "../asteroid/test-suites/action-tests/test014.ast"
+
+Output::
+
+    UGGUAGUCAG
+
+
+Challenge: Caesar cipher
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Encode a message using the Caesar cipher technique.
+
+The Caesar code is a simple method of transcoding the letters of the message
+so that each letter is replaced with the letter that occurs in the alphabet N
+positions earlier or later.
+For example, if N is 4, then the letter e becomes a, f is transformed to b,
+etc. The alphabet is looped so that z becomes v, and letters a to d become
+w to z.
+::
+#include "../asteroid/test-suites/action-tests/test015.ast"
+
+Output::
+
+    dahhk, sknhz!
+    hello, world!
+
+
+Section: Text Analysis
+----------------------
+
+Challenge: Plural endings
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Put a noun in the correct form — singular or plural — depending on the number next to it.
+
+In program outputs, it is often required to print some number followed by a noun, for example::
+
+    10 files found
+
+If there is only one file, then the phrase should be ``1 file found`` instead.
+::
+#include "../asteroid/test-suites/action-tests/test016.ast"
+
+Output::
+
+    0 files found
+    1 file found
+    2 files found
+    3 files found
+    4 files found
+    5 files found
+
+
+Challenge: The most frequent word
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the most frequent word in the given text.
+
+In our solution we use a hash table to count the number of word occurences.
+::
+#include "../asteroid/test-suites/action-tests/test017.ast"
+
+Output::
+
+    sed
+
+
+Challenge: The longest common substring
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the longest common substring in the given two strings.
+
+Let us limit ourselves with finding only the first longest substring. If there
+are more common substrings of the same length, then the rest are ignored.
+There are two loops (see also Task 17, The longest palindrome) over the first
+string (``stra``). These use the index method to search for the substring in the
+second string (``strb``).
+::
+#include "../asteroid/test-suites/action-tests/test018.ast"
+
+Output::
+
+    The longest common substring is ' fox '.
+
+
+Challenge: Anagram test
+^^^^^^^^^^^^^^^^^^^^^^^
+
+> Tell if the two words are anagrams of each other.
+
+An anagram is a word, phrase, or name formed by rearranging the letters of another, such as ``cinema``, formed from ``iceman``.
+::
+#include "../asteroid/test-suites/action-tests/test019.ast"
+
+Output::
+
+    Anagrams
+
+
+Challenge: Palindrome test
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Check if the entered string is palindromic.
+
+A palindrome is a string that can be read from both ends: left to right or right
+to left.
+::
+#include "../asteroid/test-suites/action-tests/test020.ast"
+
+Output::
+
+    Palindromic
+
+
+Challenge: The longest palindrome
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the longest palindromic substring in the given string.
+
+The main idea behind the solution is to scan the string with a window of
+varying width. In other words, starting from a given character, test all the
+substrings of any length possible at that position.
+Now, extract the substring and do the check similar to the solution of Task
+16, Palindrome test. Here, we have to be careful to check the palindrome
+without taking into account the non-letter characters, but saving the result as
+part of the original string.
+::
+#include "../asteroid/test-suites/action-tests/test021.ast"
+
+Output::
+
+    o, Wo
+
+
+Challenge: Finding duplicate texts
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find duplicate fragments in the same text.
+
+We do this by finding and hashing N-grams after the appropriate preprocessing.  We will use ``N=3``.
+::
+#include "../asteroid/test-suites/action-tests/test022.ast"
+
+Output::
+
+    lorem ipsum dolor: 2
+    ipsum dolor sit: 2
+    dolor sit amet: 3
+    sit amet consectetur: 2
+    amet consectetur adipiscing: 2
+    consectetur adipiscing elit: 2
+    in hac habitasse: 2
+    hac habitasse platea: 2
+    habitasse platea dictumst: 2
+    aliquet quam purus: 2
+    diam sed nulla: 2
+    sit amet condimentum: 2
+
+
+
+Section: Using Numbers
+----------------------
+
+Challenge: Pi
+^^^^^^^^^^^^^
+
+> Print the value of pi.
+::
+#include "../asteroid/test-suites/action-tests/test023.ast"
+
+Output::
+
+    3.141592653589793
+
+Other constants are also available.
+::
+#include "../asteroid/test-suites/action-tests/test024.ast"
+
+Output::
+
+    2.718281828459045
+    6.283185307179586
+
+
+Challenge: Factorial!
+^^^^^^^^^^^^^^^^^^^^^
+
+> Print the factorial of a given number.
+
+By definition, the factorial of a positive integer number N is a product of all the integers numbering from 1 to N, including N. Our first solution is based on the direct implementation of the definition above using the list ``reduce`` function.
+::
+#include "../asteroid/test-suites/action-tests/test025.ast"
+
+Output::
+
+    6
+
+
+Our second solution uses the recursive definition of factorial,
+::
+
+         | 1       if  x = 0,
+    x! = | x(x-1)! if  x > 0,
+         | undef   if  x < 0,
+
+where :math:`x \in Int`.
+Here, each case specifies what value the function should return if
+the predicate applied to the input is true.  The last case is of some interest because it states that the function is undefined for negative integers.
+::
+#include "../asteroid/test-suites/action-tests/test026.ast"
+
+Output::
+
+    The factorial of 3 is: 6
+
+
+Challenge: Fibonacci numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the Nth Fibonacci number.
+
+Fibonacci numbers are defined by the recurring formula:
+::
+
+    f_n = f_{n-1} + f_{n-2}
+
+You can assign two values at a time (**Challenge: Swap two values**). You can use that technique for calculating the next Fibonacci number from the previous two. To bootstrap the algorithm, the two first values are needed. In one of the definitions of the Fibonacci row, the first two values are both 1.
+
+Here we give an iterative solutions.  It is clear that there exists a trivial recursive solution by implementing the above formula.
+::
+#include "../asteroid/test-suites/action-tests/test027.ast"
+
+Output::
+
+    55
+
+
+Challenge: Print squares
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the squares of the numbers 1 through 10.
+
+Of course this is straightforward, with a ``for-loop`` over a list.  Here we show another solution using the list ``map`` function.
+::
+#include "../asteroid/test-suites/action-tests/test028.ast"
+
+Output::
+
+    [1,4,9,16,25,36,49,64,81,100]
+
+
+Challenge: Powers of two
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the first ten powers of two.
+
+Just as in the previous challenge, we skip the naive loop solution and give a solution using the ``map`` function.
+::
+#include "../asteroid/test-suites/action-tests/test029.ast"
+
+Output::
+
+    [1,2,4,8,16,32,64,128,256,512]
+
+
+Challenge: Odd and even numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the first ten odd numbers. Print the first ten even numbers.
+
+We start with printing the first ten odd numbers,
+::
+#include "../asteroid/test-suites/action-tests/test030.ast"
+
+Output::
+
+    [1,3,5,7,9]
+
+
+Now the even numbers,
+::
+#include "../asteroid/test-suites/action-tests/test031.ast"
+
+Output:
+::
+
+    [2,4,6,8,10]
+
+
+Challenge: Compare numbers approximately
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Compare the two non-integer values approximately.
+
+Comparing non-integer numbers (which are represented as floating-point numbers) is often a task that requires approximate comparison.  In Asteroid this can be accomplished with the ``isclose`` function availabel in the ``math`` module.
+::
+#include "../asteroid/test-suites/action-tests/test032.ast"
+
+
+Challenge: Prime numbers
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Decide if the given number is a prime number.
+
+Prime numbers are those that can be divided only by 1, and by themselves.
+::
+#include "../asteroid/test-suites/action-tests/test033.ast"
+
+Output:
+::
+
+    true
+    false
+
+
+Challenge: List of prime numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the list of the first ten prime numbers.
+::
+#include "../asteroid/test-suites/action-tests/test034.ast"
+
+Output:
+::
+
+    2
+    3
+    5
+    7
+    11
+    13
+    17
+    19
+    23
+    29
+
+
+Challenge: Prime factors
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the prime factors of a given number.
+
+Prime factors are the prime numbers that divide the given integer number exactly.
+::
+#include "../asteroid/test-suites/action-tests/test035.ast"
+
+Output:
+::
+
+    [3,5,11]
+
+
+Challenge: Reducing a fraction
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Compose a fraction from the two given integers — numerator and denominator — and reduce it to lowest terms.
+
+5/15 and 16/280 are examples of fractions that can be reduced. The final results of this task are 1/3 and 2/35. Generally, the algorithm of reducing a fraction requires searching for the greatest common divisor, and then dividing both numerator and denominator by that number.  For our solution we use the function ``gcd`` available in the ``math`` module.
+::
+#include "../asteroid/test-suites/action-tests/test036.ast"
+
+Output:
+::
+
+    2
+    35
+
+
+Challenge: Divide by zero
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Do something with the division by zero.
+
+Asteroid is an eager language, that is, expressions are evaluated as early as possible.  We can trap division-by-zero errors using a try-catch block.
+::
+#include "../asteroid/test-suites/action-tests/test037.ast"
+
+Output:
+::
+
+    integer division or modulo by zero
+    We are still alive...
+
+
+Section: Random Numbers
+-----------------------
+
+Challenge: Generating random numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Generate a random number between 0 and N.
+
+Asteroid has two random number generation functions: ``random()`` generates a random real value in the interval $[0.0,1.0)$ and ``randint(a,b)`` that generates a random value in the interval $[a,b]$.  The type of the random value generated depends on the type of the values a and b specifying the interval.
+::
+#include "../asteroid/test-suites/action-tests/test038.ast"
+
+Output:
+::
+
+    0.6394267984578837
+    0.025010755222666936
+    1
+    2.4489185380347624
+    2
+
+
+Challenge: Neumann’s random generator
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Implement Von Neumann’s random number generator (also known as Middle-square method).
+
+This algorithm is a simple method of generating short sequences of four-digit random integers. The method has its drawbacks, but for us, it is an interesting algorithmic task. The recipe has these steps:
+
+1. Take a number between 0 and 9999.
+2. Calculate the square of it.
+3. If necessary, add leading zeros to make the number 8-digit.
+4. Take the middle four digits.
+5. Repeat from step 2.
+
+To illustrate it with an example, let’s take the number 1234 as the seed. On step 2, it becomes 1522756; after step 3, 01522756. Finally, step 4 extracts the number 5227.
+::
+#include "../asteroid/test-suites/action-tests/test039.ast"
+
+Output:
+::
+
+    5227
+
+
+Challenge: Histogram of random numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Test the quality of the random generator by using a histogram to visualise the distribution.
+
+The quality of the built-in generator of random numbers fully depends on the algorithm the developers of the compiler used. As a user, you cannot do much to change the existing generator, but you can always test if it delivers numbers uniformly distributed across the whole interval.
+
+In our solution, we generate 10 random integers between 0 and 9. We then count how many times each of the integers have been generated.  If it is a decent random number generator, all numbers should have been generated roughly an equal number of times.
+::
+#include "../asteroid/test-suites/action-tests/test040.ast"
+
+Output:
+::
+
+    [944,1032,1015,968,981,986,1014,1058,989,1013]
+
+
+Section: Mathematical Problems
+------------------------------
+
+Challenge: Distance between two points
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Calculate the distance between the two points on a surface.
+
+There are two points on a surface, each with their own coordinates, x and y. The task is to find the distance between these two points.
+A straightforward solution would be to use the Pythagorean theorem:
+::
+#include "../asteroid/test-suites/action-tests/test041.ast"
+
+Output:
+::
+
+    2.23606797749979
+
+
+Another approach is using the math identity,
+::
+
+    ||a|| = sqrt(a . a)
+
+
+where ``.`` represents the dot product. In our case ``a`` would be the distance vector between points ``x`` and ``y``,
+::
+#include "../asteroid/test-suites/action-tests/test042.ast"
+
+Output:
+::
+
+    2.23606797749979
+
+
+The interesting part about the second approach is that it is completely dimension independent.  Note that except for the definition of the vectors $x$ and $y$ dimension never plays a part in the definition of the program.
+
+Challenge: Standard deviation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> For the given data, calculate the standard deviation value (sigma).
+
+Standard deviation is a statistical term that shows how compact data distribution is. The formula is the following:
+
+.. math::
+
+    \sigma = \sqrt\frac{1}{n-1}\sum_i(\bar{x} - x_i)^2
+
+where :math:`n` is the number of elements in the array :math:`x`; :math:`\bar{x}` is its average value (**Challenge: Average on an array**).
+::
+#include "../asteroid/test-suites/action-tests/test043.ast"
+
+Output:
+::
+
+    420.96248961952256
+
+
+Challenge: Polar coordinates
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Convert the Cartesian coordinates to polar and backward.
+
+Polar coordinates are a convenient way of representing points on a surface with the two values: distance from the centre of coordinates, and the angle between the vector and the pole axis.
+The conversion formulae between the Cartesian and polar systems, which is valid for **positive** ``x`` and ``y``, are the following:
+::
+
+    x = r cos(psi)
+    y = r sin(psi)
+    r = sqrt(x^2 + y^2)
+    psi = arctan(x/y)
+
+These expressions can be implemented as-is in the code:
+::
+#include "../asteroid/test-suites/action-tests/test044.ast"
+
+Output:
+::
+
+    (1.0000000000000002,2.0)
+
+
+For the **negative** ``x`` and ``y``, the Cartesian-to-polar conversion is a bit more complicated. Depending on the quadrant of the point, the ``psi`` value is bigger
+or smaller than ``pi``. When ``x`` is zero, it is either ``-pi/2`` or ``pi/2``.
+All these variants can be implemented by using ``with`` clauses and conditional matching, as demonstrated below:
+::
+#include "../asteroid/test-suites/action-tests/test045.ast"
+
+Output:
+::
+
+    (-2.999999999999999,5.000000000000001)
+
+
+Challenge: Monte Carlo method
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Calculate the area of a circle of radius 1 using the Monte Carlo method.
+
+The Monte Carlo method is a statistical method of calculating data whose formula is not known. The idea is to generate a big number of random numbers and see how many of them satisfy the condition.
+
+To calculate the area of a circle with a radius of 1, pairs of random numbers between −1 and 1 are generated. These pairs represent the points in the square in the center of coordinates with sides of length 2. The area of the square is thus 4. If the distance between the random point and the center of the square is less than 1, then this point is located inside the circle of that radius. Counting the number of points that landed inside the circle and the number of points outside the circle gives the approximate value of the area of the circle, as soon as the area of the square is known. Here is the program.
+::
+#include "../asteroid/test-suites/action-tests/test046.ast"
+
+Output:
+::
+
+    3.1392
+
+
+Challenge: Guess the number
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Write a program that generates a random integer number between 0 and 10, asks the user to guess it, and says if the entered value is too small or too big.
+
+First, a random number needs to be generated. Then the program must
+ask for the initial guess and enter the loop, which compares the guess with the generated number.
+::
+#include "../asteroid/test-suites/action-tests/test047.ast"
+
+Challenge: Binary to integer
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Convert a binary number to a decimal integer.
+
+In Asteroid this is straightforward using the built-in ``tointeger`` function, passing it a string representation of the binary number and the base.
+::
+#include "../asteroid/test-suites/action-tests/test048.ast"
+
+Output:
+::
+
+    45
+
+
+Challenge: Integer as binary, octal, and hex
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print a given integer number in the binary, octal, and hexadecimal representations.
+
+In Asteroid this is easily done with the ``tobase`` function.
+::
+#include "../asteroid/test-suites/action-tests/test049.ast"
+
+Output:
+::
+
+    101010
+    52
+    2A
+
+
+Challenge: Sum of digits
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Calculate the sum of digits of a given number.
+
+Pretty straightforward using string and list manipulation.
+::
+#include "../asteroid/test-suites/action-tests/test050.ast"
+
+Output:
+::
+
+    49
+
+
+Challenge: Bit counter
+^^^^^^^^^^^^^^^^^^^^^^
+
+> Count the number of bits set to 1 in a binary representation of a positive integer number.
+
+If we remove all the zeros from a binary number, then we are left with only ``1`` characters which we can then count.
+::
+#include "../asteroid/test-suites/action-tests/test051.ast"
+
+Output:
+::
+
+    4
+
+
+Challenge: Compose the largest number
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Given the list of integers, compose the largest possible number by concatenating them.
+
+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.
+::
+#include "../asteroid/test-suites/action-tests/test052.ast"
+
+Output:
+::
+
+    8675451
+
+
+Challenge: Convert to Roman numerals
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Convert an integer number to a Roman numerals string.
+
+Roman numbers are not a direct translation of the decimal system. In this task, we assume that the number is not more than 3999, which is the maximum a regular Roman number can reach.
+
+Let’s use the algorithm that keeps the table of pre-calculated sequences of Roman letters. This is so that we don’t have to check when III becomes IV, or when another I appears after V, etc.
+
+In the program below, there are four such sequences: for thousands, hundreds, tens, and ones. The program iterates over the digits of the number in the decimal representation and chooses one of the values from the array of lists stored in the ``roman_hash`` table.
+::
+#include "../asteroid/test-suites/action-tests/test053.ast"
+
+Output:
+::
+
+    [(2,1000),(0,100),(1,10),(8,1)]
+    MMXVIII
+
+
+Challenge: Spelling numbers
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Write an integer number below one million in words.
+
+Human languages have many inconsistencies, especially in the most frequent constructs. Spelling numbers seems to be a simple task, but due to a number of small differences, the resulting program is quite big.
+
+The program is listed on the next page. Let’s discuss the algorithm first.
+
+Take a number; for example, 987,654. The rules for spelling out the groups of three digits, 987 and 654, are the same. For the first group, the word thousand must be added.
+
+Now, examine a group of three digits. The first digit is the number of hundreds, and it has to be spelled only if it is not zero. If it is not zero, then we spell the digit and add the word hundred.
+
+Now, remove the leftmost digit, and we’ve got two digits left. If the remaining two digits form the number from 1 to 20, then it can be directly converted to the corresponding name. The names for the numbers from 0 to 10 are obviously different. The names for the numbers from 11 to 19 have some commonalities, but is it still easier to directly prepare the names for all of them.
+
+For the larger numbers (21 to 99), there are two cases. If the number is dividable by 10 then a name for 20, 30, 40, etc. is taken. If not, then the name is built of the name of tens and the name for units, joined with a hyphen, such as forty-five.
+
+The zero name appears only in the case when the given number is zero.
+::
+#include "../asteroid/test-suites/action-tests/test054.ast"
+
+Output:
+::
+
+    fifteen
+    seventy-five
+    nine hundred eighty-seven thousand six hundred fifty-four
+    one thousand one
+
+
+Section: Manipulating Lists and Arrays
+--------------------------------------
+
+Challenge: Swap two values
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Swap the values of two variables.
+
+In Asteroid, there is no need to use temporary variables to swap the values of two variables. Just use tuples on both sides of the equation:
+::
+
+    let (b,a) = (a,b).
+
+Consider the complete program:
+::
+#include "../asteroid/test-suites/action-tests/test055.ast"
+
+Output:
+::
+
+    (a = 20,b = 10)
+
+
+This program prints the swapped values:
+::
+
+    (a = 20,b = 10)
+
+This approach also works with elements of an array:
+::
+#include "../asteroid/test-suites/action-tests/test056.ast"
+
+Output:
+::
+
+    [3,5,4,7]
+
+
+Challenge: Reverse a list
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print the given list in reverse order.
+::
+#include "../asteroid/test-suites/action-tests/test057.ast"
+
+Output:
+::
+
+    [50,40,30,20,10]
+
+
+Challenge: Rotate a list
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Move all elements of an array N positions to the left or to the right.
+
+Asteroid does not have a built-in ``rotate`` function. However, such a function is easily constructed through slicing lists (see ``vix`` below).
+::
+#include "../asteroid/test-suites/action-tests/test058.ast"
+
+Output:
+::
+
+    [1,3,5,7,9,11,13,15]
+    [7,9,11,13,15,1,3,5]
+    [11,13,15,1,3,5,7,9]
+
+
+Challenge: Randomize an array
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Shuffle the elements of an array in random order.
+
+This is easily accomplished with the built-in ``shuffle``.
+::
+#include "../asteroid/test-suites/action-tests/test059.ast"
+
+Output:
+::
+
+    [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]
+
+
+Challenge: Incrementing array elements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Increment each element in an array.
+
+For this we use Asteroid's ``vector`` module, which can handle incrementing a vector with a scalar.
+::
+#include "../asteroid/test-suites/action-tests/test060.ast"
+
+Output:
+::
+
+    [2,3,4,5,6,7,8,9,10,11]
+
+
+Challenge: Adding up two arrays
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Take two arrays and create a new one whose elements are the sums of the corresponding items of the initial arrays.
+
+Again, here we take advantage of Asteroid's ``vector`` module.  Note that the two vectors have to be of the same length in order to add them together.
+::
+#include "../asteroid/test-suites/action-tests/test061.ast"
+
+Output:
+::
+
+    [40,42,44,46,48,50,52,54,56,58,60]
+
+
+The vector module defines a function called ``op`` that allows you to combine two vectors using any arbitrary binary function.  Rewriting the above program using ``op``,
+::
+#include "../asteroid/test-suites/action-tests/test062.ast"
+
+Output:
+::
+
+    [40,42,44,46,48,50,52,54,56,58,60]
+
+
+As we said above, any arbitrary binary function. Consider the relational operator ``<`` expressed as a lambda function,
+::
+#include "../asteroid/test-suites/action-tests/test063.ast"
+
+Output:
+::
+
+    [false,true,false,false,false,true,false,false,true,true]
+
+
+Challenge: Exclusion of two arrays
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> From the given two arrays, find the elements of the first array which do not
+appear in the second one.
+
+Here we use Asteroid's ``set`` module.
+::
+#include "../asteroid/test-suites/action-tests/test064.ast"
+
+Output:
+::
+
+    [2,3,1,4]
+
+
+Section: Information Retrieval
+------------------------------
+
+Challenge: Sum of the elements of an array
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the sum of the elements of an array of integers.
+::
+#include "../asteroid/test-suites/action-tests/test065.ast"
+
+Output:
+::
+
+    125
+
+
+If summing up elements that are greater than 10,
+::
+#include "../asteroid/test-suites/action-tests/test066.ast"
+
+Output:
+::
+
+    92
+
+
+Challenge: Average of an array
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the average value of the given array of numbers.
+::
+#include "../asteroid/test-suites/action-tests/test067.ast"
+
+Output:
+::
+
+    60
+
+
+Challenge: Is an element in a list?
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Tell if the given value is in the list.
+::
+#include "../asteroid/test-suites/action-tests/test069.ast"
+
+Output:
+::
+
+    17 is in the list
+
+
+We can also use a reduction function to solve this,
+::
+#include "../asteroid/test-suites/action-tests/test070.ast"
+
+Output:
+::
+
+    17 is in the list
+
+
+Challenge: First odd number
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the first odd number in a list of integers.
+
+The easiest way to do this is with a reduction,
+::
+#include "../asteroid/test-suites/action-tests/test071.ast"
+
+Output:
+::
+
+    9
+
+
+Challenge: Take every second element
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Form a new array by picking every second element from the original array.
+::
+#include "../asteroid/test-suites/action-tests/test072.ast"
+
+Output:
+::
+
+    [21,23,25,27,29]
+
+
+We can use an index vector to accomplish  the same thing,
+::
+#include "../asteroid/test-suites/action-tests/test073.ast"
+
+Output:
+::
+
+    [21,23,25,27,29]
+
+
+Challenge: Number of occurrences in an array
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Count how many times a particular element appears in the array.
+::
+#include "../asteroid/test-suites/action-tests/test074.ast"
+
+Output:
+::
+
+    2
+
+
+Challenge: Finding unique elements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Print all unique elements of the given array.
+
+Converting a list to a set will remove all duplicate elements in the list.
+::
+#include "../asteroid/test-suites/action-tests/test075.ast"
+
+Output:
+::
+
+    [2,3,4,5,6,7,10]
+
+
+Challenge: Minimum and maximum
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Find the minimum and the maximum numbers in the given list of integers.
+::
+#include "../asteroid/test-suites/action-tests/test076.ast"
+
+Output:
+::
+
+    15
+    2
+
+
+Challenge: Increasing sequences
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Check if the given array contains increasing (or decreasing) numbers.
+::
+#include "../asteroid/test-suites/action-tests/test077.ast"
+
+Output:
+::
+
+    true
+
+Section: Multi-Dimensional Data
+-------------------------------
+
+Challenge: Transpose a matrix
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Take a matrix and print its transposed version.
+
+In Asteroid a matrix can be represented by nested lists, like so,
+::
+
+    let m = [[1,2],
+             [3,4]].
+
+The transpose of this matrix is,
+::
+
+    let m = [[1,3],
+             [2,4]].
+
+In a square matrix computing the transpose is just a matter of swapping around the elements.  However, here we will solve the more general problem for non-square matrices,
+::
+
+    let m = [[1,2],
+             [3,4],
+             [5,6]].
+
+with its transpose,
+::
+
+    let m = [[1,3,5],
+             [2,4,6]].
+
+The procedure:
+::
+#include "../asteroid/test-suites/action-tests/test078.ast"
+
+Output:
+::
+
+    The transpose of:
+
+    1 2
+    3 4
+
+    is:
+
+    1 3
+    2 4
+
+
+    The transpose of:
+
+    1 2
+    3 4
+    5 6
+
+    is:
+
+    1 3 5
+    2 4 6
+
+
+Challenge: Sort hashes by parameter
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Sort a list of hashes using data in their values.
+
+This task is commonly performed to sort items where the sortable parameter is one of the values in the hash. For example, sorting a list of people by age.
+::
+#include "../asteroid/test-suites/action-tests/test079.ast"
+
+Output:
+::
+
+    [(Pete,20),(Joe,23),(Billie,40),(Brandi,43)]
+
+
+Challenge: Count hash values
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> For a given hash, count the number of occurrences of each of its values.
+
+For example, a hash is a collection mapping a car’s license plate to the colour of the car or a passport number to the name of the street where the person lives. In the first example, the task is to count how many cars of each colour there are. In the second example, we have to say how many people live on each street. But let’s simply count the colours of fruit.
+::
+#include "../asteroid/test-suites/action-tests/test080.ast"
+
+Output:
+::
+
+    [(red,1),(purple,1),(yellow,2),(orange,2),(green,4)]
+
+
+Challenge: Product table
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Generate and print the product table for the values from 1 to 10.
+
+We will do this with an outer loop  and a ``map`` function.
+::
+#include "../asteroid/test-suites/action-tests/test081.ast"
+
+Output:
+::
+
+      1   2   3   4   5   6   7   8   9  10
+      2   4   6   8  10  12  14  16  18  20
+      3   6   9  12  15  18  21  24  27  30
+      4   8  12  16  20  24  28  32  36  40
+      5  10  15  20  25  30  35  40  45  50
+      6  12  18  24  30  36  42  48  54  60
+      7  14  21  28  35  42  49  56  63  70
+      8  16  24  32  40  48  56  64  72  80
+      9  18  27  36  45  54  63  72  81  90
+     10  20  30  40  50  60  70  80  90 100
+
+
+Challenge: Pascal triangle
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+> Generate the numbers of the Pascal triangle and print them.
+
+The Pascal triangle is a sequence of rows of integers. It starts with a single 1 on the top row, and each following row has one number more, starting and ending with 1, while all of the other items are the sums of the two elements above it in the previous row. It is quite obvious from the illustration:
+::
+
+           1
+          1 1
+         1 2 1
+        1 3 3 1
+       1 4 6 4 1
+     1 5 10 10 5 1
+    1 6 15 20 15 6 1
+
+To calculate the values of the next row, you may want to iterate over the values of the current row and make the sums with the numbers next to it. Let us use the functional style that the language offers.
+Consider the fourth row, for example: 1 3 3 1. To make the fifth row, you can shift all the values by one position to the right and add them up to the current row:
+::
+
+      13310
+    + 01331
+    -------
+    14641
+
+We can easily accomplish this with our ``vector`` module. Given the vector of the fourth row,
+::
+
+    [1,3,3,1]
+
+we create two new vectors,
+::
+
+    [1,3,3,1,0]
+
+and
+::
+
+    [0,1,3,3,1]
+
+We then add them together,
+::
+
+    vector @add([1,3,3,1,0],[0,1,3,3,1]) = [1,4,6,4,1]
+
+The only thing that is left to do is to iterate appropiately and format the output.
+::
+#include "../asteroid/test-suites/action-tests/test082.ast"
+
+Output:
+::
+
+    1
+    1 1
+    1 2 1
+    1 3 3 1
+    1 4 6 4 1
+    1 5 10 10 5 1
+    1 6 15 20 15 6 1
+
+
+The program prints the first seven rows of the Pascal triangle. The rows are not centred, and are aligned to the left side.
+As an extra exercise, modify the program so that it prints the triangle as it is shown at the beginning of this task. For example, you can first generate rows and keep them in a separate array and then, knowing the length of the longest string, add some spaces in front of the rows before printing them.
diff --git a/docs/Installing and Running.rst b/docs/Installing and Running.rst
index 41ed75e6..929e12a4 100644
--- a/docs/Installing and Running.rst
+++ b/docs/Installing and Running.rst
@@ -5,8 +5,8 @@ Installation
 
 Asteroid is available from the PyPI project website
 `pypi.org/project/asteroid-lang <https://pypi.org/project/asteroid-lang>`_
-and is installed using,
-::
+and is installed using::
+
     $ pip install asteroid-lang
 
 The should work on Unix-like and Windows systems,
@@ -27,12 +27,13 @@ You can now run the interpreter from the command line by simply typing `asteroid
 This will work on both Windows and Unix-like systems as long as you followed the instructions above.
 To run asteroid on Unix-like systems and on our virtual machine,
 ::
+
     $ cat hello.ast
     -- the obligatory hello world program
 
     load system io.
 
-    println "Hello, World!".
+    io @println "Hello, World!".
 
     $ asteroid hello.ast
     Hello, World!
@@ -40,12 +41,13 @@ To run asteroid on Unix-like systems and on our virtual machine,
 
 On Windows 10 the same thing looks like this,
 ::
+
     C:\> type hello.ast
     -- the obligatory hello world program
 
     load system io.
 
-    println "Hello, World!".
+    io @println "Hello, World!".
 
     C:\> asteroid hello.ast
     Hello, World!
@@ -53,8 +55,18 @@ On Windows 10 the same thing looks like this,
 
 
 As you can see, once you have Asteroid installed on your system you can execute an
-Asteroid program by typing,
-::
+Asteroid program by typing::
+
     asteroid [flags] <program file>
 
-at the command prompt.
+at the command prompt.  Asteroid also supports an interactive mode::
+
+    $ asteroid
+    Asteroid Version 1.0.0
+    Run "asteroid -h" for help
+    Press CTRL+D to exit
+    > load system io.
+    > io @println "Hello, World!".
+    Hello, World!
+    >
+  
diff --git a/docs/Quickstart Tutorial.rst b/docs/Quickstart Tutorial.rst
new file mode 100644
index 00000000..7d861bdc
--- /dev/null
+++ b/docs/Quickstart Tutorial.rst
@@ -0,0 +1,218 @@
+.. role:: raw-html(raw)
+   :format: html
+
+Welcome To Asteroid!
+====================
+Thank you for visiting our page about Asteroid! If you have gone to the `Asteroid Documentation <https://asteroid-lang.readthedocs.io/en/latest/>`_ then you have seen that Asteroid is a pattern-matching oriented language.
+If you have not heard of that programming paradigm (type of programming language) before, Asteroid is one of the first of its kind. Here we provide a brief introduction to Asteroid geared towards C++ programmers.
+
+Pattern Matching at the Core of Things
+--------------------------------------
+Pattern-matching is the idea of extracting values from a structure by applying a pattern to that structure.  If the pattern
+contains variables then these variables will be instantiated with values from the structure during a successful match.  Consider the structure ``(1,2)``.
+If we apply the pattern ``(1,x)`` to that structure then the ``1`` will be matched and the variable ``x`` will be instantiated
+with the value ``2``.  The interesting part about pattern matching is that they can also fail to match.  Consider again
+our structure ``(1,2)`` but now we want to apply the pattern ``(y,1)``.  This pattern match will fail because the second component of our structure and the pattern do not match.  Because of this mismatch the variable ``y`` will also not be instantiated.  Perhaps the simplest pattern match is between a value
+and a variable as a pattern.  In that case the variable is simply instantiated with the value.
+
+A very interesting aspect of pattern matching is that it provides a powerful way to inspect the values passed to a function.
+Consider the C++ function ``f`` defined here,
+::
+  #include <iostream>
+
+  void f(int x) {
+    if (x == 0)
+      std::cout << "zero\n";
+    else
+      std::cout << "not zero\n";
+  }
+
+If the integer value passed to the function is equal to zero then it prints out the word ``zero``, otherwise it prints out
+the words ``not zero``.
+Here the programmer has to use conditionals in order to decide which output to produce.  Using conditionals is not a bad practice, however,
+functions that use pattern tend to look less cluttered.
+
+Here is the same function written in Asteroid using pattern matching,
+::
+  load system io.
+
+  function f
+     with 0 do
+        io @println("zero").
+     with x do
+        io @println("not zero").
+     end
+
+Here the value ``0`` and the variable ``x`` appearing right after the ``with`` keywords are patterns that are applied to the function value.
+If the function is called with the value ``0`` then the value will be matched by the first pattern and the associated print statement is executed.
+If the value with which the function was called is anything but ``0`` then the second pattern will match and that associated print statement
+will be executed. A variable can be considered a pattern
+that will match any value (unless other conditions have been placed on that variable).
+
+The interesting part about patterns is that they can include all kinds of additional information like, for example, that the value a pattern is to
+match is a positive integer. Consider the following example of the recursive factorial implementation.  Let's look at that function in C++,
+::
+     int fact(int x) {
+       if (x == 0)
+          return 1;
+       else if (x > 0)
+          return x * fact(x-1);
+       else
+         throw "undefined for negative values";
+     }
+
+Factorials are only defined over positive integers.  So notice that in this case we have to declare the argument as an integer argument and then
+later in the function we need to make sure that the integer value being passed in is in the correct range of values in order for the computation to be successful.
+With pattern matching in Asteroid we can accomplish all this right in the patterns that we apply to the input argument,
+::
+   -- define patterns matching positive or negative integer values
+   let POS_INT = pattern %[(k:%integer) if k > 0]%.
+   let NEG_INT = pattern %[(k:%integer) if k < 0]%.
+
+   -- define our factorial function
+   function fact
+       with 0 do
+           return 1
+       with x:*POS_INT do            -- use first pattern
+           return x * fact(x-1).
+       with x:*NEG_INT do            -- use second pattern
+           throw Error("undefined for "+x).
+       end
+
+The first two lines of the program create the patterns that define what it means to be a positive or negative integer. For example, the first pattern will only match a value that is an integer whose value is larger than zero. Later in the program, these patterns get dereferenced (which means retrieved from where they are stored in memory) using the ``*`` operator. Notice that we have a similar setup here as with the ``f`` function we looked at earlier.  If the ``0`` pattern matches then we will just return the value ``1``. The line after that is saying "with the argument x and the pattern POS_INT (or in other words, if the argument is positive), recursively find the factorial of the number" and the last ``wth`` line is saying "with the argument x and the pattern NEG_INT (if the argument is negative), throw an error".
+Notice that patterns allow us to precisely define what we mean by positive or negative integers in one place and then use these patterns in our function.
+
+Pattern matching can be applied in a lot of places in Asteroid.  But one other place is perhaps more prevalent than any other, which is pattern
+matching in Asteroid's ``let`` statement.
+The ``let`` statement is Asteroid's version of the assignment statement with a twist though:  the left side of the ``=`` sign is not just a variable
+but is considered a pattern.  For simple assignments there is no discernible difference between assignments in Asteroid and assignments in other
+languages,
+::
+  let x = val.
+
+Here, the variable ``x`` will match the value stored in ``val``.  However, because the left side of the ``=`` sign is a pattern we
+can write something like this,
+::
+  let x:%[(k:%integer) if 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,
+::
+   let 1 = 1.
+
+which simply states that the value ``1`` on the right can be matched by the pattern ``1`` on the left.  Having the ability to pattern match
+on literals is convenient for statements like these,
+::
+  let (1,x) = p.
+
+This ``let`` statement is only successful for values of ``p`` which are pairs where the first component of the pair is the value ``1``.
+**The thing to remember is that the let statement is not entirely equivalent to the assignment operator in other languages, even though it may look like that.**
+
+
+Object-Oriented Programming in Asteroid
+---------------------------------------
+The term object-oriented in programming means that code is broken up into classes and objects. Think of classes as **user defined data types**. While this may sound intimidating, there are many uses of object-oriented programming that can be used to help write efficient, clean code. For instance, there may be a time where you have to write code for software that pertains to families. While you could use tuples or arrays to represent this data, objects and classes are an even better way to achieve this feat. Take a look at this code in C++ that has the class for a family:
+::
+     #include <string>
+
+     class Family {
+     public:
+         std::string parent;
+         std::string child1;
+         std::string child2;
+
+         // constructor
+         Family(std::string p, std::string c1, std::string c2) {
+             this->parent = p;
+             this->child1 = c1;
+             this->child2 = c2;
+         }
+     };
+
+Now if you want to create an instance or object of the Family class, you could write this line to do so:
+::
+   Family *myfamily = new Family("Jim", "Bob", "Ann");
+
+where the properties parent is "Jim", child1 is "Bob" and child2 is "Ann". Now if you wanted to access one of these properties, you could do,
+::
+   std::cout << myfamily->child1; // while this looks intimidating, all this is doing is dereferencing child1
+
+Classes and objects are an easier way to store data that may not fit with any data structure that a language currently has.
+Asteroid implements object-orientation via structures, an approach it shares with the programming language Rust.
+In Asteroid the above example would be written as,
+::
+   structure Family with
+       data parent.
+       data child1.
+       data child2.
+
+       -- constructor
+       function __init__ with (p:%string, c1:%string, c2:%string) do
+          let this @parent = p.
+          let this @child1 = c1.
+          let this @child2 = c2.
+       end
+   end
+
+And you can create an object from that structure by doing,
+::
+   let myfamily = Family("Jim", "Bob", "Ann").
+
+Notice how similar the construction of objects are in both languages.
+**Think of structures in Asteroid as classes in C++, and in both languages these allow you to instantiate objects** (that means if you have programmed with classes and objects in C++, creating structures in Asteroid should be trivial). Something else to note is that similar to Rust and Go, **Asteroid does not have inheritance for classes**.  That is why programming in Asteroid is sometimes referred to as object-based programming rather than object-oriented programming.
+
+We can access substructures of objects with the access operator ``@``,
+::
+  io @println (myfamily @child1).
+
+which will print out the name of the first child.
+
+The name of the class above can now be considered a user defined data type and can appear wherever built-in data type names can appear.
+For instance it can appear in a pattern restricting the values a particular variable can take on,
+::
+  let f:%Family = myfamily.
+
+Since we are talking about the ``let`` statement in conjunction with objects, Asteroid allows pattern matching on objects!  This allows for
+easy access to substructures of objects,
+::
+     let Family(parent,first,second) = myfamily.
+
+     assert(parent is "Jim").
+     assert(first is "Bob").
+     assert(second is "Ann").
+
+Here we are matching the object stored in ``myfamily`` again the pattern ``Family(parent,first,second)`` and the variables will be instantiated
+with appropriate values from the ``data`` members of the object.
+
+Now that you understand the two different paradigms that Asteroid is made out of, you can start writing your programs in it and explore the versatility of patterns, pattern-matching and object-oriented programming.
+
+
+How to Get Started in Asteroid
+-------------------------------
+Now that you know what principles Asteroid is made of, you can now get started writing programs in it. Directions to install Asteroid can be found `here <https://asteroid-lang.readthedocs.io/en/latest/Installing%20and%20Running.html>`_.
+After you installed Asteroid correctly, you can write your first program. The first one you can write is a simple hello world program, which looks something like:
+::
+   load system io. -- header that allows the programmer to print things out to the screen and to accept input
+
+   io @println "Hello, World!".
+
+After you have written your first program, you can run the program by typing in the following line in your terminal:
+::
+   asteroid <name of program>
+
+where the name of the program is the name of the file that you want to run.
+
+**Make sure that you are in the same folder in your terminal of the file that you are trying to run!**
+
+Notice how the ``@`` symbol is used in two different places (this is common in programming languages, where one operator can be used multiple ways). In Asteroid, modules (which was the ``load system io.`` line at the top of our files) are actually objects, so to access a method in a module, you use the ``@`` symbol. So in this example, the module is the ``io`` module and we want to use the ``println`` method in that module, which is why you see the ``@`` symbol in there. **A module is a group of code that has already been written (typically by the developers of the language) which can be used again in other people's programs.**
+
+`Here <https://asteroid-lang.readthedocs.io/en/latest/Reference%20Guide.html#asteroid-modules>`_ is the complete list of modules in Asteroid.
+
+Some important things to note in Asteroid:
+
+* Most statements must end with a period (this is equivalent to using a semicolon in C++)
+* In order to print things, you must include the ``load system io.`` in your program before you attempt any output.
+* lines that start with ``--`` are comment lines
+* If you see a line that looks like (``x:%integer``), that is used to match any value of a given type. (The ``%integer`` pattern matches any integer value and can be used with any other type in Asteroid.)
+
+If you would like more information about Asteroid, please see the Asteroid `reference guide <https://asteroid-lang.readthedocs.io/en/latest/Reference%20Guide.html#>`_  and `user guide <https://asteroid-lang.readthedocs.io/en/latest/Asteroid%20User%20Guide.html>`_.
diff --git a/docs/Reference Guide.rst b/docs/Reference Guide.rst
index b8a2cfe4..46aab065 100644
--- a/docs/Reference Guide.rst
+++ b/docs/Reference Guide.rst
@@ -1,3 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+..
+   *** DO NOT EDIT; MACHINE GENERATED ***
+
 .. highlight:: none
 
 Asteroid Reference Guide
@@ -6,14 +23,601 @@ Asteroid Reference Guide
 Language Syntax
 ---------------
 
+Note: In the following descriptions ``<something>?`` denotes an optional
+something in a piece of syntax.  We also use the notation ``<something>*``
+which means that something can appear zero or more times in a program.
+Capitalized
+words are keywords where ``FOR`` represents the keyword ``for`` and ``END``
+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
+%%%%%
+
+Syntax: ``BREAK '.'?``
+
+The break statement immediately breaks out of the closest surrounding looping structure.
+Execution will continue at the statement right after the loop. Issuing a break statement
+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).
+
+Expressions at the Statement Level
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Expressions at the statement level are supported.  However, they do not have
+any effect on the computation unless they contain side effects with one
+exception:  In the absence of an explicit return statement, the value of the last expression
+evaluated in a function body is considered the return value of the function.
+
+An example,
+::
+      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.
+
+For-Loop
+%%%%%%%%
+
+Syntax: ``FOR pattern IN exp DO stmt_list END``
+
+In a for-loop the expression must evaluate to a list.  The pattern is then matched to
+each element of the list sequentially starting with the first element of the list.
+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
+
+
+Function-Definition
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: FUNCTION function_name WITH pattern DO stmt_list (WITH pattern DO stmt_list)* END
+
+Function definitions in Asteroid can have one or more function bodies associated
+with single function name.  A function body is associated with a particular pattern
+that is matched against the actual argument of the function call.  If the match
+is successful then the associated function body is executed.  If the match is not
+successful then other pattern/body pairs are tried if present.  If none of the
+patterns match the actual argument then this constitutes a runtime error.
+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
+
+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.
+
+Global
+%%%%%%
+
+Syntax: ``GLOBAL variable_name (',' variable_name)* '.'?``
+
+The ``global`` statement allows the developer to declare a variable as global
+within a function scope and this allows the developer to set the value of a global variable
+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).
+
+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``.
+
+If-Then-Else
+%%%%%%%%%%%%
+
+Syntax: ``IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE DO? stmt_list)? END``
+
+If the first expression evaluates to the equivalent of a Boolean ``true`` value
+then the associated statements will be executed and the execution
+continues after the ``end`` keyword.  If the expression evaluates to the equivalent
+of a Boolean ``false`` then the expressions of the optional ``elif`` clauses
+are evaluated if present.  If one of them evaluates to the equivalent of a Boolean
+value ``true`` then the associated statements are executed and execution continues
+after the ``end`` keyword. Otherwise
+the statements of the optional ``else`` clause are executed if present and again
+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
+
+
+Let
+%%%
+
+Syntax: ``LET pattern = exp '.'?``
+
+The ``let`` statement is Asteroid's version of the assignment statement with a twist though:  the left side of the ``=`` sign is not just a variable
+but is considered a pattern.  For simple assignments there is no discernible difference between assignments in Asteroid and assignments in other
+languages,
+::
+  let x = val.
+
+Here, the variable ``x`` will match the value stored in ``val``.  However, because the left side of the ``=`` sign is a pattern we
+can write something like this,
+::
+  load system math.
+  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,
+::
+   let 1 = 1.
+
+which simply states that the value ``1`` on the right can be matched by the pattern ``1`` on the left.  Having the ability to pattern match
+on literals is convenient for statements like these,
+::
+  let (1,x) = p.
+
+This ``let`` statement is only successful for values of ``p`` which are pairs where the first component of the pair is the value ``1``.
+
+
+Loop
+%%%%
+
+Syntax: ``LOOP DO? stmt_list END``
+
+The ``loop`` statement executes the statements in the loop body indefinitely
+unless a ``break`` statement is encountered.
+
+Repeat-Until
+%%%%%%%%%%%%
+
+Syntax: ``REPEAT DO? stmt_list UNTIL exp '.'?``
+
+Repeatedly execute the statements in the loop body until the
+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 [].
+
+
+Return
+%%%%%%
+
+Syntax; ``RETURN exp? '.'?``
+
+Explicitly return from a function with an optional return value.
+
+Structure
+%%%%%%%%%
+
+Syntax: ``STRUCTURE type_name WITH data_or_function_stmts END``
+
+The ``structure`` statement introduces a composite data type that defines a physically grouped list of variables under one name.  The variables within a structure can be declared as data members or as function members.
+Unless a member function was declared as a constructor (an ``__init__`` function) structures are
+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
+
+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
+      end
+
+      let betty = Person("Betty",21).  -- call constructor
+      assert( betty @name == "Betty" ).
+      assert( betty @age == 21 ).
+
+Also note that object identity is expressed using the ``this`` keyword.
+
+Try-Catch
+%%%%%%%%%
+
+Syntax: ``TRY DO? stmt_list (CATCH pattern DO stmt_list)+ END``
+
+This statement allows the programmer to set up exception handlers for
+exceptions thrown in the code of the ``try`` part of the statement.
+Notice that you can set up one or more handlers within the ``catch`` part of
+the statement.  If there are more than one handlers then they are searched in
+order starting with the first.  Handlers are selected via pattern matching
+on the exception object.  The handler code of the first ``catch`` clause whose
+pattern matches the exception object is executed.
+
+Below is an example of a ``try-catch`` statement where the code
+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
+
+For more details on exceptions please see the User Guide.
+
+Throw
+%%%%%
+
+Syntax: ``THROW exp '.'?``
+
+Allows the developer to throw an exception.  Any object can serve as an
+exception object. However, Asteroid provides some predefined exception objects.
+For more details on exceptions please see the User Guide.
+
+While-Loop
+%%%%%%%%%%
+
+Syntax: ``WHILE exp DO stmt_list END``
+
+While the expression evaluates to the equivalent of a Boolean ``true`` value
+execute the statements in the body of the loop.  The loop expression is reevaluated
+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.
+
+      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
+^^^^^^^^^^^
+
+All the usual arithmetic, relational, and logic operators,
+::
+      +, -, *, /, ==, =/=, <=, <, >=, >, and, or, not
+
+are supported in
+Asteroid.  For extended mathematical operations such as ``mod`` (modulus) or
+``sin`` (sine) see the ``math`` module.  Here we discuss expression constructions
+that are particular to Asteroid.
+
+Substructure Access
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``structure_exp @ index_exp``
+
+Asteroid provides the uniform substructure access operator ``@`` for all structures
+which includes lists, tuples, and objects. For example, accessing the first
+element of a list is accomplished by the expression,
+::
+      [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
+
+
+Head-Tail Operator
+%%%%%%%%%%%%%%%%%%
+
+Syntax: ``element_exp | list_exp``
+
+This operator works in one of two ways.  In the first way it allows you to
+pre-append an element to a list,
+::
+      let [1,2,3] = 1 | [2,3].
+
+It can also be nested,
+::
+      let [1,2,3] = 1 | 2 | 3 | [].
+
+In the second way it works as a pattern to deconstruct a list into its first
+element and the remainder of the list, the list with its first element removed,
+::
+      let h | t = [1,2,3].
+      assert(h == 1).
+      assert(t == [2,3]).
+
+You can put optional brackets around the operator to highlight the fact that
+we are dealing with a list,
+::
+      let [h | t] = [1,2,3].
+
+The ``is`` Predicate
+%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``exp IS pattern``
+
+This operator matches the structure computed by the expression on the left
+side against the pattern on the right side of the operator.  If the match is
+successful it returns the Boolean value ``true`` and if not successful then
+it returns the Boolean value ``false``.  All regular rules of pattern matching
+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".
+      end
+
+The ``in`` Predicate
+%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``exp IN list_exp``
+
+This predicate returns ``true`` if the value computed by the expression on the
+left in contained in the list computed by the list expression on the right.
+It is an error if the expression on the right does not compute a list.
+
+Example,
+::
+      let true = 1 in [1,2,3].
+
+List Comprehensions
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``start_exp TO end_exp (STRIDE exp)?``
+
+This expression constructs a list starting with an element given by the start expression
+up to the value of the end expression with a given stride.  If the stride expression
+is not given then a stride value of 1 is assumed.  The stride value is always a
+positive value.  The comprehension figures out how to apply the stride value to reach the
+end value from the start value.  The comprehension can be placed between optional square brackets.
+
+Examples,
+::
+      let [0,1,2,3,4] = 0 to 4.
+      let [0,-2,-4,-6] = [0 to -6 stride 2].
+
+Function Calls
+%%%%%%%%%%%%%%
+
+Syntax: ``exp exp``
+
+Function calls are defined by function application, more specifically by
+juxtaposition of expressions.  Here, the first expression has to evaluated to
+a function expression and the second expression has to evaluate to an appropriate
+actual function parameter.  Notice that function calls are defined in terms of a
+single function parameter.  If you would like to pass more than one value to a
+function then you have to create a tuple.  For example, if the function ``foo``
+needs two values to be passed to it then you need to create a tuple, e.g. ``foo (1,2)``.
+In that respect function calls differ drastically from function calls in languages
+like C/C++ or Python.
+
+Examples,
+::
+      let val = (lambda with i do i+1) 1.
+      assert(val == 2).
+
+      function foo with (q,p) do q+p end
+      let val = foo (1,2).
+      assert(val == 3).
+
+If-Else Expressions
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``then_exp IF bool_exp ELSE else_exp``
+
+If the boolean expression evaluates to true then this expression returns
+the value of the first expression.  Otherwise it will return the value of the
+last expression.
+
+Example,
+::
+      let val = "yup" if b else "nope".
+
+If ``b`` evaluates to true then this expression returns the string ``"yup"``
+otherwise it returns the string ``"nope"``.
+
+First-Class Patterns
+%%%%%%%%%%%%%%%%%%%%
+
+| Syntax: ``PATTERN exp``
+| Syntax: ``* exp``
+
+This construction allows the user to construct a pattern as a value using
+the ``pattern`` keyword.  The advantage of patterns as values is that they
+can be stored in variables or passed to or from functions.  As an example
+we construct a pattern which is a pair where the first component is the constant
+``1`` and the second component is the variable ``x`` and we store this pattern
+in the variable ``p`` for later use,
+::
+      let p = pattern (1,x).
+
+The pattern derefence operator ``*`` allows us to retrieve patterns from
+variables, e.g.
+::
+      let *p = (1,2).
+
+Here the pair ``(1,2)`` is matched against the pattern stored in the variable ``p``
+such that ``x`` is bound to the value ``2``.
+
+Type Patterns
+%%%%%%%%%%%%%
+
+Syntax: ``'%'type_name``
+
+Type patterns match all the values of a particular type.  Type patterns exist
+for all the Asteroid builtin types and are also available for user defined
+types introduced via a ``structure`` command.
+
+Example,
+::
+      let true = 1 is %integer.
+
+Named Patterns
+%%%%%%%%%%%%%%
+
+Syntax: ``name_exp ':' pattern``
+
+Named patterns allow you to bind the term matched by the pattern to a variable.
+Here the name expression has to evaluate to something that looks like a variable,
+object member variable, or array location.
+
+Example,
+::
+      let x:%integer = val.
+
+The variable ``x`` will be bound to the value of ``val`` if that value matches the
+type pattern ``%integer``.
+
+Conditional Patterns
+%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``pattern IF cond_exp``
+
+In conditional patterns the pattern only matches if the condition expression
+evaluates to true.
+
+Example,
+::
+      load system math.
+      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
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``%[ pattern ]%``
+
+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
+by placing it between the ``%[`` and ``]%`` operators.
+
+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.
+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.
+
+Asteroid Grammar
+^^^^^^^^^^^^^^^^
+
 The following is the complete grammar for the Asteroid language. Capitalized
-words are either keywords or tokens such as ``STRING`` or ``ID``.  Non-terminals
+words are either keywords such as ``FOR`` and ``END`` or tokens such as ``STRING`` and ``ID``.  Non-terminals
 are written in all lowercase letters.  The grammar utilizes an extended BNF notation
 where ``<syntactic unit>*`` means zero or more occurrences of the syntactic unit and
 ``<syntactic unit>+`` means one or more occurrences of the syntactic unit. Furthermore,
 ``<syntactic unit>?`` means that the syntactic unit is optional.  Simple terminals
 are written in quotes.
 ::
+
   ////////////////////////////////////////////////////////////////////////////////////////
   // statements
 
@@ -25,9 +629,8 @@ are written in quotes.
 
   stmt
     : '.' // NOOP
-    | LOAD SYSTEM? STRING '.'?
+    | LOAD SYSTEM? (STRING | ID) '.'?
     | GLOBAL id_list '.'?
-    | NONLOCAL id_list '.'?
     | ASSERT exp '.'?
     | STRUCTURE ID WITH struct_stmts END
     | LET pattern '=' exp '.'?
@@ -36,13 +639,12 @@ are written in quotes.
     | WHILE exp DO stmt_list END
     | REPEAT DO? stmt_list UNTIL exp '.'?
     | IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE DO? stmt_list)? END
-    | MATCH exp WITH? (CASE pattern DO stmt_list)+ (OTHERWISE DO? stmt_list)? END
     | TRY DO? stmt_list (CATCH pattern DO stmt_list)+ END
     | THROW exp '.'?
     | BREAK '.'?
     | RETURN exp? '.'?
     | function_def
-    | call_or_index '.'?
+    | exp '.'?
 
   function_def
     : FUNCTION ID body_defs END
@@ -66,37 +668,28 @@ are written in quotes.
 
   ////////////////////////////////////////////////////////////////////////////////////////
   // 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.
-
-  pattern
-    : exp
-
+  
   exp
-    : quote_exp
+    : pattern
 
-  quote_exp
-    : QUOTE exp
-    | PATTERN WITH? exp
-    | '%[' exp ']%'      // constraint-only pattern match
+  pattern
+    : PATTERN WITH? exp
+    | '%[' exp ']%'      
     | head_tail
 
   head_tail
     : conditional ('|' exp)?
 
+  
   conditional
     : compound (IF exp (ELSE exp)?)?
 
   compound
     : logic_exp0
         (
-          (IS pattern) |
-          (IN exp) |               // exp has to be a list
-          (TO exp (STEP exp)?) |   // list comprehension
+           (IS pattern) |
+           (IN exp) |               
+           (TO exp (STRIDE exp)?) |   
         )?
 
   logic_exp0
@@ -118,7 +711,10 @@ are written in quotes.
     : call_or_index (('*' | '/') call_or_index)*
 
   call_or_index
-    : primary (primary | '@' primary)* (':' pattern)?  // named pattern when ': pattern' exists
+    : primary (primary | '@' primary)* (':' pattern)?  
+
+  ////////////////////////////////////////////////////////////////////////////////////////
+  // primary expressions/patterns
 
   primary
     : INTEGER
@@ -128,14 +724,14 @@ are written in quotes.
     | FALSE
     | NONE
     | ID
-    | '*' ID         // "dereference" a variable during pattern matching
+    | '*' call_or_index   
     | 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 ')' 
+    | '[' list_stuff ']'  
     | function_const
     | TYPEMATCH           // TYPEMATCH == '%'<typename>
 
@@ -150,11 +746,12 @@ are written in quotes.
   function_const
     : LAMBDA body_defs
 
+
 Builtin Functions
 -----------------
 
 * Function ``len``, when given an input value, returns the length of that input. The
-function can only be applied to lists, strings, tuples, or structures.
+  function can only be applied to lists, strings, tuples, or structures.
 
 * Function ``hd``, when given a list as input returns the first element of that list.
   It is an error to apply this function to an empty list.
@@ -164,14 +761,14 @@ function can only be applied to lists, strings, tuples, or structures.
 
 * Function ``range`` will compute a list of values depending on the input values:
 
-  #. ``(start:%integer,stop:%integer)`` returns list ``[start to stop-1]``.
-  #. ``(start:%integer,stop:%integer,inc:%integer)`` returns list ``[start to stop-1 step inc]``.
-  #. ``(stop:%integer)`` returns list ``[0 to stop-1]``.
+  1. ``(start:%integer,stop:%integer)`` returns list ``[start to stop-1]``.
+  2. ``(start:%integer,stop:%integer,inc:%integer)`` returns list ``[start to stop-1 stride inc]``.
+  3. ``(stop:%integer)`` returns list ``[0 to stop-1]``.
 
 * Function ``getid`` returns the id (physical memory address) of any Asteroid object as an Asteroid integer.
 
 * Function ``isdefined`` returns true if a variable or type name is defined in the
-current environment otherwise it returns false. The variable or type name must be given as a string.
+  current environment otherwise it returns false. The variable or type name must be given as a string.
 
 List and String Objects
 -----------------------
@@ -182,9 +779,9 @@ Lists
 ^^^^^
 
 A **list** is a structured data type that consists of square brackets enclosing
-comma-separated values. Lists can be modified after their creation.
-Member functions on lists can be called on the data structure directly, e.g.,
-::
+comma-separated values.
+Member functions on lists can be called on the data structure directly, e.g.::
+
    [1,2,3] @length()
 
 * Function ``length`` returns the number of elements within that list.
@@ -196,15 +793,15 @@ Member functions on lists can be called on the data structure directly, e.g.,
 * Function ``clear``, given ``(none)``, removes all items from the list.
 * Function ``index`` returns a zero-based index in the list of the first element whose value is equal to ``(item)``. It raises a ValueError exception if there is no such item. The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the ``(startix)`` argument.   This function can be called with several input configurations:
 
-  #. ``(item,loc(startix:%integer,endix:%integer))``
-  #. ``(item,loc(startix:%integer))``
-  #. ``item``
+  1. ``(item,loc(startix:%integer,endix:%integer))``
+  2. ``(item,loc(startix:%integer))``
+  3. ``item``
 
 * Function ``count``, given ``(item)``, returns the number of times ``(item)`` appears in the list.
 * Function ``sort`` sorts the items of the list in place. It can be called with several different inputs:
 
-  #. ``(reverse:%boolean)`` if the boolean is set to true then the sorted list is reversed.
-  #. ``none`` returns the reverse list.
+  1. ``(reverse:%boolean)`` if the boolean is set to true then the sorted list is reversed.
+  2. ``none`` returns the reverse list.
 
 * Function ``reverse``, reverses the elements of the list in place.
 * Function ``copy``, makes a shallow copy of the list.
@@ -213,15 +810,15 @@ Member functions on lists can be called on the data structure directly, e.g.,
 * Function ``reduce`` reduces the value of elements in a list. This
   function can be called with several different inputs:
 
-  #. Input ``(f:%function)`` returns ``value``, such that ``value = f(value,this@i)``.
-  #. Input ``(f:%function,init)`` returns the same format but uses ``init`` as an initial value.
+  1. Input ``(f:%function)`` returns ``value``, such that ``value = f(value,this@i)``.
+  2. Input ``(f:%function,init)`` returns the same format but uses ``init`` as an initial value.
 
   The first argument to ``f`` is the accumulator.
 
 * Function ``filter``, given ``(f:%function)``, constructs an output list from those elements of the list for which ``f`` returns true. If ``f`` is none, the identity function is assumed, that is, all elements of the input list that are false are removed.
 * Function ``member``, given ``(item)``, returns true only if ``item`` exists on the list.
 * Function ``join``, given ``(join:%string)``, turns the list into a string using ``join`` between the elements.  The string is returned
-as the return value from this function.
+  as the return value from this function.
 
 
 See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_ for more on all the functions above.
@@ -232,8 +829,8 @@ Strings
 
 A string is a sequence of characters that can be used as a variable or a literal constant.
 Similar to lists the member functions of strings can be called directly on the
-data structure itself, e.g.
-::
+data structure itself, e.g.::
+
    "Hello there" @length()
 
 * Function ``length`` returns the number of characters within that string.
@@ -245,24 +842,21 @@ data structure itself, e.g.
   * ``(old:%string,new:%string)``
 
 * Function ``split`` will return a list of the words in a given string, using ``sep`` as the delimiter string. If ``maxsplit`` is given: at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).
-
   If ``sep`` is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, ``"1,,2"@split(",")`` returns ``["1", "", "2"]``). The ``sep`` argument may consist of multiple characters (for example, ``"1<>2<>3"@split("<>")`` returns ``["1", "2", "3"]``). Splitting an empty string with a specified separator returns ``[""]``.
-
   If ``sep`` is not specified or is None, a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string or a string consisting of just whitespace with a None separator returns ``[]``.
-
   Function ``split`` can be called with several different inputs:
 
-  #. Input ``(sep:%string,count:%integer)``
-  #. Input ``(sep:%string)``
-  #. Input ``(none)``
+  1. Input ``(sep:%string,count:%integer)``
+  2. Input ``(sep:%string)``
+  3. Input ``(none)``
 
 * Function ``toupper``, converts all the lowercase letters in a string to uppercase.
 * Function ``tolower``, converts all the uppercase letters in a string to lowercase.
 * Function ``index`` allows the user to search for a given ``item`` in a list. It returns an integer index into the string or ``none`` if ``item`` was not found.  The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular substring of the string. The returned index is computed relative to the beginning of the full string rather than the ``(startix)`` argument.The function can be called with several different inputs:
 
-  #. Input ``(item:%string,loc(startix:%integer,endix:%integer))``
-  #. Input ``(item:%string,loc(startix:%integer))``
-  #. Input ``(item:%string)``
+  1. Input ``(item:%string,loc(startix:%integer,endix:%integer))``
+  2. Input ``(item:%string,loc(startix:%integer))``
+  3. Input ``(item:%string)``
 
 * Function ``flip`` reverses a string.
 
@@ -272,7 +866,13 @@ See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/
 Asteroid Modules
 ----------------
 
-There are a number of predefined modules that can be loaded into an Asteroid program using ``load system <module name>``.
+There are a number of system modules that can be loaded into an Asteroid program using ``load system <module name>``.
+The modules are implemented as objects where all the functions of that module are
+member functions of that module object. For example, in the case of the ``io`` module
+we have ``println`` as one of the member functions.  To call that function::
+
+   load system io.
+   io @println "Hello there!".  -- println is a member function of the io module
 
 Bitwise
 ^^^^^^^
@@ -305,9 +905,9 @@ IO
 
 The `io <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/io.ast>`_ module implements Asteroid's I/O system. The module defines three default streams,
 
-#. ``__STDIN__`` - the standard input stream.
-#. ``__STDOUT__`` - the standard output stream.
-#. ``__STDERR__`` - the standard error stream.
+1. ``__STDIN__`` - the standard input stream.
+2. ``__STDOUT__`` - the standard output stream.
+3. ``__STDERR__`` - the standard error stream.
 
 Furthermore, the module supports the following functions,
 
@@ -326,24 +926,32 @@ Math
 
 The `math <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/math.ast>`_ module implements mathematical constants and functions. It supports the following functions,
 
+*Power and logarithmic functions*
+
 * Function ``exp``, given ``x:%integer``, returns e raised to the power ``x``, where e = 2.718281… is the base of natural logarithms.
 * Function ``log`` can be called with two different argument setups,
 
-  #. If only one argument, ``(x)``, is input, this returns the natural logarithm of x (to base e).
-  #. If two arguments, ``(x,base)``, are input, this returns the logarithm of x to the given base, calculated as log(x)/log(base).
+  1. If only one argument, ``(x)``, is input, this returns the natural logarithm of x (to base e).
+  2. If two arguments, ``(x,base)``, are input, this returns the logarithm of x to the given base, calculated as log(x)/log(base).
 
 * Function ``pow``, given ``(b,p:%integer)``, returns "b <sup>p</sup>" as long as b is either ``real`` or ``integer``.
 * Function ``sqrt``, given ``a``, returns its square root as long as ``a`` is either ``real`` or ``integer``.
+
+*Number-theoretic and representation functions*
+
 * Function ``abs``, given ``x``, returns its absolute value.
 * Function ``ceil``, given ``x:%real``, returns the ceiling of x: the smallest integer greater than or equal to x.
 * Function ``floor``, given ``x:%real``, returns the floor of x: the largest integer less than or equal to x.
 * Function ``gcd``, given ``(a:%integer,b:%integer)``, returns the greatest common denominator that both integers share.
 * Function ``isclose`` can be called with two different argument setups,
 
-  #. With input values ``(a,b)``, it returns returns ``true`` if the two values are close to each other and ``False`` otherwise. Default tolerance 1e-09.
-  #. With input values ``(a,b,t)``, it compares ``a`` and ``b`` with tolerance ``t``.
+  1. With input values ``(a,b)``, it returns returns ``true`` if the two values are close to each other and ``False`` otherwise. Default tolerance 1e-09.
+  2. With input values ``(a,b,t)``, it compares ``a`` and ``b`` with tolerance ``t``.
 
 * Function ``mod``, given ``(v,d)``, will return the remainder of the operation ``v/d``, as long as ``v`` and ``d`` are either ``real`` or ``integer`` values.
+
+*Trigonometric functions*
+
 * Function ``acos``, given ``x``, returns the arc cosine of x in radians. The result is between 0 and pi.
 * Function ``asin``, given ``x``, returns the arc sine of x in radians. The result is between -pi/2 and pi/2.
 * Function ``atan``, ,given ``x``, returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
@@ -359,10 +967,30 @@ The `math <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/module
 * Function ``degrees``, given ``x``, converts angle ``x`` from radians to degrees.
 * Function ``radians``,  given ``x``, converts angle ``x`` from degrees to radians.
 
+An example,
+::
+    load system io.
+    load system math.
+
+    let x = math @sin( math @pi / 2 ).
+    io @println("The sine of pi / 2 is " + x + ".").
+
 Pick
 ^^^^
 
-The `pick <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/pick.ast>`_ module implements the to randomly pick objects from a list of objects. A ``Pick`` object contains a list of items that can be randomly picked from using the ``pick`` member function. The ``pick`` function can be called with ``n:%integer`` and returns a list of ``n`` randomly picked objects from the object list.
+The `pick <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/pick.ast>`_ module implements
+pick objects that allow a user to randomly pick items from a list using the ``pick`` function.
+The ``pick`` function can be called with ``n:%integer`` and returns a list of ``n`` randomly picked objects from the object list.
+Here is a simple use case
+::
+   load system io.
+   load system pick.
+
+   let po = pick @pick([1 to 10]).
+   let objects = po @pick(3).
+   io @println objects.
+   
+
 
 Random
 ^^^^^^
@@ -372,9 +1000,9 @@ The `random <https://github.com/lutzhamel/asteroid/blob/master/asteroid/modules/
 * Function ``random``, given the input ``none``, returns a random floating point number in the range ``[0.0, 1.0)``.
 * Function ``randint`` returns a random value N in the interval lo <= N <= hi. The exact random value output depends on the types of the values specifying the interval. It can be called with two different number interval inputs:
 
-  #. ``(lo:%integer,hi:%integer)``
-  #. ``(lo:%real,hi:%real)``
-  #. Note: any other interval specification will instead output an error message for "unsupported interval specification in randint."
+  1. ``(lo:%integer,hi:%integer)``
+  2. ``(lo:%real,hi:%real)``
+  3. Note: any other interval specification will instead output an error message for "unsupported interval specification in randint."
 
 * Function ``seed``, given ``(sd:%integer)``, provides a seed value for the random number generator.
 
@@ -384,10 +1012,10 @@ Set
 The `set <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/set.ast>`_ module implements Asteroid sets as lists. Unlike lists, sets do not have repeated members. It supports the following functions,
 
 * Function ``toset``, given ``(lst:%list)``, converts the input list into a set.
-* Function ``sdiff``, given ``(a:%list,b:%list)``, computes the difference set between the two set ``a`` and ``b``.
-* Function ``sintersection``, given ``(a:%list,b:%list)``, finds the intersection between  sets ``a`` and ``b``.
-* Function ``sunion``, given ``(a:%list,b:%list)``, computes the union of sets ``a`` and ``b``.
-* Function ``sxunion``, given ``(a:%list,b:%list)``, returns all elements in ``a`` or ``b``, but not in both.
+* Function ``diff``, given ``(a:%list,b:%list)``, computes the difference set between the two set ``a`` and ``b``.
+* Function ``intersection``, given ``(a:%list,b:%list)``, finds the intersection between  sets ``a`` and ``b``.
+* Function ``union``, given ``(a:%list,b:%list)``, computes the union of sets ``a`` and ``b``.
+* Function ``xunion``, given ``(a:%list,b:%list)``, returns all elements in ``a`` or ``b``, but not in both.
 
 Sort
 ^^^^
@@ -396,31 +1024,50 @@ The `sort <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/module
 defines a parameterized ``sort`` function over a list.
 The ``sort`` function makes use of a user-defined order predicate on the list's elements to
 perform the sort. The ``Quicksort`` is the underlying sort algorithm.
-Here is a simple example example:
+The following is a simple example,
 ::
-  sort((lambda with (x,y) do return true if x<y else false),
-       [10,5,110,50]).
+   load system io.
+   load system sort.
+   let sl = sort @sort((lambda with (x,y) do return true if x<y else false),
+                       [10,5,110,50]).
+    io @println sl.
+
+prints the sorted list::
 
-returns the sorted list,
-::
   [5,10,50,110]
 
 Stream
 ^^^^^^
 
-The `stream <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/stream.ast>`_ module implements a ``Stream`` structure. The ``Stream`` structure allows the developer to turn any list into a stream supporting interface functions like ``peeking`` ahead or ``rewinding`` the stream.  In order
-to construct a stream call the constructor on a list, e.g., ``Stream([1,2,3])``.  The following stream
-interface functions are available,
+The `stream <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/stream.ast>`_ module implements streams that allow
+the developer to turn any list into a stream supporting interface functions like ``peeking`` ahead or ``rewinding`` the stream.
+The following stream interface functions are available,
 
 * Function ``eof`` returns ``true`` if the stream does not contain any further elements for processing. Otherwise it returns ``false``.
-* Function ``peek`` returns the next element available on the stream otherwise it returns ``none``.
-* Function ``next`` returns the next element available on the stream and moves the implicit stream pointer forward.  If the stream is at the ``eof`` then it returns ``none``.
-* Function ``get`` is synonymous to ``peek``.
+* Function ``peek`` returns the current element available on the stream otherwise it returns ``none``.
+* Function ``get`` returns the current element and moves the stream pointer one ahead.
 * Function ``rewind`` resets the stream pointer to the first element of the stream.
 * Function ``map`` applies a given function to each element in the stream.
 * Function ``append``, given ``item``, adds item to the end of the stream.
 * Function ``__string__`` maps a the stream to a string representation.
 
+A simple use case.
+::
+   load system io.
+   load system stream.
+
+   let s = stream @stream([1 to 10]).
+   while not s @ eof() do
+      io @ print (s @get()+" ").
+   end
+   io @println ("").
+   
+
+which outputs::
+
+   1 2 3 4 5 6 7 8 9 10
+
+
 Type
 ^^^^
 
@@ -430,21 +1077,55 @@ The `type <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/module
 
 * Function ``tointeger`` converts a given input to an integer. It can be called with two different arguments,
 
-  #. ``(item:%string,base:%integer)`` where ``base`` is a valid base for integer conversion
-  #. ``item`` where ``item`` is converted to a base 10 integer.
+  1. ``(item:%string,base:%integer)`` where ``base`` is a valid base for integer conversion
+  2. ``item`` where ``item`` is converted to a base 10 integer.
 
 
 * Function ``toreal``, given ``item``, returns the input as a real number data type.
 * Function ``toboolean``, given ``item``, returns the input as a Boolean value of either true or false.
-* Function ``tostring`` converts an Asteroid object to a string. If format values are given, it applies the formatting to the object. It can be called with several different inputs where ``*TP`` indicates a``boolean``, ``integer``, or ``string`` type and ``w`` is the width specification and ``p`` is the precision specification.  When no formatting information is provided a default string conversion occurs,
+* Function ``tostring`` converts an Asteroid object to a string. If format values are given, it applies the formatting to the object. It can be called with several different inputs where ``*TP`` indicates a``boolean``, ``integer``, or ``string`` type and ``w`` is the width specification, ``p`` is the precision specification and ``s`` is the scientific notation flag.  When no formatting information is provided a default string conversion occurs,
 
-  #. ``(v:*TP,stringformat(w:%integer))``
-  #. ``(v:%real,stringformat(w:%integer))``
-  #. ``(v:%real,stringformat(w:%integer,p:%integer))``
-  #. ``item`` - default conversion
+  1. ``(v:*TP,type @stringformat(w:%integer))``
+  2. ``(v:%real,type @stringformat(w:%integer))``
+  3. ``(v:%real,type @stringformat(w:%integer,p:%integer))``
+  4. ``(v:%real,type @stringformat(w:%integer,p:%integer,s:%boolean))``
+  5. ``item`` - default conversion
 
 * Function ``tobase`` represents the given integer ``x`` (*specifically* within the given input ``(x:%integer,base:%integer)``) as a string in the given base.
 
+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 Query Functions*
 
@@ -453,6 +1134,13 @@ The `type <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/module
 * Function ``isnone`` returns ``true`` if given ``item`` is equal to the value ``none``.
 * Function ``gettype`` returns the type of a given ``item`` as an Asteroid string.
 
+A simple example program using the ``gettype`` function,
+::
+   load system type.
+
+   let i = 1.
+   assert(type @gettype(i) == "integer").
+   
 
 Util
 ^^^^
@@ -461,8 +1149,8 @@ The `util <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/module
 
 * Function ``exit`` exits the program. It can be called with two inputs,
 
-  #. ``none``
-  #. ``msg:%string``
+  1. ``none``
+  2. ``msg:%string``
 
 * Function ``copy``, given Asteroid object ``obj``, makes a deep copy of it.
 * Function ``cls`` clears the terminal screen.
@@ -477,12 +1165,25 @@ Vector
 
 The `vector <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/vector.ast>`_ defines functions useful for vector arithmetic. It supports the following functions.  Here ``a`` and ``b`` are vectors implemented as lists,
 
-* Function ``vadd``, given the input ``(a,b)``, returns a vector that contains the element by element sum of the input vectors.
-* Function ``vsub``, given the input ``(a,b)``, returns the element by element difference vector.
-* Function ``vmult``, given the input ``(a,b)``, returns the element by element vector multiplication.
+* Function ``add``, given the input ``(a,b)``, returns a vector that contains the element by element sum of the input vectors.
+* Function ``sub``, given the input ``(a,b)``, returns the element by element difference vector.
+* Function ``mult``, given the input ``(a,b)``, returns the element by element vector multiplication.
 * Function ``dot``, given ``(a,b)``, computes the dot product of the two vectors.
-* Function ``vop``  allows the developer to vectorize an function. It can be called with three different inputs:
+* Function ``op``  allows the developer to vectorize any function. It can be called with three different inputs:
+
+  1. ``(f:%function,a:%list,b:%list)``
+  2. ``(f:%function,a:%list,b if type @isscalar(b))``
+  3. ``(f:%function,a if type @isscalar(a),b:%list)``
+
+Here is a simple example program for the ``vector`` module,
+::
+   load system io.
+   load system vector.
+
+   let a = [1,0].
+   let b = [0,1].
+
+   io @println (vector @dot (a,b)).
+   
 
-  #. ``(f:%function,a:%list,b:%list)``
-  #. ``(f:%function,a:%list,b if isscalar(b))``
-  #. ``(f:%function,a if isscalar(a),b:%list)``
+which prints the value ``0``.
diff --git a/docs/Reference Guide.txt b/docs/Reference Guide.txt
new file mode 100644
index 00000000..9875fbb2
--- /dev/null
+++ b/docs/Reference Guide.txt
@@ -0,0 +1,1005 @@
+/******************************************************************
+  This is the source file from which the reference guide is
+  generated.  We use cpp to insert live code snippets into the
+  document. In order to generate the reference guide run the
+  following command on a Unix-like system in the directory of
+  this doc:
+
+  bash generate_docs
+
+ ******************************************************************/
+#include "header.txt"
+
+.. highlight:: none
+
+Asteroid Reference Guide
+========================
+
+Language Syntax
+---------------
+
+Note: In the following descriptions ``<something>?`` denotes an optional
+something in a piece of syntax.  We also use the notation ``<something>*``
+which means that something can appear zero or more times in a program.
+Capitalized
+words are keywords where ``FOR`` represents the keyword ``for`` and ``END``
+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
+%%%%%
+
+Syntax: ``BREAK '.'?``
+
+The break statement immediately breaks out of the closest surrounding looping structure.
+Execution will continue at the statement right after the loop. Issuing a break statement
+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).
+
+Expressions at the Statement Level
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+Expressions at the statement level are supported.  However, they do not have
+any effect on the computation unless they contain side effects with one
+exception:  In the absence of an explicit return statement, the value of the last expression
+evaluated in a function body is considered the return value of the function.
+
+An example,
+::
+      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.
+
+For-Loop
+%%%%%%%%
+
+Syntax: ``FOR pattern IN exp DO stmt_list END``
+
+In a for-loop the expression must evaluate to a list.  The pattern is then matched to
+each element of the list sequentially starting with the first element of the list.
+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
+
+
+Function-Definition
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: FUNCTION function_name WITH pattern DO stmt_list (WITH pattern DO stmt_list)* END
+
+Function definitions in Asteroid can have one or more function bodies associated
+with single function name.  A function body is associated with a particular pattern
+that is matched against the actual argument of the function call.  If the match
+is successful then the associated function body is executed.  If the match is not
+successful then other pattern/body pairs are tried if present.  If none of the
+patterns match the actual argument then this constitutes a runtime error.
+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
+
+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.
+
+Global
+%%%%%%
+
+Syntax: ``GLOBAL variable_name (',' variable_name)* '.'?``
+
+The ``global`` statement allows the developer to declare a variable as global
+within a function scope and this allows the developer to set the value of a global variable
+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).
+
+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``.
+
+If-Then-Else
+%%%%%%%%%%%%
+
+Syntax: ``IF exp DO stmt_list (ELIF exp DO stmt_list)* (ELSE DO? stmt_list)? END``
+
+If the first expression evaluates to the equivalent of a Boolean ``true`` value
+then the associated statements will be executed and the execution
+continues after the ``end`` keyword.  If the expression evaluates to the equivalent
+of a Boolean ``false`` then the expressions of the optional ``elif`` clauses
+are evaluated if present.  If one of them evaluates to the equivalent of a Boolean
+value ``true`` then the associated statements are executed and execution continues
+after the ``end`` keyword. Otherwise
+the statements of the optional ``else`` clause are executed if present and again
+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
+
+
+Let
+%%%
+
+Syntax: ``LET pattern = exp '.'?``
+
+The ``let`` statement is Asteroid's version of the assignment statement with a twist though:  the left side of the ``=`` sign is not just a variable
+but is considered a pattern.  For simple assignments there is no discernible difference between assignments in Asteroid and assignments in other
+languages,
+::
+  let x = val.
+
+Here, the variable ``x`` will match the value stored in ``val``.  However, because the left side of the ``=`` sign is a pattern we
+can write something like this,
+::
+  load system math.
+  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,
+::
+   let 1 = 1.
+
+which simply states that the value ``1`` on the right can be matched by the pattern ``1`` on the left.  Having the ability to pattern match
+on literals is convenient for statements like these,
+::
+  let (1,x) = p.
+
+This ``let`` statement is only successful for values of ``p`` which are pairs where the first component of the pair is the value ``1``.
+
+
+Loop
+%%%%
+
+Syntax: ``LOOP DO? stmt_list END``
+
+The ``loop`` statement executes the statements in the loop body indefinitely
+unless a ``break`` statement is encountered.
+
+Repeat-Until
+%%%%%%%%%%%%
+
+Syntax: ``REPEAT DO? stmt_list UNTIL exp '.'?``
+
+Repeatedly execute the statements in the loop body until the
+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 [].
+
+
+Return
+%%%%%%
+
+Syntax; ``RETURN exp? '.'?``
+
+Explicitly return from a function with an optional return value.
+
+Structure
+%%%%%%%%%
+
+Syntax: ``STRUCTURE type_name WITH data_or_function_stmts END``
+
+The ``structure`` statement introduces a composite data type that defines a physically grouped list of variables under one name.  The variables within a structure can be declared as data members or as function members.
+Unless a member function was declared as a constructor (an ``__init__`` function) structures are
+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
+
+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
+      end
+
+      let betty = Person("Betty",21).  -- call constructor
+      assert( betty @name == "Betty" ).
+      assert( betty @age == 21 ).
+
+Also note that object identity is expressed using the ``this`` keyword.
+
+Try-Catch
+%%%%%%%%%
+
+Syntax: ``TRY DO? stmt_list (CATCH pattern DO stmt_list)+ END``
+
+This statement allows the programmer to set up exception handlers for
+exceptions thrown in the code of the ``try`` part of the statement.
+Notice that you can set up one or more handlers within the ``catch`` part of
+the statement.  If there are more than one handlers then they are searched in
+order starting with the first.  Handlers are selected via pattern matching
+on the exception object.  The handler code of the first ``catch`` clause whose
+pattern matches the exception object is executed.
+
+Below is an example of a ``try-catch`` statement where the code
+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
+
+For more details on exceptions please see the User Guide.
+
+Throw
+%%%%%
+
+Syntax: ``THROW exp '.'?``
+
+Allows the developer to throw an exception.  Any object can serve as an
+exception object. However, Asteroid provides some predefined exception objects.
+For more details on exceptions please see the User Guide.
+
+While-Loop
+%%%%%%%%%%
+
+Syntax: ``WHILE exp DO stmt_list END``
+
+While the expression evaluates to the equivalent of a Boolean ``true`` value
+execute the statements in the body of the loop.  The loop expression is reevaluated
+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.
+
+      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
+^^^^^^^^^^^
+
+All the usual arithmetic, relational, and logic operators,
+::
+      +, -, *, /, ==, =/=, <=, <, >=, >, and, or, not
+
+are supported in
+Asteroid.  For extended mathematical operations such as ``mod`` (modulus) or
+``sin`` (sine) see the ``math`` module.  Here we discuss expression constructions
+that are particular to Asteroid.
+
+Substructure Access
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``structure_exp @ index_exp``
+
+Asteroid provides the uniform substructure access operator ``@`` for all structures
+which includes lists, tuples, and objects. For example, accessing the first
+element of a list is accomplished by the expression,
+::
+      [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
+
+
+Head-Tail Operator
+%%%%%%%%%%%%%%%%%%
+
+Syntax: ``element_exp | list_exp``
+
+This operator works in one of two ways.  In the first way it allows you to
+pre-append an element to a list,
+::
+      let [1,2,3] = 1 | [2,3].
+
+It can also be nested,
+::
+      let [1,2,3] = 1 | 2 | 3 | [].
+
+In the second way it works as a pattern to deconstruct a list into its first
+element and the remainder of the list, the list with its first element removed,
+::
+      let h | t = [1,2,3].
+      assert(h == 1).
+      assert(t == [2,3]).
+
+You can put optional brackets around the operator to highlight the fact that
+we are dealing with a list,
+::
+      let [h | t] = [1,2,3].
+
+The ``is`` Predicate
+%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``exp IS pattern``
+
+This operator matches the structure computed by the expression on the left
+side against the pattern on the right side of the operator.  If the match is
+successful it returns the Boolean value ``true`` and if not successful then
+it returns the Boolean value ``false``.  All regular rules of pattern matching
+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".
+      end
+
+The ``in`` Predicate
+%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``exp IN list_exp``
+
+This predicate returns ``true`` if the value computed by the expression on the
+left in contained in the list computed by the list expression on the right.
+It is an error if the expression on the right does not compute a list.
+
+Example,
+::
+      let true = 1 in [1,2,3].
+
+List Comprehensions
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``start_exp TO end_exp (STRIDE exp)?``
+
+This expression constructs a list starting with an element given by the start expression
+up to the value of the end expression with a given stride.  If the stride expression
+is not given then a stride value of 1 is assumed.  The stride value is always a
+positive value.  The comprehension figures out how to apply the stride value to reach the
+end value from the start value.  The comprehension can be placed between optional square brackets.
+
+Examples,
+::
+      let [0,1,2,3,4] = 0 to 4.
+      let [0,-2,-4,-6] = [0 to -6 stride 2].
+
+Function Calls
+%%%%%%%%%%%%%%
+
+Syntax: ``exp exp``
+
+Function calls are defined by function application, more specifically by
+juxtaposition of expressions.  Here, the first expression has to evaluated to
+a function expression and the second expression has to evaluate to an appropriate
+actual function parameter.  Notice that function calls are defined in terms of a
+single function parameter.  If you would like to pass more than one value to a
+function then you have to create a tuple.  For example, if the function ``foo``
+needs two values to be passed to it then you need to create a tuple, e.g. ``foo (1,2)``.
+In that respect function calls differ drastically from function calls in languages
+like C/C++ or Python.
+
+Examples,
+::
+      let val = (lambda with i do i+1) 1.
+      assert(val == 2).
+
+      function foo with (q,p) do q+p end
+      let val = foo (1,2).
+      assert(val == 3).
+
+If-Else Expressions
+%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``then_exp IF bool_exp ELSE else_exp``
+
+If the boolean expression evaluates to true then this expression returns
+the value of the first expression.  Otherwise it will return the value of the
+last expression.
+
+Example,
+::
+      let val = "yup" if b else "nope".
+
+If ``b`` evaluates to true then this expression returns the string ``"yup"``
+otherwise it returns the string ``"nope"``.
+
+First-Class Patterns
+%%%%%%%%%%%%%%%%%%%%
+
+| Syntax: ``PATTERN exp``
+| Syntax: ``* exp``
+
+This construction allows the user to construct a pattern as a value using
+the ``pattern`` keyword.  The advantage of patterns as values is that they
+can be stored in variables or passed to or from functions.  As an example
+we construct a pattern which is a pair where the first component is the constant
+``1`` and the second component is the variable ``x`` and we store this pattern
+in the variable ``p`` for later use,
+::
+      let p = pattern (1,x).
+
+The pattern derefence operator ``*`` allows us to retrieve patterns from
+variables, e.g.
+::
+      let *p = (1,2).
+
+Here the pair ``(1,2)`` is matched against the pattern stored in the variable ``p``
+such that ``x`` is bound to the value ``2``.
+
+Type Patterns
+%%%%%%%%%%%%%
+
+Syntax: ``'%'type_name``
+
+Type patterns match all the values of a particular type.  Type patterns exist
+for all the Asteroid builtin types and are also available for user defined
+types introduced via a ``structure`` command.
+
+Example,
+::
+      let true = 1 is %integer.
+
+Named Patterns
+%%%%%%%%%%%%%%
+
+Syntax: ``name_exp ':' pattern``
+
+Named patterns allow you to bind the term matched by the pattern to a variable.
+Here the name expression has to evaluate to something that looks like a variable,
+object member variable, or array location.
+
+Example,
+::
+      let x:%integer = val.
+
+The variable ``x`` will be bound to the value of ``val`` if that value matches the
+type pattern ``%integer``.
+
+Conditional Patterns
+%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``pattern IF cond_exp``
+
+In conditional patterns the pattern only matches if the condition expression
+evaluates to true.
+
+Example,
+::
+      load system math.
+      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
+%%%%%%%%%%%%%%%%%%%%%%%%
+
+Syntax: ``%[ pattern ]%``
+
+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
+by placing it between the ``%[`` and ``]%`` operators.
+
+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.
+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.
+
+Asteroid Grammar
+^^^^^^^^^^^^^^^^
+
+The following is the complete grammar for the Asteroid language. Capitalized
+words are either keywords such as ``FOR`` and ``END`` or tokens such as ``STRING`` and ``ID``.  Non-terminals
+are written in all lowercase letters.  The grammar utilizes an extended BNF notation
+where ``<syntactic unit>*`` means zero or more occurrences of the syntactic unit and
+``<syntactic unit>+`` means one or more occurrences of the syntactic unit. Furthermore,
+``<syntactic unit>?`` means that the syntactic unit is optional.  Simple terminals
+are written in quotes.
+::
+#include "/tmp/grammar.tmp"
+
+
+Builtin Functions
+-----------------
+
+* Function ``len``, when given an input value, returns the length of that input. The
+  function can only be applied to lists, strings, tuples, or structures.
+
+* Function ``hd``, when given a list as input returns the first element of that list.
+  It is an error to apply this function to an empty list.
+
+* Function ``tl``, when given a list as input returns the rest of the list without the first element.
+  It is an error to apply this function to an empty list.
+
+* Function ``range`` will compute a list of values depending on the input values:
+
+  1. ``(start:%integer,stop:%integer)`` returns list ``[start to stop-1]``.
+  2. ``(start:%integer,stop:%integer,inc:%integer)`` returns list ``[start to stop-1 stride inc]``.
+  3. ``(stop:%integer)`` returns list ``[0 to stop-1]``.
+
+* Function ``getid`` returns the id (physical memory address) of any Asteroid object as an Asteroid integer.
+
+* Function ``isdefined`` returns true if a variable or type name is defined in the
+  current environment otherwise it returns false. The variable or type name must be given as a string.
+
+List and String Objects
+-----------------------
+
+In Asteroid, both ``lists`` and ``strings,`` are treated like objects. Due to this, they have member functions that can manipulate the contents of those objects.
+
+Lists
+^^^^^
+
+A **list** is a structured data type that consists of square brackets enclosing
+comma-separated values.
+Member functions on lists can be called on the data structure directly, e.g.::
+
+   [1,2,3] @length()
+
+* Function ``length`` returns the number of elements within that list.
+* Function ``append``, given ``(item)``, adds that item to the end of a list.
+* Function ``extend``, given ``(item)``, will extend the list by adding all the items from the item where ``item`` is either a list, a string or a tuple.
+* Function ``insert``, given ``(ix:%integer,item)``, will insert an item at a given position. The first argument is the index of the element before which to insert, so ``a@insert(0, x)`` inserts at the front of the list, and ``a@insert(a@length(), x)`` is equivalent to ``a@append(x)``.
+* Function ``remove``, given ``(item)``, removes the first element from the list whose value is equal to ``(item)``. It raises a ValueError if there is no such item.
+* Function ``pop``, given ``(ix:%integer)``, removes the item at the given position in the list and returns it. If no index is specified,``a@pop()`` removes and returns the last item in the list.
+* Function ``clear``, given ``(none)``, removes all items from the list.
+* Function ``index`` returns a zero-based index in the list of the first element whose value is equal to ``(item)``. It raises a ValueError exception if there is no such item. The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular subsequence of the list. The returned index is computed relative to the beginning of the full sequence rather than the ``(startix)`` argument.   This function can be called with several input configurations:
+
+  1. ``(item,loc(startix:%integer,endix:%integer))``
+  2. ``(item,loc(startix:%integer))``
+  3. ``item``
+
+* Function ``count``, given ``(item)``, returns the number of times ``(item)`` appears in the list.
+* Function ``sort`` sorts the items of the list in place. It can be called with several different inputs:
+
+  1. ``(reverse:%boolean)`` if the boolean is set to true then the sorted list is reversed.
+  2. ``none`` returns the reverse list.
+
+* Function ``reverse``, reverses the elements of the list in place.
+* Function ``copy``, makes a shallow copy of the list.
+* Function ``shuffle``, returns a random permutation of a given list - in place!
+* Function ``map``, given ``(f:%function)``, applies ``f`` to each element of the list in place. The modified list is returned.
+* Function ``reduce`` reduces the value of elements in a list. This
+  function can be called with several different inputs:
+
+  1. Input ``(f:%function)`` returns ``value``, such that ``value = f(value,this@i)``.
+  2. Input ``(f:%function,init)`` returns the same format but uses ``init`` as an initial value.
+
+  The first argument to ``f`` is the accumulator.
+
+* Function ``filter``, given ``(f:%function)``, constructs an output list from those elements of the list for which ``f`` returns true. If ``f`` is none, the identity function is assumed, that is, all elements of the input list that are false are removed.
+* Function ``member``, given ``(item)``, returns true only if ``item`` exists on the list.
+* Function ``join``, given ``(join:%string)``, turns the list into a string using ``join`` between the elements.  The string is returned
+  as the return value from this function.
+
+
+See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_ for more on all the functions above.
+
+
+Strings
+^^^^^^^
+
+A string is a sequence of characters that can be used as a variable or a literal constant.
+Similar to lists the member functions of strings can be called directly on the
+data structure itself, e.g.::
+
+   "Hello there" @length()
+
+* Function ``length`` returns the number of characters within that string.
+* Function ``explode``, turns a string into a list of characters.
+* Function ``trim``, given the input ``(what:%string)``, returns a copy of the string with the leading and trailing characters removed. The ``what`` argument is a string specifying the set of characters to be removed. If omitted or none, the ``what`` argument defaults to removing whitespace. The ``what`` argument is not a prefix or suffix; rather, all combinations of its values are stripped.
+* Function ``replace`` will return a copy of the string with all occurrences of regular expression pattern ``old`` replaced by the string ``new``. If the optional argument count is given, only the first count occurrences are replaced. It can be called with several different inputs:
+
+  * ``(old:%string,new:%string,count:%integer)``
+  * ``(old:%string,new:%string)``
+
+* Function ``split`` will return a list of the words in a given string, using ``sep`` as the delimiter string. If ``maxsplit`` is given: at most maxsplit splits are done (thus, the list will have at most maxsplit+1 elements). If maxsplit is not specified or -1, then there is no limit on the number of splits (all possible splits are made).
+  If ``sep`` is given, consecutive delimiters are not grouped together and are deemed to delimit empty strings (for example, ``"1,,2"@split(",")`` returns ``["1", "", "2"]``). The ``sep`` argument may consist of multiple characters (for example, ``"1<>2<>3"@split("<>")`` returns ``["1", "2", "3"]``). Splitting an empty string with a specified separator returns ``[""]``.
+  If ``sep`` is not specified or is None, a different splitting algorithm is applied: runs of consecutive whitespace are regarded as a single separator, and the result will contain no empty strings at the start or end if the string has leading or trailing whitespace. Consequently, splitting an empty string or a string consisting of just whitespace with a None separator returns ``[]``.
+  Function ``split`` can be called with several different inputs:
+
+  1. Input ``(sep:%string,count:%integer)``
+  2. Input ``(sep:%string)``
+  3. Input ``(none)``
+
+* Function ``toupper``, converts all the lowercase letters in a string to uppercase.
+* Function ``tolower``, converts all the uppercase letters in a string to lowercase.
+* Function ``index`` allows the user to search for a given ``item`` in a list. It returns an integer index into the string or ``none`` if ``item`` was not found.  The optional argument ``loc`` allows you to specify ``(startix)`` and ``(endix)`` and are used to limit the search to a particular substring of the string. The returned index is computed relative to the beginning of the full string rather than the ``(startix)`` argument.The function can be called with several different inputs:
+
+  1. Input ``(item:%string,loc(startix:%integer,endix:%integer))``
+  2. Input ``(item:%string,loc(startix:%integer))``
+  3. Input ``(item:%string)``
+
+* Function ``flip`` reverses a string.
+
+See the `Prologue module <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/prologue.ast>`_  for more on all the functions above.
+
+
+Asteroid Modules
+----------------
+
+There are a number of system modules that can be loaded into an Asteroid program using ``load system <module name>``.
+The modules are implemented as objects where all the functions of that module are
+member functions of that module object. For example, in the case of the ``io`` module
+we have ``println`` as one of the member functions.  To call that function::
+
+   load system io.
+   io @println "Hello there!".  -- println is a member function of the io module
+
+Bitwise
+^^^^^^^
+
+The `bitwise <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/bitwise.ast>`_ module defines Bitwise operations. It supports the following functions,
+
+* Function ``band`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise AND operation.
+* Function ``bor`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise OR operation.
+* Function ``bnot`` can be called with the input ``(x:%integer)``, and performs the Bitwise NOT operation.
+* Function ``bxor`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise XOR operation.
+* Function ``blshift`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise left shift operation.
+* Function ``brshift`` can be called with the input ``(x:%integer, y:%integer)``, and performs the Bitwise right shift operation.
+* Function ``blrotate`` can be called with the input ``(x:%integer, i:%integer)``, and performs the Bitwise left rotate operation.
+* Function ``brrotate`` can be called with the input ``(x:%integer, i:%integer)``, and performs the Bitwise right rotate operation.
+* Function ``bsetbit`` can be called with the input ``(x:%integer, i:%integer)``, and sets the ith bit.
+* Function ``bclearbit`` can be called with the input ``(x:%integer, i:%integer)``, and clears the ith bit.
+* Function ``bsize``can be called with the input ``(x:%integer)``, and returns the bit size.
+
+Hash
+^^^^
+
+The `hash <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/hash.ast>`_ module implements a hash for name-values pairs. It supports the following functions,
+
+* Function ``insert``, given the input ``(name,value)``, will insert a given name-value pair into the table.
+* Function ``get``, given ``name``, will return the ``value`` associated with the given ``name`` as long as it can be found otherwise an exception will be thrown.
+* Function ``aslist`` returns the hash as a list of name-value pairs.
+
+IO
+^^
+
+The `io <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/io.ast>`_ module implements Asteroid's I/O system. The module defines three default streams,
+
+1. ``__STDIN__`` - the standard input stream.
+2. ``__STDOUT__`` - the standard output stream.
+3. ``__STDERR__`` - the standard error stream.
+
+Furthermore, the module supports the following functions,
+
+* Function ``println`` can be called with ``item``, and prints a given argument to the terminal (``__STDOUT__``) with an implicit newline character.
+* Function ``print`` can be called with ``item``, and prints a given argument. No implicit newline is appended to the output.
+* Function ``input`` can be called with a string ``prompt``.  If ``prompt`` is given it is printed and then input is read from the terminal (``__STDIN__``) and returned as a string.
+* Function ``open`` opens a file. Given ``(name:%string, mode:%string)``, it returns a file descriptor of type ``FILE``. The ``mode`` string can be ``"r"`` when the file will only be read, ``"w"`` for only writing (an existing file with the same name will be erased), and ``"a"`` opens the file for appending; any data written to the file is automatically added to the end. The ``"r+"`` opens the file for both reading and writing.
+* Function ``close``, given ``file:%FILE``, closes that file.
+* Function ``read``, given ``file:%FILE``, reads a file. If no file is given the ``__STDIN__`` stream is read.
+* Function ``readln``, given ``file:%FILE``, reads a given line of input from the file. If no file is given the ``__STDIN__`` stream is read.
+* Function ``write``, given ``(file:%FILE, what:%string)``, will write ``what`` to the given ``file``.  If ``file`` is not given then it writes to the ``__STDOUT__`` stream.
+* Function ``writeln``, works the same way as ``write`` except that it appends a newline character to the output.
+
+Math
+^^^^
+
+The `math <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/math.ast>`_ module implements mathematical constants and functions. It supports the following functions,
+
+*Power and logarithmic functions*
+
+* Function ``exp``, given ``x:%integer``, returns e raised to the power ``x``, where e = 2.718281… is the base of natural logarithms.
+* Function ``log`` can be called with two different argument setups,
+
+  1. If only one argument, ``(x)``, is input, this returns the natural logarithm of x (to base e).
+  2. If two arguments, ``(x,base)``, are input, this returns the logarithm of x to the given base, calculated as log(x)/log(base).
+
+* Function ``pow``, given ``(b,p:%integer)``, returns "b <sup>p</sup>" as long as b is either ``real`` or ``integer``.
+* Function ``sqrt``, given ``a``, returns its square root as long as ``a`` is either ``real`` or ``integer``.
+
+*Number-theoretic and representation functions*
+
+* Function ``abs``, given ``x``, returns its absolute value.
+* Function ``ceil``, given ``x:%real``, returns the ceiling of x: the smallest integer greater than or equal to x.
+* Function ``floor``, given ``x:%real``, returns the floor of x: the largest integer less than or equal to x.
+* Function ``gcd``, given ``(a:%integer,b:%integer)``, returns the greatest common denominator that both integers share.
+* Function ``isclose`` can be called with two different argument setups,
+
+  1. With input values ``(a,b)``, it returns returns ``true`` if the two values are close to each other and ``False`` otherwise. Default tolerance 1e-09.
+  2. With input values ``(a,b,t)``, it compares ``a`` and ``b`` with tolerance ``t``.
+
+* Function ``mod``, given ``(v,d)``, will return the remainder of the operation ``v/d``, as long as ``v`` and ``d`` are either ``real`` or ``integer`` values.
+
+*Trigonometric functions*
+
+* Function ``acos``, given ``x``, returns the arc cosine of x in radians. The result is between 0 and pi.
+* Function ``asin``, given ``x``, returns the arc sine of x in radians. The result is between -pi/2 and pi/2.
+* Function ``atan``, ,given ``x``, returns the arc tangent of x in radians. The result is between -pi/2 and pi/2.
+* Function ``cos``, given ``x``, returns the cosine of x radians.
+* Function ``sin``, given ``x``, returns the sine of x radians.
+* Function ``tan``, given ``x``, returns the tangent of x radians.
+* Function ``acosh``, given ``x``, returns the inverse hyperbolic cosine of x.
+* Function ``asinh``, given ``x``, returns the inverse hyperbolic sine of x.
+* Function ``atanh``, given ``x``, returns the inverse hyperbolic tangent of x.
+* Function ``cosh``, given ``x``, returns the hyperbolic cosine of x.
+* Function ``sinh``, given ``x``, returns the hyperbolic sine of x.
+* Function ``tanh``, given ``x``, returns the hyperbolic tangent of x.
+* Function ``degrees``, given ``x``, converts angle ``x`` from radians to degrees.
+* Function ``radians``,  given ``x``, converts angle ``x`` from degrees to radians.
+
+An example,
+::
+#include "../asteroid/test-suites/ref-programs/math.ast"
+
+Pick
+^^^^
+
+The `pick <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/pick.ast>`_ module implements
+pick objects that allow a user to randomly pick items from a list using the ``pick`` function.
+The ``pick`` function can be called with ``n:%integer`` and returns a list of ``n`` randomly picked objects from the object list.
+Here is a simple use case
+::
+#include "../asteroid/test-suites/ref-programs/pick.ast"
+
+
+Random
+^^^^^^
+
+The `random <https://github.com/lutzhamel/asteroid/blob/master/asteroid/modules/random.ast>`_ module implements the ``random`` numbers. Using the functions included in this module will return a random value within a given range or interval. It supports the following functions,
+
+* Function ``random``, given the input ``none``, returns a random floating point number in the range ``[0.0, 1.0)``.
+* Function ``randint`` returns a random value N in the interval lo <= N <= hi. The exact random value output depends on the types of the values specifying the interval. It can be called with two different number interval inputs:
+
+  1. ``(lo:%integer,hi:%integer)``
+  2. ``(lo:%real,hi:%real)``
+  3. Note: any other interval specification will instead output an error message for "unsupported interval specification in randint."
+
+* Function ``seed``, given ``(sd:%integer)``, provides a seed value for the random number generator.
+
+Set
+^^^
+
+The `set <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/set.ast>`_ module implements Asteroid sets as lists. Unlike lists, sets do not have repeated members. It supports the following functions,
+
+* Function ``toset``, given ``(lst:%list)``, converts the input list into a set.
+* Function ``diff``, given ``(a:%list,b:%list)``, computes the difference set between the two set ``a`` and ``b``.
+* Function ``intersection``, given ``(a:%list,b:%list)``, finds the intersection between  sets ``a`` and ``b``.
+* Function ``union``, given ``(a:%list,b:%list)``, computes the union of sets ``a`` and ``b``.
+* Function ``xunion``, given ``(a:%list,b:%list)``, returns all elements in ``a`` or ``b``, but not in both.
+
+Sort
+^^^^
+
+The `sort <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/sort.ast>`_ module
+defines a parameterized ``sort`` function over a list.
+The ``sort`` function makes use of a user-defined order predicate on the list's elements to
+perform the sort. The ``Quicksort`` is the underlying sort algorithm.
+The following is a simple example,
+::
+#include "../asteroid/test-suites/ref-programs/sort.ast"
+
+prints the sorted list::
+
+  [5,10,50,110]
+
+Stream
+^^^^^^
+
+The `stream <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/stream.ast>`_ module implements streams that allow
+the developer to turn any list into a stream supporting interface functions like ``peeking`` ahead or ``rewinding`` the stream.
+The following stream interface functions are available,
+
+* Function ``eof`` returns ``true`` if the stream does not contain any further elements for processing. Otherwise it returns ``false``.
+* Function ``peek`` returns the current element available on the stream otherwise it returns ``none``.
+* Function ``get`` returns the current element and moves the stream pointer one ahead.
+* Function ``rewind`` resets the stream pointer to the first element of the stream.
+* Function ``map`` applies a given function to each element in the stream.
+* Function ``append``, given ``item``, adds item to the end of the stream.
+* Function ``__string__`` maps a the stream to a string representation.
+
+A simple use case.
+::
+#include "../asteroid/test-suites/ref-programs/stream.ast"
+
+which outputs::
+
+   1 2 3 4 5 6 7 8 9 10
+
+
+Type
+^^^^
+
+The `type <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/type.ast>`_ module defines type related functions and structures.
+
+*Type Conversion*
+
+* Function ``tointeger`` converts a given input to an integer. It can be called with two different arguments,
+
+  1. ``(item:%string,base:%integer)`` where ``base`` is a valid base for integer conversion
+  2. ``item`` where ``item`` is converted to a base 10 integer.
+
+
+* Function ``toreal``, given ``item``, returns the input as a real number data type.
+* Function ``toboolean``, given ``item``, returns the input as a Boolean value of either true or false.
+* Function ``tostring`` converts an Asteroid object to a string. If format values are given, it applies the formatting to the object. It can be called with several different inputs where ``*TP`` indicates a``boolean``, ``integer``, or ``string`` type and ``w`` is the width specification, ``p`` is the precision specification and ``s`` is the scientific notation flag.  When no formatting information is provided a default string conversion occurs,
+
+  1. ``(v:*TP,type @stringformat(w:%integer))``
+  2. ``(v:%real,type @stringformat(w:%integer))``
+  3. ``(v:%real,type @stringformat(w:%integer,p:%integer))``
+  4. ``(v:%real,type @stringformat(w:%integer,p:%integer,s:%boolean))``
+  5. ``item`` - default conversion
+
+* Function ``tobase`` represents the given integer ``x`` (*specifically* within the given input ``(x:%integer,base:%integer)``) as a string in the given base.
+
+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 Query Functions*
+
+* Function ``islist`` returns ``true`` if given ``item`` is a list otherwise it will return ``false``.
+* Function ``isscalar`` returns ``true`` if given ``item`` is either an integer or a real value.
+* Function ``isnone`` returns ``true`` if given ``item`` is equal to the value ``none``.
+* Function ``gettype`` returns the type of a given ``item`` as an Asteroid string.
+
+A simple example program using the ``gettype`` function,
+::
+#include "../asteroid/test-suites/ref-programs/type.ast"
+
+Util
+^^^^
+
+The `util <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/util.ast>`_ module defines utility functions and structures that don't really fit into any omodules. It supports the following functions,
+
+* Function ``exit`` exits the program. It can be called with two inputs,
+
+  1. ``none``
+  2. ``msg:%string``
+
+* Function ``copy``, given Asteroid object ``obj``, makes a deep copy of it.
+* Function ``cls`` clears the terminal screen.
+* Function ``sleep``,  programs sleep for ``secs`` seconds where the argument ``secs`` is either an integer or real value.
+* Function ``zip``, given ``(list1:%list,list2:%list)``, will return a list where element ``i`` of the list is the tuple ``(list1@i,list2@i)``.
+* Function ``unzip``, given a list of pairs will return a pair of lists where the first component of the pair is the list of all the first components of the pairs of the input list and the second component of the return list is a list of all the second components of the input list.
+* Function ``ascii``, given a character ``item:%string``, returns the corresponding ASCII code of the first character of the input string.
+* Function ``achar``, given a decimal ASCII code ``item:%integer``, returns the corresponding character symbol.
+
+Vector
+^^^^^^
+
+The `vector <https://github.com/asteroid-lang/asteroid/blob/master/asteroid/modules/vector.ast>`_ defines functions useful for vector arithmetic. It supports the following functions.  Here ``a`` and ``b`` are vectors implemented as lists,
+
+* Function ``add``, given the input ``(a,b)``, returns a vector that contains the element by element sum of the input vectors.
+* Function ``sub``, given the input ``(a,b)``, returns the element by element difference vector.
+* Function ``mult``, given the input ``(a,b)``, returns the element by element vector multiplication.
+* Function ``dot``, given ``(a,b)``, computes the dot product of the two vectors.
+* Function ``op``  allows the developer to vectorize any function. It can be called with three different inputs:
+
+  1. ``(f:%function,a:%list,b:%list)``
+  2. ``(f:%function,a:%list,b if type @isscalar(b))``
+  3. ``(f:%function,a if type @isscalar(a),b:%list)``
+
+Here is a simple example program for the ``vector`` module,
+::
+#include "../asteroid/test-suites/ref-programs/vector.ast"
+
+which prints the value ``0``.
diff --git a/docs/Asteroid User Guide.rst b/docs/User Guide.rst
similarity index 68%
rename from docs/Asteroid User Guide.rst
rename to docs/User Guide.rst
index 8f7490ad..66157b84 100644
--- a/docs/Asteroid User Guide.rst
+++ b/docs/User Guide.rst
@@ -1,3 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+..
+   *** DO NOT EDIT; MACHINE GENERATED ***
+
 .. highlight:: none
 
 Asteroid User Guide
@@ -7,7 +24,7 @@ Introduction
 ------------
 
 Asteroid is a multi-paradigm programming language supporting first-class patterns.
-The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_, and makes pattern matching one of its core computational mechanisms.  This is often called *pattern-matching oriented programming*. When we talk about pattern matching we mean structural pattern matching
+The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_, and makes pattern matching one of its core computational mechanisms.  We often refer to this as pattern-matching oriented programming. When we talk about pattern matching we mean structural pattern matching
 as well as regular expression matching.
 
 In this document we describe the major features of Asteroid and give plenty of examples.  If you have used a programming language like Python or JavaScript before, then Asteroid should appear very familiar.  However, there are some features which differ drastically from other programming languages due to the core pattern-matching programming
@@ -29,8 +46,8 @@ 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 with (x:%integer) if x > 0.
-    let NEG_INT = pattern with (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
@@ -79,11 +96,11 @@ Asteroid supports two more data types:
 * ``list``
 * ``tuple``
 
-These are **structured data types** in that they can contain entities of other data types. Both of these data types have the probably familiar constructors which are possibly empty squences of comma separated values enclosed by square brackets for lists, e.g. ``[1,2,3]``, and enclosed by parentheses for tuples, e.g. ``(x,y)``. For tuples we have the caveat that the 1-tuple is represented by a value followed by a comma to distinguish it from parenthesized expressions, e.g.``(3,)``.
+These are **structured data types** in that they can contain entities that belong to other data types. Both of these data types have constructors which are possibly empty sequences of comma separated values enclosed by square brackets for lists, e.g. ``[1,2,3]``, and enclosed by parentheses for tuples, e.g. ``(x,y)``. For tuples we have the caveat that the 1-tuple is represented by a value followed by a comma to distinguish it from parenthesized expressions, e.g. ``(3,)``.
 Here are some examples,
 ::
-    let a = [1,2,3].  -- this is a list
-    let c = (1,2,3).  -- this is a tuple
+    let l = [1,2,3].  -- this is a list
+    let t = (1,2,3).  -- this is a tuple
 
 As we said above, in order to distinguish it from a parenthesized value the single element in a 1-tuple has to be followed by a comma, like so,
 ::
@@ -97,16 +114,19 @@ Lists and tuples themselves are also embedded in type hierarchies, although very
 That is, any list or tuple can be viewed as a string.  This is very convenient for printing lists and tuples,
 ::
     load system io.
-    println ("this is my list: " + [1,2,3]).
+    io @println ("this is my list: " + [1,2,3]).
 
 
 Finally, Asteroid supports one more type, namely the ``none`` type.  The ``none`` type has
-only one member: A constant named conveniently ``none``.  The null-tuple belongs to this type (rather than the tuple type discussed earlier) and therefore the constant ``()`` can often be used as a convenient short hand for the constant ``none``.  That is, the following ``let`` statements will succeed,
+only one member: A constant named ``none``.  However, it turns out that the null-tuple, a tuple with no components
+indicated by ``()``, also belongs to this type rather than the tuple type discussed earlier. But the ``none``
+data type only has one constant, this implies that ``()`` and ``none`` mean the same thing and can be used
+interchangeably.  That is, the following ``let`` statements will succeed,
 ::
     let none = ().
     let () = none.
 
-meaning that the constants ``()`` and ``none`` are equivalent and pattern-match each other.
+showing that ``()`` and ``none`` are equivalent and pattern-match each other.
 The ``none`` data type itself does not belong to any type hierarchy.
 
 By now you probably figured out that statements are terminated with a period and that comments start with a ``--`` symbol and continue till the end of the line.  You probably also figured out that the ``let`` statement is Asteroid's version of assignment even though the underlying mechanism is a bit different.
@@ -117,46 +137,60 @@ Data Structures
 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 the list reversal example from above as an executable Asteroid program. So go ahead and experiment!
+In Asteroid the ``list`` is a fundamental, built-in data structure.  A trait it shares with programming languages such as Lisp, Python, ML, and Prolog.  Below is a list reversal example program.  Notice that lists are zero-indexed and
+elements of a list are accessed via the ``@`` operator,
 ::
     load system io.    -- load the io module so we can print
 
-    let a = [1,2,3].     -- construct list a
-    let b = a @[2,1,0].  -- reverse list a
-    println b.
+    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]``.
 
-In Asteroid lists are considered objects with member functions that can manipulate the list
-object, e.g. ``[1,2,3] @ reverse()``. We could rewrite the above example as,
+We can achieve the same effect by giving a list of index values (a slice) to the ``@`` operator,
+::
+    load system io.    -- load the io module so we can print
+
+    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.
+
+In Asteroid lists are considered objects with member functions that can manipulate list
+objects. We could rewrite the above example as,
 ::
     load system io.
 
     let a = [1,2,3].
-    let b = a @reverse().
-    println b.
+    let b = a @reverse(). -- reverse list using member function 'reverse'
+    io @println b.
 
-For a full list of available member functions for Asteroid lists please see the reference guide.
+The ``@`` operator allows you to access either individual elements, slices, or member functions of a list.
+Actually, the ``@`` operator is more general than that, it is Asteroid's substructure access operator.
+Notice that in order to access the ``println`` function of the ``io`` module we also use the ``@`` operator.
+This is because in Asteroid, **system modules are objects**, so you must use the ``@`` to access the functions
+of the module.
 
-As we have seen, the ``@`` operator allows you to access either individual elements, slices, or member functions of a list.
+For a comprehensive treatment of available member functions for Asteroid lists please see the reference guide.
 
 Besides using the default constructor for lists which consists of the
 square brackets enclosing a list of elements we can use **list comprehensions** to construct lists.  In Asteroid a list comprehension consist of a range specifier together with
-a step specifier allowying you to generate integer values within that range,
+a stride specifier allowing you to generate integer values within that range,
 ::
     load system io.
 
     -- build a list of odd values
-    let a = [1 to 10 step 2].  -- list comprehension
-    println ("list: " + a).
+    let a = [1 to 10 stride 2].  -- list comprehension
+    io @println ("list: " + a).
 
     -- reverse the list using a slice computed as comprehension
-    let slice = [4 to 0 step -1]. -- list comprehension
+    let slice = [4 to 0 stride 1]. -- list comprehension
     let b = a @slice.
-    println ("reversed list: " + b).
+    io @println ("reversed list: " + b).
 
 The output is,
 ::
+
     list: [1,3,5,7,9]
     reversed list: [9,7,5,3,1]
 
@@ -167,13 +201,14 @@ a list of alternating 1 and -1,
     load system io.
     load system math.
 
-    let a = [1 to 10] @map(lambda with x do return mod(x,2))
+    let a = [1 to 10] @map(lambda with x do return math @mod(x,2))
                       @map(lambda with x do return 1 if x else -1).
 
-    println a.
+    io @println a.
 
 where the output is,
 ::
+
     [1,-1,1,-1,1,-1,1,-1,1,-1]
 
 Higher dimensional arrays can easily be simulated with lists of lists,
@@ -187,62 +222,87 @@ Higher dimensional arrays can easily be simulated with lists of lists,
 
     -- modify an element in the array
     let b @1 @1 = 0.
-    println b.
+    io @println ("["+b@0+"\n "+b@1+"\n "+b@2+"]").
 
-The output is: ``[[1,2,3],[4,0,6],[7,8,9]]``
+The output is,
+::
+    [[1,2,3]
+     [4,0,6]
+     [7,8,9]]
 
-**NOTE**: At this point slicing is not supported on the left side of a ``let`` statement.
 
 Tuples
 ^^^^^^
 
 As we saw earlier, the ``tuple`` is another fundamental, built-in data structure that can be found in Asteroid.
-
 Below is an example of a tuple declaration and access.
 ::
-    load system io.   -- load the io module so we can print
     let a = (1,2,3).    -- construct tuple a
     let b = a @1.       -- access the second element in tuple a
-    println b.          -- print the element to the console
+    assert(b == 2).     -- assert that the value of the second element is correct
 
-Like ``lists``, ``tuples`` may also be nested,
+Lists and tuples may be nested,
 ::
-    load system io.
-    -- build a 2-D array
-    let b = (("a","b","c"),
+    -- build a list of tuples
+    let b = [("a","b","c"),
              ("d","e","f"),
-             ("g","h","i")).
+             ("g","h","i")].
     -- Access an element in the nested structure.
-    println(b @1 @1).
+    assert(b @1 @1 == "e").
 
-Unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared. Should we want to change the contents of an already declared tuple, we would need to abandon the original and declare a new ``tuple``. The following code block demonstrates this,
+Unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared.  The following code block demonstrates this,
 ::
     load system io.
-    -- build a tuple
-    let b = ("a","b","c").
-    -- attempt to modify an element in the tuple
+
+    let b = ("a","b","c"). -- build a tuple
+    
     try
-        let b @1 = "z".
-    catch Exception(kind,s) do
-        println(kind+": "+s).
+        let b @1 = "z". -- attempt to modify an element in the tuple
+    catch Exception(kind,message) do
+        io @println (kind+": "+message).
     end.
 
 Which will print out the following message:
 ::
-    SystemError: 'tuple' is not a mutable structure
 
+    SystemError: term '(a,b,c)' is not a mutable structure
+
+Should we want to change the contents of an already declared tuple, we would need to abandon the original and create a new one with the updated contents.
 When to use tuples and when to use lists is really application dependent.
 Tuples tend to be preferred over lists when representing some sort of structure,
-like abstract syntax trees, where that structure is unmutable meaning, for example,
+like abstract syntax trees, where that structure is immutable meaning, for example,
 that the arity of a tree node cannot change.
 
-Custom Data Structures using ``structure``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Custom Data Structures
+^^^^^^^^^^^^^^^^^^^^^^
+
+You can introduce custom data structures using the ``structure`` keyword.  For example,
+the following statement introduces a structure of type ``A`` with data members ``a`` and ``b``,
+::
+    structure A with
+       data a.
+       data b.
+    end
+
+These custom data structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.   Asteroid creates
+a *default constructor* that instantiates an object from a given structure.  A default constructor copies the arguments given to it into the
+data member fields in the order that the data members appear in the
+structure definition and as they appear in the parameter list of the constructor.
+Also, the data fields of an object are accessed via
+their names rather than index values.  Here is a simple example that illustrates
+all this,
+::
+    -- define a structure of type A
+    structure A with
+        data a.
+        data b.
+    end
+
+    let obj = A(1,2).       -- call constructor
+    assert( obj @a == 1 ).  -- access first data member
+    assert( obj @b == 2 ).  -- access second data member
 
-You can introduce custom data structures using the ``structure`` keyword.  These custom data structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.  We should mention that Asteroid creates
-a *default constructor* for a structure.  That constructor copies the arguments given to it into the
-data member fields of the structure in the order that the data members appear in the
-structure definition and as they appear in the parameter list of the constructor. Here is a simple example,
+The following is a more involved example,
 ::
     load system io.
 
@@ -250,49 +310,51 @@ structure definition and as they appear in the parameter list of the constructor
         data name.
         data age.
         data gender.
-        end
+    end
 
     -- make a list of persons
     let people = [
         -- use default constructors to construct Person instances
-        Person("George", 32, "M"),
-        Person("Sophie", 46, "F"),
-        Person("Oliver", 21, "X")
-        ].
+        Person("George", 32, "man"),
+        Person("Sophie", 46, "woman"),
+        Person("Oliver", 21, "man")
+    ].
 
-    -- retrieve the second person on the list and print
-    let Person(name,age,gender) = people @1. -- pattern match against the structure
-    println (name + " is " + age + " years old and is " +  gender + ".").
+    -- retrieve the second person on the list and use pattern
+    -- matching to extract member values
+    let Person(name,age,gender) = people @1.
+
+    -- print out the member values
+    io @println (name + " is " + age + " years old and is a " +  gender + ".").
 
 The output is,
 ::
-    Sophie is 46 years old and is F.
+
+    Sophie is 46 years old and is a woman.
 
 
-The ``structure`` statement introduces a new typed data structure. In this case it introduces a data structure of type ``Person`` with three "data slots".  We use this data structure to build a list of persons.  One of the interesting things  is that we can pattern match the generated data structure as in the second ``let`` statement in the program above.
+The ``structure`` statement introduces a data structure of type ``Person`` with the three data members ``name``, ``age``, and ``gender``.  We use this data structure to build a list of persons.  One of the interesting things is that we can pattern match the generated data structure as in the second ``let`` statement in the program to extract
+information from a ``Person`` object.
 
 In addition to the default constructor, structures in Asteroid also support user specified
 constructors and member functions.  We'll talk about those later when we talk about OO programming in Asteroid.
 
 The ``let`` Statement
--------------------
+---------------------
 
 The ``let`` statement is a pattern matching statement and can be viewed as Asteroid's version of the assignment statement even though statements like,
 ::
+
     let 1 = 1.
 
 where we take the term on the right side and match it to the pattern on the left side of
-the ``=`` operator are completely legal and highlight the fact that ``let`` statement is not equivalent to an assignment statement.  Patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, and user defined structures.
-
+the ``=`` operator are completely legal and highlight the fact that ``let`` statement is not equivalent to an assignment statement.  Simple patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, and user defined structures.
 Here is an example where we do some computations on the right side of a ``let`` statement and then match the result against a pattern on the left,
 ::
     load system io.
 
-    -- note 1+1 evaluates to 2 and is then matched
-    -- the variables x and y are bound to 1 and 3, respectively,
-    -- via pattern matching
     let [x,2,y] = [1+0,1+1,1+2].
-    println (x,y).
+    io @println (x,y).
 
 The output is: ``(1,3)``
 
@@ -301,8 +363,8 @@ of a given type.  For instance, the ``%integer`` pattern matches any integer val
 ::
     let %integer = 1.
 
-This ``let`` statement succeeds because the value ``1`` can be pattern matched against
-the type pattern ``%integer``
+This ``let`` statement succeeds because ``1`` is an integer value can be pattern-matched against
+the type pattern ``%integer``.
 
 Asteroid also
 supports something called a **named pattern** were a (sub)pattern on the left side
@@ -312,11 +374,12 @@ and that name will be instantiated with a term during pattern matching.  For exa
     load system io.
 
     let t:(1,2) = (1,2).  -- using a named pattern on lhs
-    println t.
+    io @println t.
 
 Here, the construct ``t:(1,2)`` is called a named pattern and the variable ``t`` will be unified with the term ``(1,2)``, or more generally, the variable will be unified with term
 that matches the pattern on the right of the colon.  The program will print,
 ::
+
     (1,2)
 
 We can combine type patterns and named patterns to give us something that looks
@@ -327,29 +390,31 @@ about pattern matching.  Consider,
     load system math.
     load system type.
 
-    let x:%real = pi.
-    println (tostring(x,stringformat(4,2))).
+    let x:%real = math @pi.
+    io @println (type @tostring (x,type @stringformat (4,2))).
 
 The left side of the ``let`` statement is a named type pattern that matches any real value, and
 if that match is successful then the value is bound to the variable ``x``.  Note
 that even though this looks like a declaration, it is in fact a pattern matching
-operation.  The program will print the value ``3.14``.
+operation.  The program will print the value ``3.14`` according to the format of
+4 characters with 2 characters after the decimal point.
 
 Flow of Control
 ---------------
 
-Control structure implementation in Asteroid is along the lines of any of the modern programming languages in use such as Python, Swift, or Rust.  For example, the ``for`` loop allows you to iterate over lists without having to explicitly define a loop index counter. In addition, the ``if`` statement defines what does or does not happen when certain conditions are met. For a list of all control statements in Asteroid, see the reference guide.
+Control structure implementation in Asteroid is along the lines of any of the modern programming languages such as Python, Swift, or Rust.  For example, the ``for`` loop allows you to iterate over lists without having to explicitly define a loop index counter. In addition, the ``if`` statement defines what does or does not happen when certain conditions are met in a very familiar way. For a list of all control statements in Asteroid, please take a look at the reference guide.
 
-As we said, in terms of flow of control statements there are really not a lot of surprises. This is because Asteroid supports loops and conditionals in a very similar way to many of the other modern programming languages in use today.  For example, here is a short program with a ``for`` loop that prints out the first six even positive integers,
+As we said, in terms of flow of control statements there are really not a lot of surprises. This is because Asteroid supports loops and conditionals in a very similar way to many of the other modern programming languages.  For example, here is a short program with a ``for`` loop that prints out the first six even positive integers,
 ::
     load system io.
 
-    for i in 0 to 10 step 2 do
-        println i.
+    for i in 0 to 10 stride 2 do
+        io @println i.
     end
 
 The output is,
 ::
+
     0
     2
     4
@@ -362,12 +427,13 @@ Here is another example that iterates over lists,
     load system io.
     load system util
 
-    for (ix,bird) in zip(["first","second","third"],["turkey","duck","chicken"]) do
-        println ("the "+ix+" bird is a "+bird).
+    for (ix,bird) in util @zip (["first","second","third"],["turkey","duck","chicken"]) do
+        io @println ("the "+ix+" bird is a "+bird).
     end
 
 The output is,
 ::
+
     the first bird is a turkey
     the second bird is a duck
     the third bird is a chicken
@@ -378,19 +444,19 @@ iterate pattern matching on each of the pairs on the list with the pattern ``(ix
 The following is a short program that demonstrates an ``if`` statement,
 ::
     load system io.
-    load system util.
+    load system type.
 
-    let x = tointeger(input("Please enter an integer: ")).
+    let x = type @tointeger (io @input "Please enter an integer: ").
 
     if x < 0 do
         let x = 0.
-        println("Negative, changed to zero").
+        io @println "Negative, changed to zero".
     elif x == 0 do
-        println("Zero").
+        io @println "Zero".
     elif x == 1 do
-        println("Single")
+        io @println "One".
     else do
-        println("More").
+        io @println "Something else".
     end
 
 Even though Asteroid's flow of control statements look so familiar, they support pattern matching to a degree not found in other programming languages and which we will take a look at below.
@@ -399,37 +465,53 @@ Functions
 ---------
 
 Functions in Asteroid resemble function definitions in functional programming languages such as Haskell and ML.
-Formal arguments are bound via pattern matching and functions are multi-dispatch, that is,
-a single function can have multiple bodies each attached to a different pattern
-instantiating the formal arguments.
-
-Let's start with something simple.  Here is a function definition for ``revdouble`` that reverses a list of integers
-then doubles each value before returning the result,
+Here functions have a single formal argument and function calls are expressed via juxtaposition
+of the function name and the actual argument.  Here is a simple example,
 ::
-    load system io.
+    function double
+        with i do -- pattern match the actual arg with i
+            return 2*i.
+        end
+
+    let d = double 2.  -- function call via juxtaposition
+    assert( d == 4 ).
+
+In the ``with`` statement we pattern match the actual argument that is
+being passed in against the variable ``i``.  Also note that the function call is expressed via juxtaposition,
+no parentheses necessary.
 
-    function revdouble
-        with l:%list do
-            return l @reverse() @map(lambda with x:%integer do return 2*x).
+If we wanted to pass more than a single value to a function we have to create
+a tuple and then pass that tuple to the function like in this example,
+::
+    function reduce
+        with (a,b) do -- pattern match the actual argument
+            return a*b.
         end
 
-    println (revdouble [1,2,3]).
+    let r = reduce (2,4).  -- function call via juxtaposition
+    assert( r == 8 ).
 
-The output is ``[6,4,2]``.  Notice how we used type patterns to make sure that this
-function is only applied to lists of integers.
+Even though the function call looks like a traditional function call like in
+Python it is not.  The underlying mechanism is quite different: on the call site
+we construct a tuple that holds all our values which is then passed to the function as the only parameter.
+Within the function that tuple is pattern matched and whatever variables are
+instantiated during this pattern match can be used within the function body.
 
-In order to demonstrate functional programming like multi-dispatch, the following is the quick sort implemented in
-Asteroid. Each ``with``clause introduces a new function body with its
+In Asteroid functions are multi-dispatch, that is,
+a single function can have multiple bodies each attached to a different pattern
+matching the formal argument.
+The following is the quick sort implemented in
+Asteroid where each ``with`` clause introduces a new function body with its
 corresponding pattern,
 ::
     load system io.
 
     function qsort
-        with [] do
+        with [] do -- empty list pattern
             return [].
-        with [a] do
+        with [a] do -- single element list pattern
             return [a].
-        with [pivot|rest] do
+        with [pivot|rest] do -- separating the list into pivot and rest of list
             let less=[].
             let more=[].
 
@@ -445,17 +527,19 @@ corresponding pattern,
         end
 
     -- print the sorted list
-    println (qsort [3,2,1,0])
+    io @println (qsort [3,2,1,0])
 
 The output is as expected,
 ::
+
     [0,1,2,3]
 
-Notice that we use the multi-dispatch mechanism to deal with the base cases of the
-``qsort`` recursion using separate function bodies in the first two ``with`` clauses.
-In the third ``with`` clause we use the head-tail operator ``[pivot|rest]``
-which itself is a pattern matching any non-empty list.
-Here the variable ``pivot`` matches the first element of a list, and the variable ``rest`` matches the remaining list. This remaining list is the original list with its first element removed.  What you also will notice is that function calls do not necessarily have to involve parentheses.  Function application is expressed by simple juxtaposition in Asteroid.  For example, if ``foobar`` is a function then ``foobar(a)`` is a function call in Asteroid but so is ``foobar a``.  The latter form of function call is used in the last line of the function ``qsort`` below.
+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
+quick sort.  Just keep in mind that function calls are expressed via juxtaposition
+of function name and actual argument; no parentheses necessary.
 
 As you have seen in a couple of occasions already in the document, Asteroid also supports anonymous or ``lambda`` functions.  Lambda functions behave just like regular
 functions except that you declare them on-the-fly and they are declared without a
@@ -463,7 +547,7 @@ name.  Here is an example using a ``lambda`` function,
 ::
     load system io.
 
-    println ((lambda with n do return n+1) 1).
+    io @println ((lambda with n do return n+1) 1).
 
 The output is ``2``.  Here, the lambda function is a function that takes a value
 and increments it by one.  We then apply the value ``1`` to the function and the
@@ -476,7 +560,7 @@ Pattern matching lies at the heart of Asteroid.  We saw some of Asteroid's patte
 in expressions using the ``is`` predicate.
 
 Pattern Matching in Expressions: The ``is`` Predicate
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Consider the following example of this predicate among some patterns,
 ::
@@ -485,31 +569,33 @@ Consider the following example of this predicate among some patterns,
     let p = (1,2).
 
     if p is (x,y,z) do
-        println ("it's a triple with: "+x+","+y+","+z)
+        io @println ("it's a triple with: "+x+","+y+","+z)
     elif p is (x,y) do
-        println ("it's a pair with: "+x+","+y).
+        io @println ("it's a pair with: "+x+","+y).
     else do
-        println "it's something else".
+        io @println "it's something else".
     end
 
-Here we use patterns to determine if ``p`` is a triple, a pair, or something else. Pattern matching is embedded in the expressions of the ``if`` statement. The
+Here we use patterns to determine if ``p`` is a triple, a pair, or something else. Pattern matching is embedded in the expressions of the ``if`` statement using the ``is`` predicate. The
 output of this program is,
 ::
+
     it's a pair with: 1,2
 
 Pattern matching with the ``is`` predicate can happen anywhere expressions can
-be used.  That means we can use the predicate also in the ``let`` statements,
+be used.  That means we can use the predicate also in ``let`` statements,
 ::
+
     let true = (1,2) is (1,2).
 
 This is kind of strange looking but it succeeds.  Here the
-left side of the ``is`` predicate is the term and
-the right side is the pattern.  Obviously this pattern match will succeed because the
+left operand of the ``is`` predicate is a term and
+the right operand is a pattern.  Obviously this pattern match will succeed because the
 term and the pattern look identical.  The return value of the ``is`` predicate is then
-pattern matched against the ``true`` value on the left of the ``=`` operator.
+pattern matched against the ``true`` value on the left of the ``=`` symbol.
 
 We can also employ pattern matching in loops.
-In the following program we use the ``is`` predicate to test whether the list is empty or not
+In the following program we use the ``is`` predicate to test whether a list is empty or not
 while looping,
 ::
     load system io.
@@ -517,18 +603,19 @@ while looping,
     let list = [1,2,3].
 
     repeat do
-        let [head|tail] = list.
-        println head.
+        let [head|tail] = list. -- pattern match with head/tail operator
+        io @println head.
         let list = tail.
-    until list is [].
+    until list is []. -- pattern match with is predicate
 
 The output is,
 ::
+
     1
     2
     3
 
-The example employs pattern matching using the head-tail operator in the ``repeat-until`` loop expression in order to iterate over a list and print the list elements.  The
+In addition, the example employs pattern matching using the head-tail operator  in order to iterate over the list elements and print print them.  The
 termination condition of the loop is computed with the ``is`` predicate.
 
 Pattern Matching in Function Arguments
@@ -537,10 +624,12 @@ Pattern Matching in Function Arguments
 As we have seen earlier, Asteroid supports pattern matching on function arguments in the style of ML and many other functional programming languages.
 Here is an example that uses pattern matching on function arguments using custom data structures.  The program below implements `Peano addition <https://en.wikipedia.org/wiki/Peano_axioms#Addition>`_ on terms using the two Peano axioms,
 ::
+
     x + 0 = x
     x + s(y) = s(x+y)
 
-Here ``x`` and ``y`` are variables, ``0`` represents the natural number with value zero, and ``s`` is the successor function.  In Peano arithmetic any natural number can be represented by the appropriate number of applications of the successor function to the natural number ``0``. Here is the program where we replaced the ``+`` operator with the
+Here ``x`` and ``y`` are variables, ``0`` represents the natural number with value zero, and ``s`` is the successor function.  In Peano arithmetic any natural number can be represented by the appropriate number of applications of the successor function to the natural number ``0``. Here is the program that implements
+the Peano arithmetic based on the two axiom where we replaced the ``+`` operator with the
 ``add`` symbol,
 ::
     -- implements Peano addition on terms
@@ -565,10 +654,11 @@ Here ``x`` and ``y`` are variables, ``0`` represents the natural number with val
         end
 
     -- add 2 3
-    println(reduce(add(s(s(0)),s(s(s(0)))))).
+    io @println (reduce(add(s(s(0)),s(s(s(0)))))).
 
 Our program defines the structure ``s`` to represent the successor function and the structure ``add`` to represent Peano addition. Next, it defines a function that uses pattern matching to identify the left sides of the two axioms.  If either pattern matches the input to the ``reduce`` function, it will activate the corresponding function body and rewrite the term recursively in an appropriate manner.  We have one additional pattern which matches if neither one of the Peano axiom patterns matches and terminates the recursion.  Finally,  on the last line, we use our ``reduce`` function to compute the Peano term for the addition of 2 + 3. As expected, the output of this program is,
 ::
+
     s(s(s(s(s(0)))))
 
 which represents the value 5.
@@ -593,7 +683,7 @@ the kind of values that are being passed to a particular function body,
             throw Error("factorial is not defined for "+n).
         end
 
-    println ("The factorial of 3 is: " + factorial (3)).
+    io @println ("The factorial of 3 is: " + factorial 3).
 
 Here we see that first, we make sure that we are being passed integers and second,
 that the integers are positive using the appropriate conditions on the input values. If
@@ -601,7 +691,7 @@ we are being passed a negative integer, then we throw an error.
 
 
 Pattern Matching in ``for`` Loops
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 We have seen pattern matching in ``for`` loops earlier.  Here we show another
 example. This combines structural matching with regular expression matching
@@ -624,13 +714,13 @@ that selects certain items from a list. Suppose we want to print out the names o
 
     -- print names that contain 'p'
     for Person(name:".*p.*",_) in people do
-        println name.
+        io @println name.
     end
 
 Here we pattern match the ``Person`` object in the ``for`` loop and then use a regular expression to see if the name of that person matches our requirement that it contains a lower case 'p'.  We can tag the pattern with a variable name, a named pattern, so that we can print out the name if the regular expression matches. The output is ``Sophie``.
 
 Pattern Matching in ``try-catch`` Statements
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 Exception handling in Asteroid is very similar to exception handling in many of the other modern programming languages available today.  The example below shows an Asteroid program  that throws one of two exceptions depending on the randomly generated value ``i``,
 ::
@@ -647,16 +737,16 @@ Exception handling in Asteroid is very similar to exception handling in many of
         end
 
     try
-        let i = random().
-        if i >= .5 do
+        let i = random @random().
+        if i >= 0.5 do
             throw Head(i).
         else do
             throw Tail(i).
         end
     catch Head(v) do
-        println("you win with "+tostring(v,stringformat(4,2))).
+        io @println("you win with "+type @tostring(v,type @stringformat(4,2))).
     catch Tail(v) do
-        println("you loose with "+tostring(v,stringformat(4,2))).
+        io @println("you loose with "+type @tostring(v,type @stringformat(4,2))).
     end
 
 The ``Head`` and ``Tail`` exceptions are handled by their corresponding ``catch`` statements, respectively.  In both cases the exception object is unpacked using pattern matching and the unpacked value is used in the appropriate message printed to the screen.
@@ -670,6 +760,7 @@ Structures, Object-Based Programming, and Pattern Matching
 
 We saw structures such as,
 ::
+
     structure Person with
         data name.
         data age.
@@ -681,6 +772,7 @@ introduce a new type name into a program. For instance, in the case above, the `
 statement introduces the type name ``Person``.   Given a structure definition, we can
 create **instances** of that structure.  For example,
 ::
+
     let scarlett = Person("Scarlett",28,"F").
 
 The right side of the ``let`` statement invokes the default constructor for the
@@ -697,7 +789,7 @@ can access members of the instance,
 
     let scarlett = Person("Scarlett",28,"F").
     -- access the name field of the structure instance
-    println (scarlett @name).
+    io @println (scarlett @name).
 
 Asteroid allows you to attach functions to structures.  In member functions
 the object identity of the instance is available through the ``this`` keyword.
@@ -713,7 +805,7 @@ of the instance,
         data gender.
         function hello
             with none do
-                println ("Hello, my name is "+this @name).
+                io @println ("Hello, my name is "+this @name).
             end
         end
 
@@ -723,6 +815,7 @@ of the instance,
 
 This program will print out,
 ::
+
     Hello, my name is Scarlett
 
 The expression ``this @name`` accesses the ``name`` field of the instance the
@@ -740,7 +833,7 @@ data fields.  So even if we declare a structure like this,
         -- the function is defined in the middle of the data fields
         function hello
             with none do
-                println ("Hello, my name is "+this @name).
+                io @println ("Hello, my name is "+this @name).
             end
         data age.
         data gender.
@@ -748,12 +841,13 @@ data fields.  So even if we declare a structure like this,
 
     -- pattern matching ignores function definitions
     let Person(name,age,_) = Person("Scarlett",28,"F").
-    println (name+" is "+age+" years old").
+    io @println (name+" is "+age+" years old").
 
 where the function ``hello`` is defined in the middle of the data fields,
 pattern matching simply ignores the function definition and pattern matches
 only on the data fields.  The output of the program is,
 ::
+
     Scarlett is 28 years old
 
 Here is a slightly more involved example based on the
@@ -794,30 +888,33 @@ Here is the program listing for the example in Asteroid,
     buddy @add_trick "roll over".
 
     -- print out all the dogs that know how to fetch
-    for (Dog(name,tricks) if tostring(tricks) is ".*fetch.*") in [fido,buddy] do
-        println (name+" knows how to fetch").
+    for (Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*") in [fido,buddy] do
+        io @println (name+" knows how to fetch").
     end
 
 After declaring the structure we instantiate two dogs, Fido and Buddy, and add
-tricks to their respective trick repertiores.  The last couple of lines
+tricks to their respective trick repertoires.  The last couple of lines
 of the program consist of a ``for`` loop over a list of our dogs.
 The ``for`` loop is interesting
 because here we use structural, conditional, and regular expression pattern
 matching in order to only select the dogs that know how to do ``fetch`` from
 the list of dogs.  The pattern is,
 ::
-    Dog(name,tricks) if tostring(tricks) is ".*fetch.*"
+
+    Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*"
 
 The structural part of the pattern is ``Dog(name,tricks)`` which simply matches
 any dog instance on the list.  However, that match is only successful if
 the conditional part of the pattern holds,
 ::
-    if tostring(tricks) is ".*fetch.*"
+
+    if type @tostring(tricks) is ".*fetch.*"
 
 This condition only succeeds if the ``tricks`` list viewed as a string matches
 the regular expression ``".*fetch.*"``. That is, if the list contains the word ``fetch``.
 The output is,
 ::
+
     Fido knows how to fetch
 
 
@@ -839,7 +936,8 @@ In Asteroid first-class patterns are introduced with the keywords ``pattern with
 and patterns themselves are values that we can store in variables and then reference
 when we want to use them.  Like so,
 ::
-    let P = pattern with (x,y).
+
+    let P = pattern (x,y).
     let *P = (1,2).
 
 The left side of the second ``let`` statement dereferences the pattern stored in variable ``P``
@@ -858,9 +956,10 @@ the following function that takes a pair of values.  The twist is that
 the first component of the pair is restricted to the primitive data types of
 Asteroid,
 ::
+
     function foo
         with (x if (x is %boolean) or (x is %integer) or (x is %string),y) do
-            println (x,y).
+            io @println (x,y).
         end
 
 That complicated pattern for the first component completely obliterates the
@@ -869,6 +968,7 @@ difficult to read.
 
 We can express the same function with a first-class pattern,
 ::
+
     let TP = pattern
         with q if (q is %boolean) or
                   (q is %integer) or
@@ -876,7 +976,7 @@ We can express the same function with a first-class pattern,
 
     function foo
         with (x:*TP,y) do
-            println (x,y).
+            io @println (x,y).
         end
 
 It is clear now that the main input structure to the function is a pair and the
@@ -900,7 +1000,7 @@ spots where the patterns occurs. Consider the following program snippet,
             throw Error("fact undefined for negative values").
         end
 
-    function stepf
+    function sign
         with 0 do
             return 1
         with (n:%integer) if n > 0 do
@@ -913,8 +1013,8 @@ 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 with (x:%integer) if x > 0.
-    let NEG_INT = pattern with (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
@@ -925,7 +1025,7 @@ much more elegant way,
             throw Error("fact undefined for negative values").
         end
 
-    function stepf
+    function sign
         with 0 do
                 return 1
             with *POS_INT do
@@ -937,154 +1037,13 @@ much more elegant way,
 The relevant patterns are now stored in the variables ``POS_INT`` and ``NEG_INT``
 which are then used in the function definitions.
 
-Running Patterns in Reverse
-^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-One of the challenges when programming with patterns is to keep an object structure and
-the patterns aimed at destructuring that object structure in sync.  First-class
-patterns solve this problem in an elegant way by viewing first-class patterns as
-essentially "object network constructors".  In that way, a first-class pattern is
-used to construct an object structure as well as destructure it without having to
-worry that the structure and pattern will get out of sync.
-
-In order to use a pattern as a constructor we apply the ``eval`` function to it which
-turns the pattern into a value from Asteroid's point of view which can then be used
-in computations.  For example,
-::
-    load system io.
-    let P = pattern with ([a],[b]).
-    let a = 1.
-    let b = 2.
-    let v = eval P. -- use pattern to construct a value
-    println v.
-
-The output of the program is,
-::
-    ([1],[2])
-
-which is the value computed by the ``eval`` function given the values associated with
-the variables ``a`` and ``b``, and
-the first-class pattern ``P``.  Of course, first-class patterns can be used
-to destructure the constructed value,
-::
-    load system io.
-    let P = pattern with ([a],[b]).
-    let v = ([1],[2]).
-    let *P = v.
-    println a.
-    println b.
-
-As expected, the output is,
-::
-    1
-    2
-
-which are the values of the variables instantiated by the pattern match of the first-class
-pattern.
-
-As a more advanced example, consider the following
-program that defines a family object network.  It
-uses the first-class pattern ``FP`` to both construct an object network representing
-a family and, since it is a pattern, can also be used to destructure a family object
-network.  Here is the program listing,
-::
-    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
-    -----------------------------
-    println(destructure_family(FP,f1)).
-    println(destructure_family(FP,f2)).
-
-The function ``construct_family`` constructs a family evaluating the pattern using
-the ``eval`` function.  The formal parameters of the function provide values for
-the free variables in the pattern.  Since we are dealing with first-class
-patterns we can simply pass the pattern to the function as a value.
-
-The function ``destructure_family`` does the opposite.  It uses the first-class
-pattern to pattern-match the passed in term, that is, it destructures that term
-using the pattern.  The return statement captures the variables declared as a result
-of that pattern match and returns the values as a list. The output of the program is,
-::
-    [Harry,Bridget,Sue,Peter]
-    [Margot,Selma,Latisha,Rudolf]
-
-
-Notice that the whole program is essentially parameterized over the structure
-of the pattern.  We could easily change some internals of this pattern without
-affecting the rest of the program.
-
 Constraint Patterns
 -------------------
 
 Sometimes we want to use patterns as constraints on other patterns.  Consider
 the following (somewhat artificial) example,
 ::
+
    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
@@ -1094,6 +1053,7 @@ introduces a spurious binding of the variable ``v`` into the current environment
 which might be undesirable due to variable name clashes.  Our notion of constraint pattern
 addresses this.  We can rewrite the above statement as follows,
 ::
+
    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 ``%[...]%``
@@ -1105,13 +1065,13 @@ in functions.  Consider the following program,
 ::
    load system io.
 
-   let POS_INT = pattern with %[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
       return a+b.
    end
 
-   println (add(1,2)).
+   io @println (add(1,2)).
 
 Without the ``%[...]%`` operators around the pattern ``v if (v is %integer) and v > 0``
 the argument list pattern for the function
@@ -1137,11 +1097,12 @@ written in Asteroid,
     load system io.
     load system type.
 
+    let pos_num = pattern %[x if type @isscalar(x) and x > 0]%.
+   
     structure Asteroid with
        data size.
        function __init_
-          -- make sure that object has a positive size
-          with v if isscalar(v) and v > 0 do
+          with v:*pos_num do
              let this @size = v.
           end
     end
@@ -1149,16 +1110,14 @@ written in Asteroid,
     structure Spaceship with
         data size.
        function __init_
-          -- make sure that object has a positive size
-          with v if isscalar(v) and v > 0 do
+          with v:*pos_num do
              let this @size = v.
           end
     end
 
     -- we use first-class pattern SpaceObject to
     -- express that both asteroids and space ships are space objects.
-    -- Note: SpaceObject is a pure constraint pattern specified with %[...]%
-    let SpaceObject = pattern with %[x if (x is %Asteroid) or (x is %Spaceship)]%.
+    let SpaceObject = pattern %[x if (x is %Asteroid) or (x is %Spaceship)]%.
 
     -- multi-dispatch function
     function collide_with
@@ -1178,15 +1137,16 @@ written in Asteroid,
       return "Big boom!" if (x@size > 100 and y@size > 100) else collide_with(x, y).
     end
 
-    println (collide(Asteroid(101), Spaceship(300))).
-    println (collide(Asteroid(10), Spaceship(10))).
-    println (collide(Spaceship(101), Spaceship(10))).
+    io @println (collide(Asteroid(101), Spaceship(300))).
+    io @println (collide(Asteroid(10), Spaceship(10))).
+    io @println (collide(Spaceship(101), Spaceship(10))).
 
 Each ``with`` clause in the function ``collide_with`` introduces a new function body with its
 corresponding pattern.
 The function bodies in this case are simple ``return`` statements
 but they could be arbitrary computations.  The output of the program is,
 ::
+
     Big boom!
     a/s
     s/s
@@ -1198,6 +1158,7 @@ More on Exceptions
 
 This section will give further information on how to work with **exceptions**, or unexpected conditions that break the regular flow of execution.  Exceptions generated by Asteroid are ``Exception`` objects with the following structure,
 ::
+
     structure Exception with
         data kind.
         data value.
@@ -1206,14 +1167,14 @@ This section will give further information on how to work with **exceptions**, o
 The ``kind`` field will be populated by Asteroid with one of the following strings,
 
 * ``PatternMatchFailed`` - this exception will be thrown if the user attempted an
-explicit pattern match which failed, e.g. a let statement whose left side pattern
-does not match the term on the right side.
+  explicit pattern match which failed, e.g. a let statement whose left side pattern
+  does not match the term on the right side.
 
 * ``NonLinearPatternError`` - this exception occurs when a pattern has more than
-one variable with the same name, e.g. ``let (x,x) = (1,2).``
+  one variable with the same name, e.g. ``let (x,x) = (1,2).``
 
 * ``RedundantPatternFound`` - this exception is thrown if one pattern makes another
-superfluous, e.g. in a multi-dispatch function definition.
+  superfluous, e.g. in a multi-dispatch function definition.
 
 * ``ArithmeticError`` - e.g. division by zero
 
@@ -1229,11 +1190,12 @@ example,
     try
         let x = 1/0.
     catch Exception("ArithmeticError", s) do
-        println s.
+        io @println s.
     end
 
 The output is,
 ::
+
     integer division or modulo by zero
 
 
@@ -1244,7 +1206,7 @@ Asteroid also provides a predefined ``Error`` object for user level exceptions,
     try
         throw Error("something worth throwing").
     catch Error(s) do
-        println s.
+        io @println s.
     end
 
 Of course the user can also use the ``Exception`` object for their own exceptions
@@ -1255,12 +1217,13 @@ by defining a ``kind`` that does not interfere with the predefined ``kind`` stri
     try
         throw Exception("MyException","something worth throwing").
     catch Exception("MyException",s) do
-        println s.
+        io @println s.
     end
 
 The output here is,
 ::
-    something worth therefore
+
+    something worth throwing
 
 In addition to the Asteroid defined exceptions,
 the user is allowed to construct user level exceptions with any kind of object including tuples and lists. Here is an example that constructs a tuple as an exception object,
@@ -1270,7 +1233,7 @@ the user is allowed to construct user level exceptions with any kind of object i
     try
         throw ("funny exception", 42).
     catch ("funny exception", v) do
-        println v.
+        io @println v.
     end
 
 The output of this program is ``42``.
@@ -1283,7 +1246,7 @@ exception object itself.  Here is an example using a ``wildcard``,
     try
         let (x,y) = (1,2,3).
     catch _ do
-        println "something happened".
+        io @println "something happened".
     end
 
 Here is an example using a variable,
@@ -1294,34 +1257,38 @@ Here is an example using a variable,
     try
         let (x,y) = (1,2,3).
     catch e do
-        println ("something happened: "+tostring(e)).
+        io @println ("something happened: "+type @tostring(e)).
     end
 
 In this last example we simply convert the caught exception object into a string
 and print it,
 ::
-    something happened: Exception(PatternMatchFailed,pattern match failed: term and pattern lists/tuples are not the same length)
+
+    something happened: Exception(PatternMatchFailed,pattern match failed: term and pattern
+    lists/tuples are not the same length)
 
 
 Basic Asteroid I/O
 ------------------
 
-I/O functions are defined in the ``io`` module. The ``println`` function prints its argument in a readable form to the terminal.  Recall that the ``+`` operator also implements string concatenation.  This allows us to construct nicely formatted output strings,
+I/O functions are defined as member functions of the ``io`` module. The ``println`` function prints its argument in a readable form to the terminal.  Recall that the ``+`` operator also implements string concatenation.  This allows us to construct nicely formatted output strings,
 ::
     load system io.
 
     let a = 1.
     let b = 2.
-    println ("a + b = " + (a + b)).
+    io @println ("a + b = " + (a + b)).
 
 The output is
 ::
+
     a + b = 3
 
 We can use the ``tostring`` function defined in the ``type`` module to provide some
 additional formatting. The idea is that the ``tostring`` function takes a value to be turned into a string together with an optional ``stringformat`` formatting specifier object,
 ::
-    tostring(value[,stringformat(width spec[,precision spec])])
+
+    type @tostring(value[,type @stringformat(width spec[,precision spec])])
 
 The width specifier tells the ``tostring`` function how many characters to reserve for the string conversion of the value.  If the value requires more characters than given in the width specifier then the width specifier is ignored.  If the width specifier is larger than than the number of characters required for the value then the value will be right justified.  For real values there is an optional precision specifier.
 
@@ -1333,23 +1300,24 @@ Here is a program that exercises some of the string formatting options,
 
     -- if the width specifier is larger than the length of the value
     -- then the value will be right justified
-    let b = tostring(true,stringformat(10)).
-    println b.
+    let b = type @tostring(true,type @stringformat(10)).
+    io @println b.
 
-    let i = tostring(5,stringformat(5)).
-    println i.
+    let i = type @tostring(5,type @stringformat(5)).
+    io @println i.
 
     -- we can format a string by applying tostring to the string
-    let s = tostring("hello there!",stringformat(30)).
-    println s.
+    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 = tostring(pi,stringformat(6,3)).
-    println r.
+    let r = type @tostring(math @pi,type @stringformat(6,3)).
+    io @println r.
 
 The output of the program is,
 ::
+
           true
         5
                       hello there!
@@ -1364,11 +1332,12 @@ Another useful function defined in the ``io`` module is the ``input`` function t
 ::
     load system io.
 
-    let name = input("What is your name? ").
-    println ("Hello " + name + "!").
+    let name = io @input("What is your name? ").
+    io @println ("Hello " + name + "!").
 
 The output is,
 ::
+
     What is your name? Leo
     Hello Leo!
 
@@ -1379,18 +1348,15 @@ We can use the type casting functions such as ``tointeger`` or ``toreal`` define
     load system io.
     load system type.
 
-    let i = tointeger(input("Please enter a positive integer value: ")).
-
-    if i < 0 do
-        throw Error("I want a positive integer value.").
-    end
+    let i if i > 0  = type @tointeger(io @input("Please enter a positive integer value: ")).
 
     for k in 1 to i do
-        println k.
+        io @println k.
     end
 
 The output is,
 ::
+
     Please enter a positive integer value: 3
     1
     2
@@ -1403,25 +1369,20 @@ The Module System
 -----------------
 
 A module in Asteroid is a file with a set of valid Asteroid statements.
-You can load this file into other Asteroid code with the statement,
-::
+You can load this file into other Asteroid code with the statement::
+
    load "example_path/example_filename".
 
-or
+or::
 
-::
    load example_modulename.
 
-
-In Asteroid modules do not have a separate name space;
-symbols from a module are entered into Asteroid's global name space.
-
 The search strategy for a module to be loaded is as follows,
 
-#. raw module name - could be an absolute path
-#. search in current directory
-#. search in directory where Asteroid is installed
-#. search in subdirectory where Asteroid was started
+1. raw module name - could be an absolute path
+2. search in current directory
+3. search in directory where Asteroid is installed
+4. search in subdirectory where Asteroid was started
 
 Modules defined by the Asteroid system should be loaded with the keyword ``system``
 in order to avoid any clashes with locally defined modules.  If the ``system``
@@ -1433,8 +1394,9 @@ Say that you wanted to load the ``math`` module so you could execute a certain t
     load system io.
     load system math.
 
-    let x = sin( pi / 2 ).
-    println("The sine of pi / 2 is " + x + ".").
+    let x = math @sin( math @pi / 2 ).
+    io @println("The sine of pi / 2 is " + x + ".").
 
 Both the function ``sin`` and the constant value ``pi`` are defined in the ``math`` module.
 In addition, the ``io`` module is where all input/output functions in Asteroid (such as ``println``) come from.
+If you want the complete list of modules, make sure to check out the reference guide `here <https://asteroid-lang.readthedocs.io/en/latest/Reference%20Guide.html>`_.
diff --git a/docs/User Guide.txt b/docs/User Guide.txt
new file mode 100644
index 00000000..f2a50323
--- /dev/null
+++ b/docs/User Guide.txt
@@ -0,0 +1,906 @@
+/******************************************************************
+  This is the source file from which the user guide is generated.
+  We use cpp to insert live code snippets into the document.
+  In order to generate the user guide run the following command
+  on a Unix-like system in the directory of this doc:
+
+  bash generate_docs
+
+ ******************************************************************/
+#include "header.txt"
+
+.. highlight:: none
+
+Asteroid User Guide
+===================
+
+Introduction
+------------
+
+Asteroid is a multi-paradigm programming language supporting first-class patterns.
+The language is heavily influenced by `Python <https://www.python.org>`_, `Rust <https://www.rust-lang.org>`_, `ML <https://www.smlnj.org>`_, and `Prolog <http://www.swi-prolog.org>`_, and makes pattern matching one of its core computational mechanisms.  We often refer to this as pattern-matching oriented programming. When we talk about pattern matching we mean structural pattern matching
+as well as regular expression matching.
+
+In this document we describe the major features of Asteroid and give plenty of examples.  If you have used a programming language like Python or JavaScript before, then Asteroid should appear very familiar.  However, there are some features which differ drastically from other programming languages due to the core pattern-matching programming
+paradigm.  Here are just two examples:
+
+**Example:** All statements that look like assignments are actually pattern-match statements.  For example if we state,
+::
+#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,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-002.ast"
+
+which is just another pattern match without any variable instantiations.
+
+**Example:** Patterns in Asteroid are first-class citizens of the language.
+This is best demonstrated with a program.  Here is a program
+that recursively computes the factorial of a positive integer and uses first-class patterns
+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
+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.
+
+These are just two examples where Asteroid differs drastically from other programming languages.
+This document is an overview of Asteroid and is intended to get you started quickly
+with programming in Asteroid.
+
+
+The Basics
+----------
+
+As with most languages we are familiar with, Asteroid has **variables** (alpha-numeric symbols starting with an alpha character) and **constants**.  Constants are available for all the **primitive data types**,
+
+* ``integer``, e.g. ``1024``
+* ``real``, e.g. ``1.75``
+* ``string``, e.g. ``"Hello, World!"``
+* ``boolean``, e.g. ``true``
+
+Asteroid arranges these data types in a **type hierarchy**,
+
+``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 supports two more 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,)``.
+Here are some examples,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-005.ast"
+
+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,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-006.ast"
+
+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,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-007.ast"
+
+
+Finally, Asteroid supports one more type, namely the ``none`` type.  The ``none`` type has
+only one member: A constant named ``none``.  However, it turns out that the null-tuple, a tuple with no components
+indicated by ``()``, also belongs to this type rather than the tuple type discussed earlier. But the ``none``
+data type only has one constant, this implies that ``()`` and ``none`` mean the same thing and can be used
+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.
+
+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.
+
+Data Structures
+---------------
+
+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,
+::
+#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"
+
+In Asteroid lists are considered objects with member functions that can manipulate list
+objects. We could rewrite the above example as,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-010.ast"
+
+The ``@`` operator allows you to access either individual elements, slices, or member functions of a list.
+Actually, the ``@`` operator is more general than that, it is Asteroid's substructure access operator.
+Notice that in order to access the ``println`` function of the ``io`` module we also use the ``@`` operator.
+This is because in Asteroid, **system modules are objects**, so you must use the ``@`` to access the functions
+of the module.
+
+For a comprehensive treatment of available member functions for Asteroid lists please see the reference guide.
+
+Besides using the default constructor for lists which consists of the
+square brackets enclosing a list of elements we can use **list comprehensions** to construct lists.  In Asteroid a list comprehension consist of a range specifier together with
+a stride specifier allowing you to generate integer values within that range,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-011.ast"
+
+The output is,
+::
+
+    list: [1,3,5,7,9]
+    reversed list: [9,7,5,3,1]
+
+Asteroid's simple list comprehensions in conjunction with the ``map`` function for lists allows you to
+construct virtually  any kind of list. For example, the following program constructs
+a list of alternating 1 and -1,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-012.ast"
+
+where the output is,
+::
+
+    [1,-1,1,-1,1,-1,1,-1,1,-1]
+
+Higher dimensional arrays can easily be simulated with lists of lists,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-013.ast"
+
+The output is,
+::
+    [[1,2,3]
+     [4,0,6]
+     [7,8,9]]
+
+
+Tuples
+^^^^^^
+
+As we saw earlier, the ``tuple`` is another fundamental, built-in data structure that can be found in Asteroid.
+Below is an example of a tuple declaration and access.
+::
+#include "../asteroid/test-suites/ug-programs/prgm-014.ast"
+
+Lists and tuples may be nested,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-015.ast"
+
+Unlike lists, tuples are immutable. This means that their contents cannot be changed once they have been declared.  The following code block demonstrates this,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-016.ast"
+
+Which will print out the following message:
+::
+
+    SystemError: term '(a,b,c)' is not a mutable structure
+
+Should we want to change the contents of an already declared tuple, we would need to abandon the original and create a new one with the updated contents.
+When to use tuples and when to use lists is really application dependent.
+Tuples tend to be preferred over lists when representing some sort of structure,
+like abstract syntax trees, where that structure is immutable meaning, for example,
+that the arity of a tree node cannot change.
+
+Custom Data Structures
+^^^^^^^^^^^^^^^^^^^^^^
+
+You can introduce custom data structures using the ``structure`` keyword.  For example,
+the following statement introduces a structure of type ``A`` with data members ``a`` and ``b``,
+::
+    structure A with
+       data a.
+       data b.
+    end
+
+These custom data structures differ from lists and tuples in the sense that the name of the structure acts like a type tag.  So, when you define a new structure you are in fact introducing a new type into your program.   Asteroid creates
+a *default constructor* that instantiates an object from a given structure.  A default constructor copies the arguments given to it into the
+data member fields in the order that the data members appear in the
+structure definition and as they appear in the parameter list of the constructor.
+Also, the data fields of an object are accessed via
+their names rather than index values.  Here is a simple example that illustrates
+all this,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-017a.ast"
+
+The following is a more involved example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-017.ast"
+
+The output is,
+::
+
+    Sophie is 46 years old and is a woman.
+
+
+The ``structure`` statement introduces a data structure of type ``Person`` with the three data members ``name``, ``age``, and ``gender``.  We use this data structure to build a list of persons.  One of the interesting things is that we can pattern match the generated data structure as in the second ``let`` statement in the program to extract
+information from a ``Person`` object.
+
+In addition to the default constructor, structures in Asteroid also support user specified
+constructors and member functions.  We'll talk about those later when we talk about OO programming in Asteroid.
+
+The ``let`` Statement
+---------------------
+
+The ``let`` statement is a pattern matching statement and can be viewed as Asteroid's version of the assignment statement even though statements like,
+::
+
+    let 1 = 1.
+
+where we take the term on the right side and match it to the pattern on the left side of
+the ``=`` operator are completely legal and highlight the fact that ``let`` statement is not equivalent to an assignment statement.  Simple patterns are expressions that consist purely of constructors and variables. Constructors themselves consist of constants, list and tuple constructors, and user defined structures.
+Here is an example where we do some computations on the right side of a ``let`` statement and then match the result against a pattern on the left,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-018.ast"
+
+The output is: ``(1,3)``
+
+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 on the left side
+of a ``let`` statement (or any pattern as it appears in Asteroid) can be given a name
+and that name will be instantiated with a term during pattern matching.  For example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-020.ast"
+
+Here, the construct ``t:(1,2)`` is called a named pattern and the variable ``t`` will be unified with the term ``(1,2)``, or more generally, the variable will be unified with term
+that matches the pattern on the right of the colon.  The program will print,
+::
+
+    (1,2)
+
+We can combine type patterns and named patterns to give us something that looks
+like a variable declaration in other languages. In Asteroid, though, it is still just all
+about pattern matching.  Consider,
+::
+#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.14`` according to the format of
+4 characters with 2 characters after the decimal point.
+
+Flow of Control
+---------------
+
+Control structure implementation in Asteroid is along the lines of any of the modern programming languages such as Python, Swift, or Rust.  For example, the ``for`` loop allows you to iterate over lists without having to explicitly define a loop index counter. In addition, the ``if`` statement defines what does or does not happen when certain conditions are met in a very familiar way. For a list of all control statements in Asteroid, please take a look at the reference guide.
+
+As we said, in terms of flow of control statements there are really not a lot of surprises. This is because Asteroid supports loops and conditionals in a very similar way to many of the other modern programming languages.  For example, here is a short program with a ``for`` loop that prints out the first six even positive integers,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-022.ast"
+
+The output is,
+::
+
+    0
+    2
+    4
+    6
+    8
+    10
+
+Here is another example that iterates over lists,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-023.ast"
+
+The output is,
+::
+
+    the first bird is a turkey
+    the second bird is a duck
+    the third bird is a chicken
+
+Here we first create a list of pairs using the ``zip`` function, over which we then
+iterate pattern matching on each of the pairs on the list with the pattern ``(ix,bird)``.
+
+The following is a short program that demonstrates an ``if`` statement,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-024.ast"
+
+Even though Asteroid's flow of control statements look so familiar, they support pattern matching to a degree not found in other programming languages and which we will take a look at below.
+
+Functions
+---------
+
+Functions in Asteroid resemble function definitions in functional programming languages such as Haskell and ML.
+Here functions have a single formal argument and function calls are expressed via juxtaposition
+of the function name and the actual argument.  Here is a simple example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-025a.ast"
+
+In the ``with`` statement we pattern match the actual argument that is
+being passed in against the variable ``i``.  Also note that the function call is expressed via juxtaposition,
+no parentheses necessary.
+
+If we wanted to pass more than a single value to a function we have to create
+a tuple and then pass that tuple to the function like in this example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-025b.ast"
+
+Even though the function call looks like a traditional function call like in
+Python it is not.  The underlying mechanism is quite different: on the call site
+we construct a tuple that holds all our values which is then passed to the function as the only parameter.
+Within the function that tuple is pattern matched and whatever variables are
+instantiated during this pattern match can be used within the function body.
+
+In Asteroid functions are multi-dispatch, that is,
+a single function can have multiple bodies each attached to a different pattern
+matching the formal argument.
+The following is the quick sort implemented in
+Asteroid where each ``with`` clause introduces a new function body with its
+corresponding pattern,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-026.ast"
+
+The output is as expected,
+::
+
+    [0,1,2,3]
+
+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
+quick sort.  Just keep in mind that function calls are expressed via juxtaposition
+of function name and actual argument; no parentheses necessary.
+
+As you have seen in a couple of occasions already in the document, Asteroid also supports anonymous or ``lambda`` functions.  Lambda functions behave just like regular
+functions except that you declare them on-the-fly and they are declared without a
+name.  Here is an example using a ``lambda`` function,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-027.ast"
+
+The output is ``2``.  Here, the lambda function is a function that takes a value
+and increments it by one.  We then apply the value ``1`` to the function and the
+print function prints out the value ``2``.
+
+Pattern Matching
+----------------
+
+Pattern matching lies at the heart of Asteroid.  We saw some of Asteroid's pattern matching ability when we discussed the ``let`` statement.  We can also have pattern matching
+in expressions using the ``is`` predicate.
+
+Pattern Matching in Expressions: The ``is`` Predicate
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Consider the following example of this predicate among some patterns,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-028.ast"
+
+Here we use patterns to determine if ``p`` is a triple, a pair, or something else. Pattern matching is embedded in the expressions of the ``if`` statement using the ``is`` predicate. The
+output of this program is,
+::
+
+    it's a pair with: 1,2
+
+Pattern matching with the ``is`` predicate can happen anywhere expressions can
+be used.  That means we can use the predicate also in ``let`` statements,
+::
+
+    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
+term and the pattern look identical.  The return value of the ``is`` predicate is then
+pattern matched against the ``true`` value on the left of the ``=`` symbol.
+
+We can also employ pattern matching in loops.
+In the following program we use the ``is`` predicate to test whether a list is empty or not
+while looping,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-029.ast"
+
+The output is,
+::
+
+    1
+    2
+    3
+
+In addition, the example employs pattern matching using the head-tail operator  in order to iterate over the list elements and print print them.  The
+termination condition of the loop is computed with the ``is`` predicate.
+
+Pattern Matching in Function Arguments
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As we have seen earlier, Asteroid supports pattern matching on function arguments in the style of ML and many other functional programming languages.
+Here is an example that uses pattern matching on function arguments using custom data structures.  The program below implements `Peano addition <https://en.wikipedia.org/wiki/Peano_axioms#Addition>`_ on terms using the two Peano axioms,
+::
+
+    x + 0 = x
+    x + s(y) = s(x+y)
+
+Here ``x`` and ``y`` are variables, ``0`` represents the natural number with value zero, and ``s`` is the successor function.  In Peano arithmetic any natural number can be represented by the appropriate number of applications of the successor function to the natural number ``0``. Here is the program that implements
+the Peano arithmetic based on the two axiom where we replaced the ``+`` operator with the
+``add`` symbol,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-030.ast"
+
+Our program defines the structure ``s`` to represent the successor function and the structure ``add`` to represent Peano addition. Next, it defines a function that uses pattern matching to identify the left sides of the two axioms.  If either pattern matches the input to the ``reduce`` function, it will activate the corresponding function body and rewrite the term recursively in an appropriate manner.  We have one additional pattern which matches if neither one of the Peano axiom patterns matches and terminates the recursion.  Finally,  on the last line, we use our ``reduce`` function to compute the Peano term for the addition of 2 + 3. As expected, the output of this program is,
+::
+
+    s(s(s(s(s(0)))))
+
+which represents the value 5.
+
+Conditional Pattern Matching
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Asteroid allows the user to attach conditions to patterns that need to hold in order
+for the pattern match to succeed.  This is particularly useful for restricting
+input values to function bodies.  Consider the following definition of the
+``factorial`` function where we use conditional pattern matching to control
+the kind of values that are being passed to a particular function body,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-031.ast"
+
+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.
+
+
+Pattern Matching in ``for`` Loops
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+We have seen pattern matching in ``for`` loops earlier.  Here we show another
+example. This combines structural matching with regular expression matching
+in ``for`` loops
+that selects certain items from a list. Suppose we want to print out the names of persons that contain a lower case 'p',
+::
+#include "../asteroid/test-suites/ug-programs/prgm-032.ast"
+
+Here we pattern match the ``Person`` object in the ``for`` loop and then use a regular expression to see if the name of that person matches our requirement that it contains a lower case 'p'.  We can tag the pattern with a variable name, a named pattern, so that we can print out the name if the regular expression matches. The output is ``Sophie``.
+
+Pattern Matching in ``try-catch`` Statements
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Exception handling in Asteroid is very similar to exception handling in many of the other modern programming languages available today.  The example below shows an Asteroid program  that throws one of two exceptions depending on the randomly generated value ``i``,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-033.ast"
+
+The ``Head`` and ``Tail`` exceptions are handled by their corresponding ``catch`` statements, respectively.  In both cases the exception object is unpacked using pattern matching and the unpacked value is used in the appropriate message printed to the screen.
+
+It is worth noting that even though Asteroid has builtin exception objects such as ``Error``,
+you can construct any kind of object and throw it as part of an exception.
+
+
+Structures, Object-Based Programming, and Pattern Matching
+----------------------------------------------------------
+
+We saw structures such as,
+::
+
+    structure Person with
+        data name.
+        data age.
+        data gender.
+        end
+
+earlier.  It is Asteroid's way to create custom data structures. These structures
+introduce a new type name into a program. For instance, in the case above, the ``structure``
+statement introduces the type name ``Person``.   Given a structure definition, we can
+create **instances** of that structure.  For example,
+::
+
+    let scarlett = Person("Scarlett",28,"F").
+
+The right side of the ``let`` statement invokes the default constructor for the
+structure in order to create an instance stored in the variable ``scarlett``. We
+can access members of the instance,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-034.ast"
+
+Asteroid allows you to attach functions to structures.  In member functions
+the object identity of the instance is available through the ``this`` keyword.
+For example, we can
+extend our ``Person`` structure with the ``hello`` function that uses the ``name`` field
+of the instance,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-035.ast"
+
+This program will print out,
+::
+
+    Hello, my name is Scarlett
+
+The expression ``this @name`` accesses the ``name`` field of the instance the
+function ``hello`` was called on.
+Even though our structures are starting to look a bit more like object definitions,
+pattern matching continues to work in the same way from when we discussed structures.
+The only thing you need to keep in mind is that you **cannot** pattern match on a
+function field.  From a pattern matching perspective, a structure consists only of
+data fields.  So even if we declare a structure like this,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-036.ast"
+
+where the function ``hello`` is defined in the middle of the data fields,
+pattern matching simply ignores the function definition and pattern matches
+only on the data fields.  The output of the program is,
+::
+
+    Scarlett is 28 years old
+
+Here is a slightly more involved example based on the
+dog example from the `Python documentation <https://docs.python.org/3/tutorial/classes.html>`_.
+The idea of the dog example is to have a structure that describes dogs by their
+names and the tricks that they can perform.  Tricks can be added to a particular
+dog instance by calling the ``add_trick`` function.  Rather than using the default
+constructor, we define a constructor for our instances with the ``__init__`` function.
+Here is the program listing for the example in Asteroid,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-037.ast"
+
+After declaring the structure we instantiate two dogs, Fido and Buddy, and add
+tricks to their respective trick repertoires.  The last couple of lines
+of the program consist of a ``for`` loop over a list of our dogs.
+The ``for`` loop is interesting
+because here we use structural, conditional, and regular expression pattern
+matching in order to only select the dogs that know how to do ``fetch`` from
+the list of dogs.  The pattern is,
+::
+
+    Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*"
+
+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.*"
+
+This condition only succeeds if the ``tricks`` list viewed as a string matches
+the regular expression ``".*fetch.*"``. That is, if the list contains the word ``fetch``.
+The output is,
+::
+
+    Fido knows how to fetch
+
+
+Patterns as First-Class Citizens
+--------------------------------
+
+A programming language feature that is promoted to first-class status does not
+change the power of a programming language in terms of computability but it does
+increase its expressiveness.  Think functions as first-class citizens of a programming
+language.  First-class functions give us ``lambda`` functions and ``map``, both powerful
+programming tools.
+
+The same is true when we promote patterns to first-class citizen status in a language.  It
+doesn't change what we can and cannot compute with the language. But it does change how
+we can express what we want to compute.  That is, it changes the expressiveness
+of a programming language.
+
+In Asteroid first-class patterns are introduced with the keywords ``pattern with``
+and patterns themselves are values that we can store in variables and then reference
+when we want to use them.  Like so,
+::
+
+    let P = pattern (x,y).
+    let *P = (1,2).
+
+The left side of the second ``let`` statement dereferences the pattern stored in variable ``P``
+and uses the pattern to match against the term ``(1,2)``.
+
+Here we look at three examples of how first-class patterns can add to a developer's
+programming toolbox.
+
+Pattern Factoring
+^^^^^^^^^^^^^^^^^
+
+Patterns can become very complicated especially when conditional pattern matching
+is involved.  First-class patterns allow us to control the complexity of patterns
+by breaking patterns up into smaller subpatterns that are more easily managed. Consider
+the following function that takes a pair of values.  The twist is that
+the first component of the pair is restricted to the primitive data types of
+Asteroid,
+::
+
+    function foo
+        with (x if (x is %boolean) or (x is %integer) or (x is %string),y) do
+            io @println (x,y).
+        end
+
+That complicated pattern for the first component completely obliterates the
+overall structure of the parameter pattern and makes the function definition
+difficult to read.
+
+We can express the same function with a first-class pattern,
+::
+
+    let TP = pattern
+        with q if (q is %boolean) or
+                  (q is %integer) or
+                  (q is %string).
+
+    function foo
+        with (x:*TP,y) do
+            io @println (x,y).
+        end
+
+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``.
+
+Pattern Reuse
+^^^^^^^^^^^^^
+
+In most applications of patterns in programming languages specific patterns appear
+in many spots in a program.  If patterns are not first-class citizens the developer
+will have to retype the same patterns over and over again in the various different
+spots where the patterns occurs. Consider the following program snippet,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-038.ast"
+
+In order to write these two functions we had to repeat the almost identical pattern
+four times.  First-class patterns allow us to write the same two functions in a
+much more elegant way,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-039.ast"
+
+The relevant patterns are now stored in the variables ``POS_INT`` and ``NEG_INT``
+which are then used in the function definitions.
+
+Constraint Patterns
+-------------------
+
+Sometimes we want to use patterns as constraints on other patterns.  Consider
+the following (somewhat artificial) example,
+::
+
+   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
+on the pattern ``x`` in the sense that we want a match on ``x`` only to succeed
+if ``some_value`` is a positive integer.  The problem is that this constraint pattern
+introduces a spurious binding of the variable ``v`` into the current environment
+which might be undesirable due to variable name clashes.  Our notion of constraint pattern
+addresses this.  We can rewrite the above statement as follows,
+::
+
+   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``
+into the current environment.
+
+The most common use of constraint patterns 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``
+the argument list pattern for the function
+``(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
+to occur in the argument list pattern.
+
+
+More on Multi-Dispatch
+----------------------
+
+With the ``qsort`` function above we saw functional programming style dispatch
+where the ``with`` clauses represent a case analysis over a single type, namely
+the input type to the function.
+However, Asteroid has a much broader view of multi-dispatch where the ``with`` clauses
+represent a case analysis over different types.
+In order to demonstrate this type of multi-dispatch, we show the example program from the
+`multi-dispatch Wikipedia page <https://en.wikipedia.org/wiki/Multiple_dispatch>`_
+written in Asteroid,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-044.ast"
+
+Each ``with`` clause in the function ``collide_with`` introduces a new function body with its
+corresponding pattern.
+The function bodies in this case are simple ``return`` statements
+but they could be arbitrary computations.  The output of the program is,
+::
+
+    Big boom!
+    a/s
+    s/s
+
+
+
+More on Exceptions
+------------------
+
+This section will give further information on how to work with **exceptions**, or unexpected conditions that break the regular flow of execution.  Exceptions generated by Asteroid are ``Exception`` objects with the following structure,
+::
+
+    structure Exception with
+        data kind.
+        data value.
+    end
+
+The ``kind`` field will be populated by Asteroid with one of the following strings,
+
+* ``PatternMatchFailed`` - this exception will be thrown if the user attempted an
+  explicit pattern match which failed, e.g. a let statement whose left side pattern
+  does not match the term on the right side.
+
+* ``NonLinearPatternError`` - this exception occurs when a pattern has more than
+  one variable with the same name, e.g. ``let (x,x) = (1,2).``
+
+* ``RedundantPatternFound`` - this exception is thrown if one pattern makes another
+  superfluous, e.g. in a multi-dispatch function definition.
+
+* ``ArithmeticError`` - e.g. division by zero
+
+* ``FileNotFound`` - an attempt of opening a file failed.
+
+* ``SystemError`` - a general exception.
+
+In addition to the ``kind`` field, the ``value`` field holds a string with some further details on the exception. Specific exceptions can be caught by pattern matching on the ``kind`` field of the ``Exception`` object.  For
+example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-045.ast"
+
+The output is,
+::
+
+    integer division or modulo by zero
+
+
+Asteroid also provides a predefined ``Error`` object for user level exceptions,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-046.ast"
+
+Of course the user can also use the ``Exception`` object for their own exceptions
+by defining a ``kind`` that does not interfere with the predefined ``kind`` strings above,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-047.ast"
+
+The output here is,
+::
+
+    something worth throwing
+
+In addition to the Asteroid defined exceptions,
+the user is allowed to construct user level exceptions with any kind of object including tuples and lists. Here is an example that constructs a tuple as an exception object,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-048.ast"
+
+The output of this program is ``42``.
+
+Now, if you don't care what kind of exception you catch, you need to use a ``wildcard`` or a variable because exception handlers are activated via pattern matching on the
+exception object itself.  Here is an example using a ``wildcard``,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-049.ast"
+
+Here is an example using a variable,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-050.ast"
+
+In this last example we simply convert the caught exception object into a string
+and print it,
+::
+
+    something happened: Exception(PatternMatchFailed,pattern match failed: term and pattern
+    lists/tuples are not the same length)
+
+
+Basic Asteroid I/O
+------------------
+
+I/O functions are defined as member functions of the ``io`` module. The ``println`` function prints its argument in a readable form to the terminal.  Recall that the ``+`` operator also implements string concatenation.  This allows us to construct nicely formatted output strings,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-051.ast"
+
+The output is
+::
+
+    a + b = 3
+
+We can use the ``tostring`` function defined in the ``type`` module to provide some
+additional formatting. The idea is that the ``tostring`` function takes a value to be turned into a string together with an optional ``stringformat`` formatting specifier object,
+::
+
+    type @tostring(value[,type @stringformat(width spec[,precision spec])])
+
+The width specifier tells the ``tostring`` function how many characters to reserve for the string conversion of the value.  If the value requires more characters than given in the width specifier then the width specifier is ignored.  If the width specifier is larger than than the number of characters required for the value then the value will be right justified.  For real values there is an optional precision specifier.
+
+Here is a program that exercises some of the string formatting options,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-052.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.
+
+The ``io`` module also defines a function ``print`` which behaves just like ``println``
+except that it does not terminate print with a newline.
+
+Another useful function defined in the ``io`` module is the ``input`` function that, given an optional prompt string, will prompt the user at the terminal and return the input value as a string.  Here is a small example,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-053.ast"
+
+The output is,
+::
+
+    What is your name? Leo
+    Hello Leo!
+
+
+We can use the type casting functions such as ``tointeger`` or ``toreal`` defined in the
+``type`` module to convert the string returned from ``input`` into a numeric value,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-054.ast"
+
+The output is,
+::
+
+    Please enter a positive integer value: 3
+    1
+    2
+    3
+
+
+Finally, the function ``read`` reads from ``stdin`` and returns the input as a string.  The function ``write`` writes a string to ``stdout``.
+
+The Module System
+-----------------
+
+A module in Asteroid is a file with a set of valid Asteroid statements.
+You can load this file into other Asteroid code with the statement::
+
+   load "example_path/example_filename".
+
+or::
+
+   load example_modulename.
+
+The search strategy for a module to be loaded is as follows,
+
+1. raw module name - could be an absolute path
+2. search in current directory
+3. search in directory where Asteroid is installed
+4. search in subdirectory where Asteroid was started
+
+Modules defined by the Asteroid system should be loaded with the keyword ``system``
+in order to avoid any clashes with locally defined modules.  If the ``system``
+keyword is used then Asteroid only searches in its system folders
+rather than in user directories.
+
+Say that you wanted to load the ``math`` module so you could execute a certain trigonometric function. The following Asteroid program loads the ``math`` module as well as the ``io``  module. Only after loading them would you be able to complete the sine function below,
+::
+#include "../asteroid/test-suites/ug-programs/prgm-055.ast"
+
+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>`_.
diff --git a/docs/conf.py b/docs/conf.py
index fe6a460e..c857f380 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -22,7 +22,7 @@
 author = 'Lutz Hamel, Tim Colaneri, Oliver McLaughlin, Ariel Finkel, Theodore Henson, Calvin Higgins'
 
 # The full version, including alpha/beta/rc tags
-release = '0.1.0'
+release = '1.0.0'
 
 
 # -- General configuration ---------------------------------------------------
diff --git a/docs/generate_docs b/docs/generate_docs
new file mode 100755
index 00000000..691b1cd2
--- /dev/null
+++ b/docs/generate_docs
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+echo "generating User Guide.rst"
+cpp -w -P -traditional "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"
+
+echo "generating Asteroid in Action.rst"
+cpp -w -P -traditional "Asteroid in Action.txt" > "Asteroid in Action.rst"
diff --git a/docs/header.txt b/docs/header.txt
new file mode 100644
index 00000000..c7cf5888
--- /dev/null
+++ b/docs/header.txt
@@ -0,0 +1,4 @@
+/* header for generated .rst files */
+
+..
+   *** DO NOT EDIT; MACHINE GENERATED ***
diff --git a/docs/index.rst b/docs/index.rst
index f9204103..d76aa355 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -17,6 +17,7 @@ Contents
    :maxdepth: 1
 
    Installing and Running
-   Asteroid User Guide
+   Quickstart Tutorial
+   User Guide
    Reference Guide
    Asteroid in Action
diff --git a/docs/strip b/docs/strip
new file mode 100644
index 00000000..c8525d8e
--- /dev/null
+++ b/docs/strip
@@ -0,0 +1,57 @@
+#!/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/requirements.txt b/requirements.txt
new file mode 100644
index 00000000..c6406d6a
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,3 @@
+pandas
+numpy
+matplotlib
diff --git a/setup.py b/setup.py
index b60f88f2..eb63bc90 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@
 
 setup(
     name="asteroid-lang",
-    version="0.1.0",
+    version="1.0.0",
     author="University of Rhode Island",
     author_email="lutzhamel@uri.edu",
     description="A pattern-matching oriented programming language.",


Test patch:
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
new file mode 100644
index 00000000..881c72c3
--- /dev/null
+++ b/.github/workflows/tests.yml
@@ -0,0 +1,19 @@
+name: Run Tests
+on:
+    pull_request:
+        branches:
+            - master
+            - dev-1.0.0
+env:
+    PYTHONPATH: ${{ github.workspace }}
+jobs:
+  run-tests:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out repository
+        uses: actions/checkout@v2
+        
+      - name: Run tests
+        run: |
+            pip install -r requirements.txt
+            python ${{ github.workspace }}/asteroid/test-suites/run-tests.py
diff --git a/asteroid/programs/test_hash.ast b/asteroid/programs/test_hash.ast
index b34a10e2..f76395e3 100644
--- a/asteroid/programs/test_hash.ast
+++ b/asteroid/programs/test_hash.ast
@@ -1,7 +1,6 @@
-load "io".
-load "hash".
+load system io.
+load system hash.
 
-let h = HashTable().
+let h = hash @hash().
 h@insert("hello","there").
-println (h@get("hello")).
-
+io @println (h@get("hello")).
diff --git a/asteroid/test-suites/action-tests/test001.ast b/asteroid/test-suites/action-tests/test001.ast
new file mode 100644
index 00000000..89382e6a
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test001.ast
@@ -0,0 +1,3 @@
+  load system io.
+
+  io @println "Hello, World!".
diff --git a/asteroid/test-suites/action-tests/test002.ast b/asteroid/test-suites/action-tests/test002.ast
new file mode 100644
index 00000000..f70bb104
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test002.ast
@@ -0,0 +1,3 @@
+  load system io.
+
+  io @__raw_print__ "Hello, World!".
diff --git a/asteroid/test-suites/action-tests/test003-io.txt b/asteroid/test-suites/action-tests/test003-io.txt
new file mode 100644
index 00000000..599f87bf
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test003-io.txt
@@ -0,0 +1,2 @@
+Leo
+
diff --git a/asteroid/test-suites/action-tests/test003.ast b/asteroid/test-suites/action-tests/test003.ast
new file mode 100644
index 00000000..87862ce4
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test003.ast
@@ -0,0 +1,5 @@
+  load system io.
+
+  io @print ("Enter your name: ").
+  let name = io @input().
+  io @print ("Hello, "+name+"!").
diff --git a/asteroid/test-suites/action-tests/test004-io.txt b/asteroid/test-suites/action-tests/test004-io.txt
new file mode 100644
index 00000000..599f87bf
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test004-io.txt
@@ -0,0 +1,2 @@
+Leo
+
diff --git a/asteroid/test-suites/action-tests/test004.ast b/asteroid/test-suites/action-tests/test004.ast
new file mode 100644
index 00000000..434e5a6c
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test004.ast
@@ -0,0 +1,4 @@
+  load system io.
+
+  let name = io @input("Enter your name: ").
+  io @println ("Hello, "+name+"!").
diff --git a/asteroid/test-suites/action-tests/test005-io.txt b/asteroid/test-suites/action-tests/test005-io.txt
new file mode 100644
index 00000000..599f87bf
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test005-io.txt
@@ -0,0 +1,2 @@
+Leo
+
diff --git a/asteroid/test-suites/action-tests/test005.ast b/asteroid/test-suites/action-tests/test005.ast
new file mode 100644
index 00000000..b558631c
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test005.ast
@@ -0,0 +1,3 @@
+  load system io.
+
+  io @println ("Hello, "+io @input("Enter your name: ")+"!").
diff --git a/asteroid/test-suites/action-tests/test006.ast b/asteroid/test-suites/action-tests/test006.ast
new file mode 100644
index 00000000..06b56af2
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test006.ast
@@ -0,0 +1,4 @@
+  load system io.
+
+  load "util".
+  io @println (len("Hello!")).
diff --git a/asteroid/test-suites/action-tests/test007.ast b/asteroid/test-suites/action-tests/test007.ast
new file mode 100644
index 00000000..00daf778
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test007.ast
@@ -0,0 +1,3 @@
+  load system io.
+
+  io @println ("Hello!" @length()).
diff --git a/asteroid/test-suites/action-tests/test008.ast b/asteroid/test-suites/action-tests/test008.ast
new file mode 100644
index 00000000..3c339a57
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test008.ast
@@ -0,0 +1,15 @@
+  load system io.
+
+  function unique with (x,y) do
+      if not (x @member(y)) do
+          return x @append(y).
+      else do
+          return x.
+      end
+  end
+
+  let digits = "332211" @explode()
+                        @sort()
+                        @reduce(unique,[]).
+  io @println digits.
+  assert(digits == ["1","2","3"]).
diff --git a/asteroid/test-suites/action-tests/test009.ast b/asteroid/test-suites/action-tests/test009.ast
new file mode 100644
index 00000000..eb55ad55
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test009.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let str = "Hello, World!" @explode()
+                            @reverse()
+                            @join("").
+  io @println str.
+  assert(str == "!dlroW ,olleH").
diff --git a/asteroid/test-suites/action-tests/test010.ast b/asteroid/test-suites/action-tests/test010.ast
new file mode 100644
index 00000000..6b79b4ca
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test010.ast
@@ -0,0 +1,5 @@
+  load system io.
+  let str = "   Hello  ,   World    !   " @trim()
+                                          @replace("  ","").
+  io @println str.
+  assert(str == "Hello, World!").
diff --git a/asteroid/test-suites/action-tests/test011.ast b/asteroid/test-suites/action-tests/test011.ast
new file mode 100644
index 00000000..2fee7100
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test011.ast
@@ -0,0 +1,21 @@
+  load system io.
+
+  function title with w do
+      let letter_list = w @tolower()
+                          @explode().
+      let first_letter = letter_list @0
+                                     @toupper().
+      if letter_list @length() > 1 do
+          let title_case = ([first_letter] + letter_list @[1 to letter_list@length()-1]) @join("").
+      else
+          let title_case = first_letter.
+      end
+      return title_case.
+  end
+
+  let str = "once upon a time".
+  let camel_str = str @split()
+                      @map(title)
+                      @join("").
+  io @println camel_str.
+  assert(camel_str == "OnceUponATime").
diff --git a/asteroid/test-suites/action-tests/test012.ast b/asteroid/test-suites/action-tests/test012.ast
new file mode 100644
index 00000000..04121140
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test012.ast
@@ -0,0 +1,8 @@
+  load system io.
+
+  let root = "file".
+  let ext = ".txt".
+
+  for i in 1 to 5 do
+      io @println (root+i+ext).
+  end
diff --git a/asteroid/test-suites/action-tests/test013.ast b/asteroid/test-suites/action-tests/test013.ast
new file mode 100644
index 00000000..a0211b23
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test013.ast
@@ -0,0 +1,22 @@
+  load system io.
+  load system type.
+  load system util.
+  load system pick.
+  load system random.
+
+  random @seed(42).
+
+  -- make up lists of symbols useful for password construction
+  let int_list = [0 to 9] @map(type @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 = ["!","_","#","$","%","*"].
+  -- build the overall pick list of symbols
+  let pick_list = int_list+lc_list+uc_list+sp_list.
+
+  -- generate the password and print it.
+  let pwd = pick @pick pick_list @pick(15)
+                           @join("").
+  io @println pwd.
+
+  assert (pwd == "e3zvshdbS43brt#")
diff --git a/asteroid/test-suites/action-tests/test014.ast b/asteroid/test-suites/action-tests/test014.ast
new file mode 100644
index 00000000..c8b7ad17
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test014.ast
@@ -0,0 +1,26 @@
+  load system io.
+
+  let dna2rna_table =
+      [
+        ("A","U"),
+        ("C","G"),
+        ("G","C"),
+        ("T","A")
+      ].
+
+  function dna2rna with x do
+      for (dna,rna) in dna2rna_table do
+          if x is *dna do
+              return rna.
+          end
+      end
+      throw Error("unknown dna char "+x).
+  end
+
+  let dna_seq = "ACCATCAGTC".
+  let rna_seq = dna_seq @explode()
+                        @map(dna2rna)
+                        @join("").
+  io @println rna_seq.
+
+  assert(rna_seq == "UGGUAGUCAG").
diff --git a/asteroid/test-suites/action-tests/test015.ast b/asteroid/test-suites/action-tests/test015.ast
new file mode 100644
index 00000000..55163256
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test015.ast
@@ -0,0 +1,40 @@
+  load system io.
+  load system util.
+
+  let achar = util @achar.
+  let ascii = util @ascii.
+
+  let encode_table = [119 to 122] @map(achar) + [97 to 118] @map(achar).
+
+  function encode with (v:%string) if len(v) == 1 do
+      -- only lowercase letters are encoded
+      if not (ascii(v) in [97 to 122]) do
+          return v.
+      else
+          return encode_table @(ascii(v)-ascii("a")).
+      end
+  end
+
+  function decode with (v:%string) if len(v) == 1 do
+      -- only lowercase letters are decoded
+      if not (ascii(v) in [97 to 122]) do
+          return v.
+      else
+          return encode_table @(ascii(v)-ascii("w")+4).
+      end
+  end
+
+  let message = "hello, world!"
+  let secret = message @explode()
+                       @map(encode)
+                       @join("").
+  io @println secret.
+
+  assert (secret == "dahhk, sknhz!")
+
+  let decoded_msg = secret @explode()
+                           @map(decode)
+                           @join("").
+  io @println decoded_msg.
+
+  assert (decoded_msg == "hello, world!")
diff --git a/asteroid/test-suites/action-tests/test016.ast b/asteroid/test-suites/action-tests/test016.ast
new file mode 100644
index 00000000..40abab14
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test016.ast
@@ -0,0 +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").
+  end
diff --git a/asteroid/test-suites/action-tests/test017.ast b/asteroid/test-suites/action-tests/test017.ast
new file mode 100644
index 00000000..bfca622a
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test017.ast
@@ -0,0 +1,58 @@
+
+  load system io.
+  load system util.
+  load system hash.
+
+  -- text generated at 'https://www.lipsum.com/'
+  let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
+  accumsan magna quis risus commodo, et pellentesque dui cursus. Sed quis risus
+  libero. Cras et mattis libero, eget varius nisi. Phasellus ultrices, augue non
+  dictum eleifend, nunc elit blandit velit, a viverra risus enim in tellus.
+  Maecenas quis ante eget turpis rhoncus rhoncus eget ut mauris. Suspendisse nec
+  erat sed nunc tempus hendrerit. Nunc dictum nunc molestie eleifend tempus.
+  Praesent cursus lorem diam, sed mattis velit vehicula scelerisque. Nunc iaculis
+  rhoncus ante. Etiam quam nisi, fermentum et euismod a, vulputate eu elit.
+  Suspendisse tincidunt ligula quis interdum blandit. Quisque sed aliquam tellus.
+  Pellentesque ac lacus pulvinar, ornare purus ac, viverra ex. Donec quis pharetra
+  dolor.
+
+  In ac massa tortor. Cras sagittis luctus scelerisque. Morbi a neque sed tortor
+  ultrices dapibus. Mauris pretium vitae massa non auctor. Cras egestas ex ante,
+  ac ullamcorper ante dignissim eget. Fusce bibendum justo ut enim luctus, id
+  volutpat diam lacinia. Mauris sit amet ante risus.
+
+  Nullam rhoncus ultricies dui. Etiam vel metus vehicula, pellentesque felis ut,
+  suscipit nunc. Sed nec interdum lorem. Maecenas odio erat, vestibulum nec
+  dapibus id, commodo vitae libero. Nulla sed urna sit amet nunc commodo finibus
+  sed vel elit. Aliquam euismod feugiat nisi quis placerat. Aliquam libero nisl,
+  ultrices non est at, sagittis hendrerit dui. Quisque id sem lorem. Nam ultricies
+  metus id ultrices molestie. Pellentesque elementum consequat nibh, nec convallis
+  lorem ullamcorper in. Etiam vitae mi tellus. Etiam accumsan massa sit amet dolor
+  tincidunt iaculis. Nam ullamcorper blandit sem id bibendum. Quisque elementum
+  ipsum ac sapien blandit vehicula."
+
+  -- get rid of punctuation, turn to lower case, and split into words.
+  -- Note: we could have employed richer regular expressions to clean up the text here
+  let wl = text @replace("\.","")
+                @replace(",","")
+                @tolower()
+                @split().
+
+  -- 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
+          ht @insert(w,1).
+      else do
+          ht @insert(w,ht @get(w)+1).
+      end
+  end
+
+  -- get the contents of hash table and find the most frequent word
+  let (keys,values) = util @unzip(ht@aslist()).
+  let values_sorted = values @copy()
+                             @sort(true).
+  let most_frequent_word = keys @(values @index(values_sorted @0)).
+  io @println most_frequent_word.
+
+  assert (most_frequent_word == "sed").
diff --git a/asteroid/test-suites/action-tests/test018.ast b/asteroid/test-suites/action-tests/test018.ast
new file mode 100644
index 00000000..b527952a
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test018.ast
@@ -0,0 +1,22 @@
+  load system io.
+
+  let stra = "the quick brown fox jumps over the lazy dog".
+  let strb = "what does the fox say?".
+  let common = "".
+
+  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
+              let common = s.
+          end
+      end
+  end
+
+  if common do
+      io @println ("The longest common substring is '"+common+"'.").
+  else do
+      io @println ("There are no common substrings.").
+  end
+
+  assert (common == " fox ").
diff --git a/asteroid/test-suites/action-tests/test019.ast b/asteroid/test-suites/action-tests/test019.ast
new file mode 100644
index 00000000..a164c34e
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test019.ast
@@ -0,0 +1,18 @@
+  load system io.
+
+  let str1 = "cinema".
+  let str2 = "iceman".
+
+  function normalize with str do
+      return str @explode()
+                 @sort()
+                 @join("").
+  end
+
+  if normalize(str1) == normalize(str2) do
+      io @println "Anagrams".
+  else do
+      io @println "Not anagrams".
+  end
+
+  assert (normalize(str1) == normalize(str2)).
diff --git a/asteroid/test-suites/action-tests/test020.ast b/asteroid/test-suites/action-tests/test020.ast
new file mode 100644
index 00000000..9cefab85
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test020.ast
@@ -0,0 +1,20 @@
+  load system io.
+
+  let str = "Was it a rat I saw?".
+
+  function clean with str:%string do
+      return str @tolower()
+                 @replace("[^a-z]","").
+  end
+
+  -- only keep lower case letters
+  let clean_str = clean(str).
+
+  -- check if it is palidromic
+  if clean_str == clean_str @flip() do
+      io @println "Palindromic".
+  else do
+      io @println "Not palindromic".
+  end
+
+  assert (clean_str == clean_str @flip()).
diff --git a/asteroid/test-suites/action-tests/test021.ast b/asteroid/test-suites/action-tests/test021.ast
new file mode 100644
index 00000000..3035e843
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test021.ast
@@ -0,0 +1,32 @@
+  load system io.
+
+  let str = "Hello, World!".
+
+  function clean with str:%string do
+      return str @tolower()
+                 @replace("[^a-z]","").
+  end
+
+  function palindrome_test with str:%string do
+      let clean_str = clean(str).
+      if clean_str == clean_str @flip() do
+          return true.
+      else do
+          return false.
+      end
+  end
+
+  -- create the moving window over the string
+  let longest_palindrome = "".
+
+  for i in 0 to str @length()-2 do
+      for j in i+1 to str @length()-1 do
+          let str1 = str @[i to j].
+          if palindrome_test(str1) and
+             str1 @length() > longest_palindrome @length() do
+              let longest_palindrome = str1.
+          end
+      end
+  end
+
+  io @println longest_palindrome.
diff --git a/asteroid/test-suites/action-tests/test022.ast b/asteroid/test-suites/action-tests/test022.ast
new file mode 100644
index 00000000..b90110c8
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test022.ast
@@ -0,0 +1,116 @@
+  load system io.
+  load system hash.
+
+  -- text from "www.lipsum.com"
+
+  let str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
+  malesuada sapien nec neque suscipit, non rutrum arcu scelerisque. Nam feugiat
+  sapien porta ipsum accumsan, eget maximus diam volutpat. Pellentesque elementum
+  in orci quis pretium. Donec dignissim nunc lectus, id ornare urna varius ut.
+  Praesent semper faucibus vehicula. Aliquam luctus sapien at lorem malesuada,
+  eget suscipit felis facilisis. Suspendisse velit lectus, mollis sit amet tempor
+  eget, faucibus ut nulla. Vestibulum et elementum dolor, a vehicula ipsum. Morbi
+  ut fringilla nisi. Fusce congue rutrum orci nec porta. Ut laoreet justo vel
+  turpis sodales vehicula. Nulla porttitor nisl id odio eleifend sodales.
+
+  Suspendisse blandit tristique enim id laoreet. Etiam vel aliquet dui, quis
+  tempus magna. Donec blandit volutpat felis egestas tincidunt. Integer placerat
+  luctus mi non pharetra. Donec aliquet nisl orci, egestas elementum nunc bibendum
+  a. Morbi nec risus aliquet, viverra nunc in, molestie odio. Curabitur
+  pellentesque, ante eget dictum aliquam, felis leo bibendum libero, vel bibendum
+  lorem velit eget ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
+  Vestibulum pretium tellus quis ante vulputate, pretium tincidunt ipsum dapibus.
+  Praesent congue, ipsum ut sagittis tempus, lacus nisi dapibus dui, aliquam porta
+  metus odio ut neque. Aliquam vitae faucibus dolor. Nulla iaculis lorem non
+  mauris viverra, ut malesuada nibh aliquam. Nam bibendum sit amet massa in
+  dignissim. Nam posuere nunc ante, at viverra diam rhoncus vel.
+
+  Aliquam mollis sagittis nulla. Maecenas faucibus eu dui eget accumsan.
+  Suspendisse sit amet fermentum sapien. Nunc vitae mi nibh. Mauris condimentum
+  vestibulum imperdiet. Quisque at vehicula dui. Integer sit amet volutpat arcu.
+  Maecenas efficitur leo tortor, non ullamcorper magna tempor non. Sed efficitur
+  quis metus ut pulvinar. Proin nunc felis, congue sit amet nibh placerat,
+  tincidunt mattis nunc. Duis efficitur lacus a orci porttitor, sed molestie risus
+  tempor.
+
+  Sed tincidunt ipsum at urna sollicitudin feugiat. Ut mollis orci quis massa
+  dictum facilisis. Maecenas non elementum mauris. Sed rutrum orci faucibus,
+  tristique nunc nec, mattis ante. Pellentesque habitant morbi tristique senectus
+  et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst.
+  Morbi pellentesque dolor sit amet nunc tincidunt, ut rutrum ante vulputate.
+  Nullam pretium, mi sed condimentum luctus, ipsum nunc dictum lorem, vel
+  ultricies nibh mi ut sem. Nam volutpat id libero eget mollis.
+
+  Vestibulum eget velit eros. Phasellus sit amet vestibulum odio, vel malesuada
+  quam. Mauris dictum erat eu ligula mollis laoreet. Phasellus ut ante auctor,
+  hendrerit ipsum et, fermentum magna. Etiam nec eros elementum, consectetur nibh
+  ac, ullamcorper ligula. Aliquam sed porttitor sapien. Nulla tincidunt, turpis
+  vitae venenatis aliquet, quam purus elementum diam, in tincidunt orci diam sed
+  nulla. Cras pellentesque non diam quis sollicitudin. Duis suscipit lectus dui,
+  eu varius metus pretium sit amet.
+
+  Nulla eu ex velit. Ut non justo semper, gravida erat quis, vehicula est.
+  Suspendisse nunc dui, iaculis id purus sit amet, rutrum commodo lacus. Aenean
+  consequat turpis a est vestibulum, ac accumsan nibh dapibus. Nam blandit
+  scelerisque lectus, eu pellentesque arcu ornare non. Fusce ac gravida diam. Ut
+  in fringilla eros. Sed metus augue, porta quis vehicula at, pellentesque et
+  mauris. Duis sodales lacus sit amet condimentum placerat. In blandit tristique
+  nulla eget malesuada. Sed congue finibus neque at semper. Etiam pellentesque
+  egestas urna, ut lobortis odio euismod et. Phasellus aliquet quam purus, quis
+  ullamcorper sem mollis eu.
+
+  Mauris quis ullamcorper nisi. Aenean quam nulla, sodales eu faucibus in, mattis
+  a nulla. Nullam pulvinar pretium justo eu mattis. Aliquam rutrum ipsum vitae leo
+  maximus ultrices. Donec ut pulvinar nisi. Sed pharetra, turpis dictum lobortis
+  egestas, quam massa venenatis enim, dapibus efficitur dolor mauris eu felis.
+  Donec vulputate ultrices justo sit amet condimentum. Donec id posuere nulla. In
+  vestibulum mi in lectus commodo dignissim. Quisque vestibulum egestas arcu sit
+  amet finibus. Proin commodo aliquet neque quis maximus.
+
+  Nulla facilisi. Sed gravida aliquet diam in congue. Mauris vehicula justo ac
+  sollicitudin laoreet. Mauris enim mi, auctor id magna eget, feugiat sollicitudin
+  leo. Vivamus ornare ornare commodo. Suspendisse ut dui quis enim porta pretium.
+  Praesent vitae lacus fermentum, posuere orci ac, imperdiet massa. Nulla
+  hendrerit id nisl sed maximus. Vivamus commodo lacus eu condimentum bibendum.
+  Suspendisse porttitor sem eget dolor aliquet congue. Pellentesque tristique
+  augue at quam hendrerit dignissim. Aenean a congue dui. Vestibulum ante ipsum
+  primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer ante
+  lacus, commodo et enim sed, auctor egestas metus.
+
+  Aliquam a urna id risus tincidunt rutrum. Nunc facilisis, tortor ac suscipit
+  aliquam, ante neque tincidunt mi, nec ullamcorper lectus ligula vel urna.
+  Suspendisse lobortis at felis sit amet facilisis. Pellentesque velit lacus,
+  porttitor vitae eros rutrum, convallis blandit erat. Pellentesque nec mi
+  viverra, volutpat dui in, rutrum lacus. Ut non venenatis leo. Praesent
+  sollicitudin magna porttitor lorem elementum molestie non a turpis. Suspendisse
+  potenti.
+
+  Donec malesuada iaculis laoreet. Nunc ut volutpat ante, ut consequat tortor.
+  Phasellus posuere, ipsum quis dignissim iaculis, nisl felis ullamcorper ligula,
+  quis placerat sem sapien nec ante. Cras suscipit ut magna nec lacinia. Donec
+  ipsum nibh, imperdiet non aliquam eu, maximus id ante. Pellentesque vitae felis
+  felis. Aliquam et diam sed nulla volutpat vestibulum molestie non lacus.
+  Praesent porta et lacus auctor fermentum. In hac habitasse platea dictumst.
+  Aliquam erat volutpat. Etiam at ligula orci. Class aptent taciti sociosqu ad
+  litora torquent per conubia nostra, per inceptos himenaeos."
+
+  let word_list = str @tolower()
+                      @replace("[^a-z0-9_]"," ")
+                      @split().
+  let ht = hash @hash().
+
+  -- create N-grams
+  for i in 0 to word_list @length()-3 do
+      -- 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
+          ht @insert(n_gram,1).
+      else do
+          ht @insert(n_gram,ht @get(n_gram)+1).
+      end
+  end
+
+  for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
+      io @println (n_gram+": "+cnt).
+  end
diff --git a/asteroid/test-suites/action-tests/test023.ast b/asteroid/test-suites/action-tests/test023.ast
new file mode 100644
index 00000000..21087323
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test023.ast
@@ -0,0 +1,4 @@
+  load system io.
+  load system math. -- definition of pi
+
+  io @println (math @pi).
diff --git a/asteroid/test-suites/action-tests/test024.ast b/asteroid/test-suites/action-tests/test024.ast
new file mode 100644
index 00000000..d2d1e37b
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test024.ast
@@ -0,0 +1,7 @@
+  load system io.
+  load system math.
+
+  io @println (math @e).
+  io @println (math @tau). -- tau=2*pi
+
+  assert (math @tau == 2 * math @pi)
diff --git a/asteroid/test-suites/action-tests/test025.ast b/asteroid/test-suites/action-tests/test025.ast
new file mode 100644
index 00000000..fd115097
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test025.ast
@@ -0,0 +1,6 @@
+  load system io.
+
+  let n = 3.
+  let fact = [1 to n] @reduce(lambda with (a,b) do return a*b).
+  io @println fact.
+  assert (fact == 6).
diff --git a/asteroid/test-suites/action-tests/test026.ast b/asteroid/test-suites/action-tests/test026.ast
new file mode 100644
index 00000000..74f53e4b
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test026.ast
@@ -0,0 +1,16 @@
+  load system io.
+
+  let POS_INT = pattern with (x:%integer) if x > 0.
+  let NEG_INT = pattern with (x:%integer) if x < 0.
+
+  function fact
+      with 0 do
+          return 1
+      with n:*POS_INT do
+          return n * fact (n-1).
+      with n:*NEG_INT do
+          throw Error("factorial is not defined for "+n).
+      end
+
+  io @println ("The factorial of 3 is: " + fact (3)).
+  assert (fact(3) == 6).
diff --git a/asteroid/test-suites/action-tests/test027.ast b/asteroid/test-suites/action-tests/test027.ast
new file mode 100644
index 00000000..866df045
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test027.ast
@@ -0,0 +1,11 @@
+  load system io.
+
+  let n = 10. -- compute the 10th Fib number
+
+  let (f_1,f_2) = (1,1).
+  for i in 3 to n do
+      let (f_1,f_2) = (f_1+f_2,f_1).
+  end
+
+  io @println f_1.
+  assert (f_1 == 55)
diff --git a/asteroid/test-suites/action-tests/test028.ast b/asteroid/test-suites/action-tests/test028.ast
new file mode 100644
index 00000000..ed843ae3
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test028.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let sq = [1 to 10] @map(lambda with x do return x*x).
+
+  io @println sq.
+
+  assert (sq == [1,4,9,16,25,36,49,64,81,100])
diff --git a/asteroid/test-suites/action-tests/test029.ast b/asteroid/test-suites/action-tests/test029.ast
new file mode 100644
index 00000000..45d7fd2b
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test029.ast
@@ -0,0 +1,8 @@
+  load system io.
+  load system math.
+
+  let p2 = [0 to 9] @map(lambda with x do return math @pow(2,x)).
+
+  io @println p2.
+
+  assert (p2 == [1,2,4,8,16,32,64,128,256,512])
diff --git a/asteroid/test-suites/action-tests/test030.ast b/asteroid/test-suites/action-tests/test030.ast
new file mode 100644
index 00000000..58361425
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test030.ast
@@ -0,0 +1,10 @@
+  load system io.
+  load system math.
+
+  let odd = []
+  for (n if math @mod(n,2) =/= 0) in 1 to 10 do
+      let odd = odd + [n].
+  end
+
+  io @println odd.
+  assert(odd == [1,3,5,7,9])
diff --git a/asteroid/test-suites/action-tests/test031.ast b/asteroid/test-suites/action-tests/test031.ast
new file mode 100644
index 00000000..1403ccfd
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test031.ast
@@ -0,0 +1,10 @@
+  load system io.
+  load system math.
+
+  let even = []
+  for (n if math @mod(n,2) == 0) in 1 to 10 do
+      let even = even + [n].
+  end
+
+  io @println even.
+  assert(even == [2,4,6,8,10])
diff --git a/asteroid/test-suites/action-tests/test032.ast b/asteroid/test-suites/action-tests/test032.ast
new file mode 100644
index 00000000..18e849e9
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test032.ast
@@ -0,0 +1,8 @@
+  load system io.
+  load system math.
+
+  -- not equal under the default tolerance of 1E-09
+  assert (not math @isclose(2.0,2.00001)).
+
+  -- equal under the user defined tolerance of 0.0001
+  assert (math @isclose(2.0,2.00001,0.0001)).
diff --git a/asteroid/test-suites/action-tests/test033.ast b/asteroid/test-suites/action-tests/test033.ast
new file mode 100644
index 00000000..4f14055b
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test033.ast
@@ -0,0 +1,21 @@
+  load system io.
+  load system math.
+
+  function isprime with x do
+      if x >= 2 do
+          for y in range(2,x) do
+              if not math @mod(x,y) do
+                  return false.
+              end
+          end
+      else do
+          return false.
+      end
+      return true.
+  end
+
+  io @println (isprime 17).
+  io @println (isprime 15).
+
+  assert (isprime(17)).
+  assert (not isprime(15)).
diff --git a/asteroid/test-suites/action-tests/test034.ast b/asteroid/test-suites/action-tests/test034.ast
new file mode 100644
index 00000000..e739bf6b
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test034.ast
@@ -0,0 +1,24 @@
+  load system io.
+  load system math.
+
+  function isprime with x do
+      if x >= 2 do
+          for y in range(2,x) do
+              if not math @mod(x,y) do
+                  return false.
+              end
+          end
+      else do
+          return false.
+      end
+      return true.
+  end
+
+  let cnt = 0.
+  for (n if isprime(n)) in 1 to 1000000 do
+      io @println n.
+      let cnt = cnt+1.
+      if cnt == 10 do
+          break.
+      end
+  end
diff --git a/asteroid/test-suites/action-tests/test035.ast b/asteroid/test-suites/action-tests/test035.ast
new file mode 100644
index 00000000..f5951893
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test035.ast
@@ -0,0 +1,41 @@
+  load system io.
+  load system math.
+
+  function isprime with x do
+      if x >= 2 do
+          for y in range(2,x) do
+              if not math @mod(x,y) do
+                  return false.
+              end
+          end
+      else do
+          return false.
+      end
+      return true.
+  end
+
+  function primes with x do
+      let lp = [].
+      for (n if isprime(n)) in 1 to x do
+          let lp = lp+[n].
+      end
+      return lp.
+  end
+
+  let n = 165.
+  let factors = [].
+  let primes_list =  primes(n).
+  let ix = 0.
+
+  while n > 1 do
+      let factor = primes_list @ix.
+      let ix = ix+1.
+      if not math @mod(n,factor) do
+          let ix = 0.
+          let n = n/factor.
+          let factors = factors+[factor].
+      end
+  end
+  io @println factors.
+
+  assert (factors == [3,5,11])
diff --git a/asteroid/test-suites/action-tests/test036.ast b/asteroid/test-suites/action-tests/test036.ast
new file mode 100644
index 00000000..a117d4ff
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test036.ast
@@ -0,0 +1,16 @@
+  load system io.
+  load system math.
+
+  -- fraction a/b
+  let a = 16.
+  let b = 280.
+
+  -- reduce fraction
+  let gcd_val = math @gcd(a,b).
+  let numerator = a/gcd_val.
+  let denominator = b/gcd_val.
+  io @println numerator.
+  io @println denominator.
+
+  -- show that original and reduced fraction are the same value
+  assert (a/b == numerator/denominator).
diff --git a/asteroid/test-suites/action-tests/test037.ast b/asteroid/test-suites/action-tests/test037.ast
new file mode 100644
index 00000000..eb4a43d6
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test037.ast
@@ -0,0 +1,8 @@
+  load system io.
+
+  try
+      io @println (42/0).
+  catch Exception(_,m) do
+      io @println m.
+  end
+  io @println "We are still alive...".
diff --git a/asteroid/test-suites/action-tests/test038.ast b/asteroid/test-suites/action-tests/test038.ast
new file mode 100644
index 00000000..9ba4e8b0
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test038.ast
@@ -0,0 +1,17 @@
+  load system io.
+  load system random.
+  load system util.
+  load system type.
+
+  let randint = random @randint.
+
+  random @seed(42).
+
+  io @println (random @random()).          -- random value in [0.0,1.0)
+  io @println (randint(0.0,1.0)).  -- random value in [0.0,1.0]
+  io @println (randint(0,1)).      -- always 0 or 1
+
+  -- generating a random number in the appropriate interval
+  let n = 10.
+  io @println (randint(0.0,type @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
new file mode 100644
index 00000000..ff6e72b8
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test039.ast
@@ -0,0 +1,17 @@
+  load system io.
+  load system util.
+  load system type.
+
+  let n = 1234.
+  let sq = n*n.
+  let sq_str = type @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).
+  io @println rval.
+
+  assert (rval == 5227)
diff --git a/asteroid/test-suites/action-tests/test040.ast b/asteroid/test-suites/action-tests/test040.ast
new file mode 100644
index 00000000..24af6d35
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test040.ast
@@ -0,0 +1,11 @@
+  load system io.
+  load system random.
+
+  let hist = [0 to 9] @map(lambda with _ do return 0).
+
+  for _ in range(10000) do
+      let ix = random @randint(0,9).
+      let hist @ix = hist @ix +1
+  end
+
+  io @println hist.
diff --git a/asteroid/test-suites/action-tests/test041.ast b/asteroid/test-suites/action-tests/test041.ast
new file mode 100644
index 00000000..5b8ac6be
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test041.ast
@@ -0,0 +1,9 @@
+  load system io.
+  load system math.
+
+  let x = [10, 3].
+  let y = [9, 1].
+  let d = (math @sqrt(math @pow(x@0-y@0,2) + math @pow(x@1-y@1,2))).
+  io @println d.
+
+  assert (d == 2.23606797749979)
diff --git a/asteroid/test-suites/action-tests/test042.ast b/asteroid/test-suites/action-tests/test042.ast
new file mode 100644
index 00000000..970e5fed
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test042.ast
@@ -0,0 +1,11 @@
+  load system io.
+  load system math.
+  load system vector.
+
+  let x = [10, 3].
+  let y = [9, 1].
+  let a = vector @sub(x,y).
+  let d = math @sqrt(vector @dot(a,a)).
+  io @println d.
+
+  assert (d == 2.23606797749979)
diff --git a/asteroid/test-suites/action-tests/test043.ast b/asteroid/test-suites/action-tests/test043.ast
new file mode 100644
index 00000000..65d1b8f7
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test043.ast
@@ -0,0 +1,13 @@
+  load system io.
+  load system math.
+
+  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 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).
+  io @println sigma.
+
+  assert (sigma == 420.96248961952256)
diff --git a/asteroid/test-suites/action-tests/test044.ast b/asteroid/test-suites/action-tests/test044.ast
new file mode 100644
index 00000000..a9139b18
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test044.ast
@@ -0,0 +1,29 @@
+  load system io.
+  load system math.
+
+  -- define common math functions locally so the
+  -- formulas are easy to read
+  let cos = math @cos.
+  let sin = math @sin.
+  let sqrt = math @sqrt.
+  let pow = math @pow.
+  let atan = math @atan.
+
+  function polar_to_cartesian with (r,psi) do
+      -- return a tuple: (x,y)
+      return (r*cos(psi),r*sin(psi)).
+  end
+
+  function cartesian_to_polar with (x,y) do
+      -- return a tuple: (r,psi)
+      return (sqrt(pow(x,2)+pow(y,2)),atan(y/x)).
+  end
+
+  let (r,psi) = cartesian_to_polar(1,2).
+  let (x,y) = polar_to_cartesian(r,psi).
+
+  io @println (x,y).
+
+  -- show that the recovered coordinates are the same
+  -- we started with
+  assert (math @isclose(1,x,0.0001) and math @isclose(2,y,0.0001)).
diff --git a/asteroid/test-suites/action-tests/test045.ast b/asteroid/test-suites/action-tests/test045.ast
new file mode 100644
index 00000000..3f23b73c
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test045.ast
@@ -0,0 +1,47 @@
+  load system io.
+  load system math.
+  load system util.
+  load system type.
+
+  -- define common math functions locally so the
+  -- formulas are easy to read
+  let cos = math @cos.
+  let sin = math @sin.
+  let sqrt = math @sqrt.
+  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)
+      return (r*cos(psi),r*sin(psi)).
+  end
+
+  function cartesian_to_polar with (x,y) do
+      return (sqrt(pow(x,2)+pow(y,2)),cartesian_to_psi(x,y)).
+  end
+
+  function cartesian_to_psi
+      with (x,y) if x > 0  do
+          return atan(toreal(y)/x).
+      with (x,y) if x < 0 and y >= 0 do
+          return atan(toreal(y)/x)+pi.
+      with (x,y) if x < 0 and y < 0 do
+          return atan(toreal(y)/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
+          return -pi/2.
+      with (x,y) if x == 0 and y == 0 do
+          return none.
+      end
+
+  let (r,psi) = cartesian_to_polar(-3,5).
+  let (x,y) = polar_to_cartesian(r,psi).
+
+  io @println (x,y).
+
+  -- show that the recovered coordinates are the same
+  -- we started with
+  assert (math @isclose(-3,x,0.0001) and math @isclose(5,y,0.0001)).
diff --git a/asteroid/test-suites/action-tests/test046.ast b/asteroid/test-suites/action-tests/test046.ast
new file mode 100644
index 00000000..0876a4eb
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test046.ast
@@ -0,0 +1,22 @@
+  load system io.
+  load system math.
+  load system random.
+
+  let sqrt = math @sqrt.
+  let pow = math @pow.
+  let randint = random @randint.
+
+  random @seed(42).
+
+  let inside = 0.
+  let n = 10000.
+  for _ in 1 to n do
+      let point = (randint(-1.0,1.0),randint(-1.0,1.0)).
+      if sqrt(pow(point@0,2)+pow(point@1,2)) <= 1.0 do
+          let inside = inside+1.
+      end
+  end
+  let area = 4.0 * inside / n.
+  io @println area.
+
+  assert (area == 3.1392).
diff --git a/asteroid/test-suites/action-tests/test047-io.txt b/asteroid/test-suites/action-tests/test047-io.txt
new file mode 100644
index 00000000..021ea30c
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test047-io.txt
@@ -0,0 +1,2 @@
+10
+
diff --git a/asteroid/test-suites/action-tests/test047.ast b/asteroid/test-suites/action-tests/test047.ast
new file mode 100644
index 00000000..b04b5155
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test047.ast
@@ -0,0 +1,18 @@
+  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: ")).
+  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: ")).
+  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
new file mode 100644
index 00000000..0984ee04
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test048.ast
@@ -0,0 +1,8 @@
+  load system io.
+  load system type.
+
+  let bin = "101101".
+  let int = type @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
new file mode 100644
index 00000000..fd0656c3
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test049.ast
@@ -0,0 +1,16 @@
+  load system io.
+  load system type.
+
+  let tobase = type @tobase.
+  let tointeger = type @tointeger.
+
+  let val = 42.
+
+  io @println (tobase(val,2)).  -- bin
+  io @println (tobase(val,8)).  -- oct
+  io @println (tobase(val,16)). -- hex
+
+  -- make sure that conversions are correct in both directions
+  assert (tointeger(tobase(val,2),2) == val).
+  assert (tointeger(tobase(val,8),8) == val).
+  assert (tointeger(tobase(val,16),16) == val).
diff --git a/asteroid/test-suites/action-tests/test050.ast b/asteroid/test-suites/action-tests/test050.ast
new file mode 100644
index 00000000..4b3838b0
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test050.ast
@@ -0,0 +1,12 @@
+  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).
+  io @println s.
+
+  assert (s == 49).
diff --git a/asteroid/test-suites/action-tests/test051.ast b/asteroid/test-suites/action-tests/test051.ast
new file mode 100644
index 00000000..6eb6139f
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test051.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let bits = "1010101" @replace("0","")
+                       @length().
+  io @println bits.
+
+  assert (bits == 4).
diff --git a/asteroid/test-suites/action-tests/test052.ast b/asteroid/test-suites/action-tests/test052.ast
new file mode 100644
index 00000000..5d41c460
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test052.ast
@@ -0,0 +1,7 @@
+  load system io.
+  load system type.
+
+  let a = type @tointeger([67, 8, 1, 5, 45] @map(type @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
new file mode 100644
index 00000000..4f35a8de
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test053.ast
@@ -0,0 +1,26 @@
+  load system io.
+  load system math.
+  load system util.
+  load system hash.
+  load system type.
+
+  let roman_hash = hash @hash().
+  roman_hash @insert(1000,["","M","MM","MMM"]).
+  roman_hash @insert(100,["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]).
+  roman_hash @insert(10,["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"]).
+  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).
+  io @println z.
+  let roman = "".
+  for (d,p) in z do
+      let roman = roman + roman_hash @get(p) @d.
+  end
+  io @println roman.
+
+  assert (roman == "MMXVIII")
diff --git a/asteroid/test-suites/action-tests/test054.ast b/asteroid/test-suites/action-tests/test054.ast
new file mode 100644
index 00000000..9a12bd9d
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test054.ast
@@ -0,0 +1,33 @@
+  load system io.
+  load system math.
+
+  let mod = math @mod.
+
+  let names = ["zero","one","two","three","four","five","six","seven","eight","nine",
+               "ten","eleven","twelve","thirteen","fourteen","fifteen",
+               "sixteen","seventeen","eighteen","nineteen","twenty","thirty",
+               "forty","fifty","sixty","seventy","eighty","ninety"].
+
+  function spell_number
+      with (n:%integer) if n < 20 do
+          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 "".
+          return r.
+      with (n:%integer) if n < 1000 do
+          return spell_part(n,100,"hundred").
+      with (n:%integer) if n < 1000000 do
+          return spell_part(n,1000,"thousand").
+      end
+
+  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.
+      end
+
+  io @println (spell_number 15).
+  io @println (spell_number 75).
+  io @println (spell_number 987654).
+  io @println (spell_number 1001).
diff --git a/asteroid/test-suites/action-tests/test055.ast b/asteroid/test-suites/action-tests/test055.ast
new file mode 100644
index 00000000..09efbd39
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test055.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let (a,b) = (10,20).
+  let (b,a) = (a,b).
+  io @println ("a = "+a,"b = "+b).
+
+  assert ((a,b) is (20,10)).
diff --git a/asteroid/test-suites/action-tests/test056.ast b/asteroid/test-suites/action-tests/test056.ast
new file mode 100644
index 00000000..ae6e762c
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test056.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let a = [3,5,7,4].
+  let (a@2,a@3) = (a@3,a@2).
+  io @println a.
+
+  assert (a is [3,5,4,7]).
diff --git a/asteroid/test-suites/action-tests/test057.ast b/asteroid/test-suites/action-tests/test057.ast
new file mode 100644
index 00000000..ece36a05
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test057.ast
@@ -0,0 +1,6 @@
+  load system io.
+
+  let a = [10, 20, 30, 40, 50].
+  io @println (a @reverse()).
+
+  assert(a == [50,40,30,20,10]).
diff --git a/asteroid/test-suites/action-tests/test058.ast b/asteroid/test-suites/action-tests/test058.ast
new file mode 100644
index 00000000..38711499
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test058.ast
@@ -0,0 +1,18 @@
+  load system io.
+  load system math.
+
+  function rotate with (l:%list,i:%integer) do
+      let n = l @length().
+      let vix = range n @map(lambda with x do return math @mod(x+i,n)).
+      return l @vix.
+  end
+
+
+  let a = [1, 3, 5, 7, 9, 11, 13, 15].
+  let b = rotate(a,3).
+  let c = rotate(a,-3).
+  io @println a.
+  io @println b.
+  io @println c.
+
+  assert(b == [7,9,11,13,15,1,3,5] and c == [11,13,15,1,3,5,7,9]).
diff --git a/asteroid/test-suites/action-tests/test059.ast b/asteroid/test-suites/action-tests/test059.ast
new file mode 100644
index 00000000..b460fca6
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test059.ast
@@ -0,0 +1,8 @@
+  load system io.
+  load system random.
+
+  random @seed(42).
+  let b = [1 to 20] @shuffle().
+  io @println b.
+
+  assert(b == [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]).
diff --git a/asteroid/test-suites/action-tests/test060.ast b/asteroid/test-suites/action-tests/test060.ast
new file mode 100644
index 00000000..c38c4e9b
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test060.ast
@@ -0,0 +1,8 @@
+  load system io.
+  load system vector.
+
+  let a = [1 to 10].
+  let b = vector @add(a,1).
+  io @println b.
+
+  assert(b == [2,3,4,5,6,7,8,9,10,11]).
diff --git a/asteroid/test-suites/action-tests/test061.ast b/asteroid/test-suites/action-tests/test061.ast
new file mode 100644
index 00000000..96b987df
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test061.ast
@@ -0,0 +1,9 @@
+  load system io.
+  load system vector.
+
+  let a = [10 to 20].
+  let b = [30 to 40].
+  let c = vector @add(a,b).
+  io @println c.
+
+  assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
diff --git a/asteroid/test-suites/action-tests/test062.ast b/asteroid/test-suites/action-tests/test062.ast
new file mode 100644
index 00000000..5cafb0a5
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test062.ast
@@ -0,0 +1,9 @@
+  load system io.
+  load system vector.
+
+  let a = [10 to 20].
+  let b = [30 to 40].
+  let c = vector @op((lambda with (x,y) do return x+y),a,b).
+  io @println c.
+
+  assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
diff --git a/asteroid/test-suites/action-tests/test063.ast b/asteroid/test-suites/action-tests/test063.ast
new file mode 100644
index 00000000..0e1785fa
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test063.ast
@@ -0,0 +1,12 @@
+  load system io.
+  load system vector.
+  load system random.
+
+  random @seed(42).
+
+  let a = [1 to 10] @shuffle().
+  let b = [1 to 10] @shuffle().
+  let c = vector @op((lambda with (x,y) do return x<y),a,b).
+  io @println c.
+
+  assert(c == [false,true,false,false,false,true,false,false,true,true]).
diff --git a/asteroid/test-suites/action-tests/test064.ast b/asteroid/test-suites/action-tests/test064.ast
new file mode 100644
index 00000000..b95d0b18
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test064.ast
@@ -0,0 +1,9 @@
+  load system io.
+  load system set.
+
+  let a = [1 to 10].
+  let b = [5 to 15].
+  let c = set @diff(a,b).
+  io @println c.
+
+  assert(c @sort() == [1,2,3,4]).
diff --git a/asteroid/test-suites/action-tests/test065.ast b/asteroid/test-suites/action-tests/test065.ast
new file mode 100644
index 00000000..2b0e0dde
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test065.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
+  let s = a @reduce(lambda with (x,y) do return x+y).
+  io @println s.
+
+  assert (s == 125).
diff --git a/asteroid/test-suites/action-tests/test066.ast b/asteroid/test-suites/action-tests/test066.ast
new file mode 100644
index 00000000..df6032bc
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test066.ast
@@ -0,0 +1,8 @@
+  load system io.
+
+  let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
+  let f = (lambda with (x,y) do return x+(y if y > 10 else 0)).
+  let s = a @reduce(f,0).
+  io @println s.
+
+  assert (s == 92).
diff --git a/asteroid/test-suites/action-tests/test067.ast b/asteroid/test-suites/action-tests/test067.ast
new file mode 100644
index 00000000..b35f0b71
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test067.ast
@@ -0,0 +1,7 @@
+  load system io.
+
+  let a = [7, 11, 34, 50, 200].
+  let avg = a @reduce(lambda with (x,y) do return x+y)/a @length().
+  io @println avg.
+
+  assert (avg == 60).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test068.ast b/asteroid/test-suites/action-tests/test068.ast
similarity index 85%
rename from asteroid/test-suites/using-asteroid-tests/programs/test068.ast
rename to asteroid/test-suites/action-tests/test068.ast
index 1305c469..4441301e 100644
--- a/asteroid/test-suites/using-asteroid-tests/programs/test068.ast
+++ b/asteroid/test-suites/action-tests/test068.ast
@@ -1,10 +1,9 @@
+load system io.
+load system random.
 
-load "io".
-load "random".
+random @seed(42).
 
-seed(42).
-
--- Asteroid allows the user to escape to the Python 
+-- Asteroid allows the user to escape to the Python
 -- ecosystem.  Here we use this to construct a
 -- plot of the moving average
 function plot with (dt,avg) do escape
@@ -44,7 +43,8 @@ plt.legend(labels =['Data', 'Moving Average'], fontsize=14)
 plt.title('Moving Average', fontsize=20)
 plt.xlabel('Instance', fontsize=16)
 plt.ylabel('Value', fontsize=16)
-plt.show()
+#plt.show()
+plt.savefig('action-tests/action-test68.png')
 "
 end
 
@@ -58,7 +58,7 @@ function sum with lst:%list do
     return lst @reduce(lambda with (x,y) do return x+y).
 end
 
-let dt = [1 to 100] @map(lambda with _ do return random()).
+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).
 
 plot(dt @[3 to 96],mavg).
diff --git a/asteroid/test-suites/action-tests/test069.ast b/asteroid/test-suites/action-tests/test069.ast
new file mode 100644
index 00000000..8a1c090f
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test069.ast
@@ -0,0 +1,5 @@
+  load system io.
+
+  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")).
diff --git a/asteroid/test-suites/action-tests/test070.ast b/asteroid/test-suites/action-tests/test070.ast
new file mode 100644
index 00000000..779bb07e
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test070.ast
@@ -0,0 +1,10 @@
+  load system io.
+
+  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").
+  else
+      io @println (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
new file mode 100644
index 00000000..a8127013
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test071.ast
@@ -0,0 +1,10 @@
+  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).
+  io @println odd.
diff --git a/asteroid/test-suites/action-tests/test072.ast b/asteroid/test-suites/action-tests/test072.ast
new file mode 100644
index 00000000..2d5b867d
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test072.ast
@@ -0,0 +1,7 @@
+  load system io.
+  load system math.
+
+  let array = [20 to 30] @filter(lambda with x do return math @mod(x,2)).
+  io @println array.
+
+  assert (array == [21,23,25,27,29]).
diff --git a/asteroid/test-suites/action-tests/test073.ast b/asteroid/test-suites/action-tests/test073.ast
new file mode 100644
index 00000000..245bef34
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test073.ast
@@ -0,0 +1,8 @@
+  load system io.
+  load system math.
+
+  let a = [20 to 30].
+  let array = a @[1 to a @length()-1 stride 2] .
+  io @println array.
+
+  assert (array == [21,23,25,27,29]).
diff --git a/asteroid/test-suites/action-tests/test074.ast b/asteroid/test-suites/action-tests/test074.ast
new file mode 100644
index 00000000..ba66c464
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test074.ast
@@ -0,0 +1,18 @@
+  load system io.
+  load system math.
+
+  let dt = ["apple",
+            "pear",
+            "grape",
+            "lemon",
+            "peach",
+            "apple",
+            "banana",
+            "grape",
+            "pineapple",
+            "avocado"].
+            
+  let cnt = dt @count("grape").
+  io @println cnt.
+
+  assert (cnt == 2).
diff --git a/asteroid/test-suites/action-tests/test075.ast b/asteroid/test-suites/action-tests/test075.ast
new file mode 100644
index 00000000..198f25bc
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test075.ast
@@ -0,0 +1,12 @@
+  load system io.
+  load system set.
+
+  function unique with lst:%list do
+      return set @toset lst @sort().
+  end
+
+  let a = unique([2, 3, 7, 4, 5, 5, 6, 2, 10, 7]).
+
+  io @println a.
+
+  assert (a == [2,3,4,5,6,7,10])
diff --git a/asteroid/test-suites/action-tests/test076.ast b/asteroid/test-suites/action-tests/test076.ast
new file mode 100644
index 00000000..98c1de1a
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test076.ast
@@ -0,0 +1,19 @@
+  load system io.
+
+  function max with lst:%list do
+      return lst @sort(true) @0.
+  end
+
+  function min with lst:%list do
+      return lst @sort() @0.
+  end
+
+  let v = [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
+  
+  let a = max v.
+  let b = min v.
+
+  io @println a.
+  io @println b.
+
+  assert (a == 15 and b == 2).
diff --git a/asteroid/test-suites/action-tests/test077.ast b/asteroid/test-suites/action-tests/test077.ast
new file mode 100644
index 00000000..8581896a
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test077.ast
@@ -0,0 +1,9 @@
+  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)).
+
+  io @println b.
+
+  assert (b).
diff --git a/asteroid/test-suites/action-tests/test078.ast b/asteroid/test-suites/action-tests/test078.ast
new file mode 100644
index 00000000..e7863b20
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test078.ast
@@ -0,0 +1,59 @@
+  load system io.
+
+  function transpose with m do
+      -- figure out the dimensions
+      let xdim = m @0 @length().
+      let ydim = m @length().
+
+      -- reserve space for the transpose
+      -- first we do the ydim of new matrix
+      let mt = range(xdim).
+      for y in mt do
+          let mt @y = range(ydim).
+      end
+
+      -- swap the elements
+      for x in range(xdim) do
+          for y in range(ydim) do
+              let mt @x @y = m @y @x.
+          end
+      end
+
+      return mt.
+  end
+
+  function print_matrix with m do
+      io @println "".
+      for r in m do
+          for e in r do
+              io @print (e + " ").
+          end
+          io @println ("").
+      end
+      io @println "".
+  end
+
+  let m = [[1,2],
+           [3,4]].
+
+  let mt = transpose(m).
+
+  io @println ("The transpose of:").
+  print_matrix m.
+  io @println ("is:").
+  print_matrix mt.
+  io @println ("").
+
+  let m = [[1,2],
+           [3,4],
+           [5,6]].
+
+  let mt = transpose(m).
+
+  io @println ("The transpose of:").
+  print_matrix m.
+  io @println ("is:").
+  print_matrix mt.
+  io @println ("").
+
+  assert(mt == [[1,3,5],[2,4,6]]).
diff --git a/asteroid/test-suites/action-tests/test079.ast b/asteroid/test-suites/action-tests/test079.ast
new file mode 100644
index 00000000..4e3e6a4f
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test079.ast
@@ -0,0 +1,30 @@
+  load system io.
+  load system hash.
+  load system sort.
+  load system random.
+
+  let randint = random @randint.
+
+  random @seed(42).
+
+  -- hash of names with ages
+  let ht = hash @hash().
+  ht @insert("Billie",randint(20,50)).
+  ht @insert("Joe",randint(20,50)).
+  ht @insert("Pete",randint(20,50)).
+  ht @insert("Brandi",randint(20,50)).
+
+  -- export the hash as a list of pairs
+  let lst = ht @aslist().
+
+  -- define our order predicate on a
+  -- list of pairs where the second
+  -- component holds the order info
+  function pairs with ((_,x),(_,y)) do
+      return true if x < y else false.
+  end
+
+  -- print out the sorted list
+  io @println (sort @sort(pairs,lst)).
+
+  assert (sort @sort(pairs,lst) == [("Pete",20),("Joe",23),("Billie",40),("Brandi",43)])
diff --git a/asteroid/test-suites/action-tests/test080.ast b/asteroid/test-suites/action-tests/test080.ast
new file mode 100644
index 00000000..d5a245c8
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test080.ast
@@ -0,0 +1,33 @@
+  load system io.
+  load system hash.
+  load system sort.
+
+  let fruit_hash = hash @hash().
+  fruit_hash @insert("apple","red").
+  fruit_hash @insert("avocado","green").
+  fruit_hash @insert("banana","yellow").
+  fruit_hash @insert("grapefruit","orange").
+  fruit_hash @insert("grapes","green").
+  fruit_hash @insert("kiwi","green").
+  fruit_hash @insert("lemon","yellow").
+  fruit_hash @insert("orange","orange").
+  fruit_hash @insert("pear","green").
+  fruit_hash @insert("plum","purple").
+
+  let fruit_lst = fruit_hash @aslist().
+
+  let color_hash = hash @hash().
+  for (_,color) in fruit_lst do
+      if not color_hash @get(color) do
+          color_hash @insert(color,1).
+      else
+          color_hash @insert(color, color_hash @get(color) +1).
+      end
+  end
+  let color_lst = color_hash @aslist().
+
+  function pairs with ((_,x),(_,y)) do
+      return true if x < y else false.
+  end
+
+  io @println (sort @sort(pairs,color_lst)).
diff --git a/asteroid/test-suites/action-tests/test081.ast b/asteroid/test-suites/action-tests/test081.ast
new file mode 100644
index 00000000..403b2f71
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test081.ast
@@ -0,0 +1,12 @@
+  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.
+  end
+
+  for i in 1 to 10 do
+      io @println ([1 to 10] @map(lambda with x do return format(i*x)) @join(" ")).
+  end
diff --git a/asteroid/test-suites/action-tests/test082.ast b/asteroid/test-suites/action-tests/test082.ast
new file mode 100644
index 00000000..009dcdb9
--- /dev/null
+++ b/asteroid/test-suites/action-tests/test082.ast
@@ -0,0 +1,20 @@
+  load system io.
+  load system vector.
+  load system util.
+  load system type.
+
+  let triangle = [[1]].
+  let ix = 0.
+
+  for i in 1 to 6 do
+      let v = triangle @ix.
+      let v1 = [0] + v.
+      let v2 = v + [0].
+      let new_v = vector @add(v1,v2).
+      let triangle = triangle + [new_v].
+      let ix = ix + 1.
+  end
+
+  for r in triangle do
+      io @println (r @map(lambda with v do return type @tostring v) @join(" ")).
+  end
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/run-tests.py b/asteroid/test-suites/first-class-redundant-pattern-tests/run-tests.py
deleted file mode 100755
index 55febef6..00000000
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/run-tests.py
+++ /dev/null
@@ -1,42 +0,0 @@
-#!/usr/bin/env python3
-# coding: utf-8
-
-# # Regression Tests
-
-
-import sys
-import os
-
-# uncomment if tim
-# sys.path[0] ='/Users/Timothy/Documents/GitHub/asteroid/code'
-
-# uncomment if running on SageMaker
-#sys.path[0] = '/home/ec2-user/SageMaker/asteroid/code'
-#sys.path[0] = '/Users/lutz/Dropbox/URI/Projects/Asteroid/asteroid-git/code'
-
-# 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 two levels above (the code directory)
-sys.path[0] = "../../"
-
-from interp import interp
-
-programs = os.listdir("programs")
-programs.sort()
-
-for pname in programs:
-    f = open("programs/"+pname,"r")
-    p = f.read()
-    print("**********"+pname+"*************")
-    #print(p)
-    #print("********************output*********************")
-    try:
-        interp(p,exceptions=True)
-    except:
-        pass
-
-    f.close()
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test001.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test001.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test001.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test001.ast
index c7458f3a..fdb8f4b5 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test001.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test001.ast
@@ -6,7 +6,7 @@
 --------------------------------------
 -- By Timothy Colaneri
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with x.
@@ -32,10 +32,10 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test002.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test002.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test002.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test002.ast
index f4a3a46e..4aca597a 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test002.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test002.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with ( 1, value1, value2).
@@ -27,10 +27,10 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test003.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test003.ast
similarity index 86%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test003.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test003.ast
index c00db92c..b8d7a07e 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test003.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test003.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with 1.
@@ -26,10 +26,10 @@ try
     let x = testFunction( 1 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test004.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test004.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test004.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test004.ast
index 26a029bd..6beefa2e 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test004.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test004.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with ( 1, 2, 3).
@@ -29,10 +29,10 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test005.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test005.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test005.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test005.ast
index e27f31ce..4e7b5e88 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test005.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test005.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- let ptrn1 = pattern with ( x, y, z).
@@ -24,10 +24,10 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test006.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test006.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test006.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test006.ast
index 206252b0..8b40532b 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test006.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test006.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with "name1".
@@ -30,10 +30,10 @@ try
     let x = testFunction( "name4" ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test008.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test008.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test008.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test008.ast
index 9944741d..3f2c3b09 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test008.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test008.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with 1.1.
@@ -32,10 +32,10 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + y ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test009.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test009.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test009.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test009.ast
index 4162136f..7044b22c 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test009.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test009.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with 1.10.
@@ -29,10 +29,10 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + y ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test010.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test010.ast
similarity index 86%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test010.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test010.ast
index ef321a85..4839ba30 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test010.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test010.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with false.
@@ -27,10 +27,10 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + y ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test011.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test011.ast
similarity index 89%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test011.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test011.ast
index 9c13a427..c94207bd 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test011.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test011.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with ".*p.*".
@@ -24,10 +24,10 @@ function test_function
 try
 
   let var = test_function( "test string z" ).
-  println ( var ).
+  io @println ( var ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test012.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test012.ast
similarity index 90%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test012.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test012.ast
index c3b78b58..9a28752e 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test012.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test012.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with ".*q.*".
@@ -27,10 +27,10 @@ function test_function
 try
 
   let var = test_function( "test string z" ).
-  println ( var ).
+  io @println ( var ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test013.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test013.ast
similarity index 85%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test013.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test013.ast
index 29868815..ffe14da6 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test013.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test013.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with [ x, y ].
@@ -24,10 +24,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test014.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test014.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test014.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test014.ast
index c695ef49..799ee34d 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test014.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test014.ast
@@ -6,7 +6,7 @@
 --------------------------------------
 -- By Timothy Colaneri
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with [ x , y].
@@ -28,10 +28,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test015.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test015.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test015.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test015.ast
index 0458ce42..fa54d6b4 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test015.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test015.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with [ h1 | h2 | h3 |  tail ].
@@ -27,10 +27,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test016.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test016.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test016.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test016.ast
index f5f60bbf..27244a5a 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test016.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test016.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with [ 1 | 2 | 3 | 4 | tail ].
@@ -30,10 +30,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test017.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test017.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test017.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test017.ast
index 6e454be0..d059bbce 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test017.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test017.ast
@@ -4,7 +4,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with person1:( fname, lname).
@@ -29,10 +29,10 @@ try
     let x = testFunction( 3 , 4 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test018.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test018.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test018.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test018.ast
index be83fca4..2061a3b5 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test018.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test018.ast
@@ -4,7 +4,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with person1:( fname, lname).
@@ -29,10 +29,10 @@ try
     let x = testFunction( 3 , 4 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test019.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test019.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test019.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test019.ast
index ed8fbbbd..07ac60ad 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test019.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test019.ast
@@ -4,7 +4,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with ( fname, lname).
@@ -26,10 +26,10 @@ try
     let x = testFunction( 3 , 4 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test020.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test020.ast
similarity index 89%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test020.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test020.ast
index 88fb3802..674a1a10 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test020.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test020.ast
@@ -4,7 +4,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with person:[( fname, lname)| tail].
@@ -28,10 +28,10 @@ try
     let x = testFunction[ ("test","name") ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test021.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test021.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test021.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test021.ast
index ff1c564f..d288b323 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test021.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test021.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with 0.
@@ -26,10 +26,10 @@ try
     let x = fact( 5 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test022.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test022.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test022.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test022.ast
index ee971f8a..c72d3ef9 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test022.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test022.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with 0.
@@ -29,10 +29,10 @@ try
     let x = testFunction( 5,1 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test023.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test023.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test023.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test023.ast
index f981fafa..8a25b2fd 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test023.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test023.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with 0.
@@ -29,10 +29,10 @@ try
     let x = testFunction( 5,1 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test024.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test024.ast
similarity index 88%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test024.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test024.ast
index f21d8bdb..5bdfae58 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test024.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test024.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with x:%tuple.
@@ -30,10 +30,10 @@ try
     let x = testFunction( (5,1) ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test025.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test025.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test025.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test025.ast
index 92caecca..0bb71365 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test025.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test025.ast
@@ -4,7 +4,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 let ptrn1 = pattern with [ head1 | head2 | tail ].
@@ -25,10 +25,10 @@ try
     let x = testFunction( (5,1) ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test026.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test026.ast
similarity index 91%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test026.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test026.ast
index 04b982d2..20dd5e1f 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test026.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test026.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -37,10 +37,10 @@ function testFunction
 try 
     
     let x = testFunction( Person("George", 32, "M") ).
-    println ( x ).
+    io @println ( x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test027.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test027.ast
similarity index 87%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test027.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test027.ast
index 06e591d3..302b05e3 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test027.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test027.ast
@@ -6,7 +6,7 @@
 --------------------------------------
 --------------------------------------
 -- implements Peano addition on terms
-load "io".
+load system io.
 load "util".
 
 structure S with
@@ -35,10 +35,10 @@ function reduce
     end 
 
 try      
-    println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
+    io @println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    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/programs/test028.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test028.ast
similarity index 93%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test028.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test028.ast
index ae07ed4f..53dd6fe3 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test028.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test028.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 structure Dog
@@ -40,8 +40,8 @@ try
   -- Fido the dog
   let fido = Dog("Fido").
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test029.ast b/asteroid/test-suites/first-class-redundant-pattern-tests/test029.ast
similarity index 90%
rename from asteroid/test-suites/first-class-redundant-pattern-tests/programs/test029.ast
rename to asteroid/test-suites/first-class-redundant-pattern-tests/test029.ast
index ef3f8091..c37d2419 100644
--- a/asteroid/test-suites/first-class-redundant-pattern-tests/programs/test029.ast
+++ b/asteroid/test-suites/first-class-redundant-pattern-tests/test029.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -42,11 +42,11 @@ let loopCounter = 0.
 -- print names that contain 'p'
 for Person(_,_,_) in people do
   try
-    println (test_function( people @loopCounter )).
+    io @println (test_function( people @loopCounter )).
   catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
   catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
   end.
   let loopCounter = loopCounter + 1.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test001.ast b/asteroid/test-suites/redundant-pattern-test/test001.ast
similarity index 85%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test001.ast
rename to asteroid/test-suites/redundant-pattern-test/test001.ast
index e1d297e6..ddfc98a9 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test001.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test001.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -24,10 +24,10 @@ function testFunction
 try
     -- Evaluate the function with a test input.
     let x = testFunction( 1 , 2 , 3 ).
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test002.ast b/asteroid/test-suites/redundant-pattern-test/test002.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test002.ast
rename to asteroid/test-suites/redundant-pattern-test/test002.ast
index 1ecf3ff1..f23edb60 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test002.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test002.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -25,11 +25,11 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
 
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test003.ast b/asteroid/test-suites/redundant-pattern-test/test003.ast
similarity index 85%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test003.ast
rename to asteroid/test-suites/redundant-pattern-test/test003.ast
index ee4968b4..5dc40885 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test003.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test003.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -23,10 +23,10 @@ try
     let x = testFunction( 1 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test004.ast b/asteroid/test-suites/redundant-pattern-test/test004.ast
similarity index 87%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test004.ast
rename to asteroid/test-suites/redundant-pattern-test/test004.ast
index b1ca4d5f..8ff5a315 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test004.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test004.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -26,10 +26,10 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test005.ast b/asteroid/test-suites/redundant-pattern-test/test005.ast
similarity index 85%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test005.ast
rename to asteroid/test-suites/redundant-pattern-test/test005.ast
index d725681d..1f15728a 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test005.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test005.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -21,10 +21,10 @@ try
     let x = testFunction( 1 , 2 , 3 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test006.ast b/asteroid/test-suites/redundant-pattern-test/test006.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test006.ast
rename to asteroid/test-suites/redundant-pattern-test/test006.ast
index 8e3523ec..90a3ecd4 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test006.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test006.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -25,10 +25,10 @@ try
     let x = testFunction( "name4" ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test008.ast b/asteroid/test-suites/redundant-pattern-test/test008.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test008.ast
rename to asteroid/test-suites/redundant-pattern-test/test008.ast
index fd383a59..0127b9f0 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test008.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test008.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -27,10 +27,10 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + y ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test009.ast b/asteroid/test-suites/redundant-pattern-test/test009.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test009.ast
rename to asteroid/test-suites/redundant-pattern-test/test009.ast
index 114d5fd7..faeb6e2b 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test009.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test009.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -26,10 +26,10 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + y ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test010.ast b/asteroid/test-suites/redundant-pattern-test/test010.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test010.ast
rename to asteroid/test-suites/redundant-pattern-test/test010.ast
index c1ba7e30..0ce788d3 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test010.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test010.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -24,10 +24,10 @@ try
     let y = testFunction( x ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + y ).
+    io @println( "The value returned is: " + y ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test011.ast b/asteroid/test-suites/redundant-pattern-test/test011.ast
similarity index 88%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test011.ast
rename to asteroid/test-suites/redundant-pattern-test/test011.ast
index f5943a4f..1c02d54a 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test011.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test011.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function test_function 
@@ -22,10 +22,10 @@ function test_function
 try
     
     let var = test_function( "test string z" ).
-    println ( var ).
+    io @println ( var ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test012.ast b/asteroid/test-suites/redundant-pattern-test/test012.ast
similarity index 88%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test012.ast
rename to asteroid/test-suites/redundant-pattern-test/test012.ast
index 1cb15e19..6dbf2448 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test012.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test012.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function test_function 
@@ -22,10 +22,10 @@ function test_function
 try
     
   let var = test_function( "test string z" ).
-  println ( var ).
+  io @println ( var ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test013.ast b/asteroid/test-suites/redundant-pattern-test/test013.ast
similarity index 85%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test013.ast
rename to asteroid/test-suites/redundant-pattern-test/test013.ast
index 929165c5..f65e685c 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test013.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test013.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -22,10 +22,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test014.ast b/asteroid/test-suites/redundant-pattern-test/test014.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test014.ast
rename to asteroid/test-suites/redundant-pattern-test/test014.ast
index fcadb01f..0a086e33 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test014.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test014.ast
@@ -6,7 +6,7 @@
 --------------------------------------
 -- By Timothy Colaneri
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -26,10 +26,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test015.ast b/asteroid/test-suites/redundant-pattern-test/test015.ast
similarity index 87%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test015.ast
rename to asteroid/test-suites/redundant-pattern-test/test015.ast
index 8fe28ada..e79d08f3 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test015.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test015.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -23,10 +23,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test016.ast b/asteroid/test-suites/redundant-pattern-test/test016.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test016.ast
rename to asteroid/test-suites/redundant-pattern-test/test016.ast
index a4c9a488..88759fd7 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test016.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test016.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -25,10 +25,10 @@ try
     let x = testFunction[ 3 , 4 ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test017.ast b/asteroid/test-suites/redundant-pattern-test/test017.ast
similarity index 87%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test017.ast
rename to asteroid/test-suites/redundant-pattern-test/test017.ast
index b207643f..3ad7cf43 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test017.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test017.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -25,10 +25,10 @@ try
     let x = testFunction( 3 , 4 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test018.ast b/asteroid/test-suites/redundant-pattern-test/test018.ast
similarity index 87%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test018.ast
rename to asteroid/test-suites/redundant-pattern-test/test018.ast
index 7f78056e..03a7b092 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test018.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test018.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -26,10 +26,10 @@ try
     let x = testFunction( 3 , 4 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test019.ast b/asteroid/test-suites/redundant-pattern-test/test019.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test019.ast
rename to asteroid/test-suites/redundant-pattern-test/test019.ast
index 84cbc0fb..9236d691 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test019.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test019.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -25,10 +25,10 @@ try
     let x = testFunction( 3 , 4 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test020.ast b/asteroid/test-suites/redundant-pattern-test/test020.ast
similarity index 88%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test020.ast
rename to asteroid/test-suites/redundant-pattern-test/test020.ast
index a5aa82aa..2d6b98b6 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test020.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test020.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 -- A testing function with multiple patterns
@@ -26,10 +26,10 @@ try
     let x = testFunction[ ("test","name") ].
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ).
+    io @println( "The value returned is: " + x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test021.ast b/asteroid/test-suites/redundant-pattern-test/test021.ast
similarity index 85%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test021.ast
rename to asteroid/test-suites/redundant-pattern-test/test021.ast
index 1cc0a6e0..36a5a18b 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test021.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test021.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function fact
@@ -23,11 +23,11 @@ try
     let x = fact( 5 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x ). 
+    io @println( "The value returned is: " + x ). 
 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test022.ast b/asteroid/test-suites/redundant-pattern-test/test022.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test022.ast
rename to asteroid/test-suites/redundant-pattern-test/test022.ast
index c3ac557c..6d1ff98b 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test022.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test022.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function testFunction
@@ -24,11 +24,11 @@ try
     let x = testFunction( 5,1 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ).
+    io @println( "The value returned is: " + x  ).
 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test023.ast b/asteroid/test-suites/redundant-pattern-test/test023.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test023.ast
rename to asteroid/test-suites/redundant-pattern-test/test023.ast
index b8fa6c07..9a31dcd1 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test023.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test023.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function testFunction
@@ -24,11 +24,11 @@ try
     let x = testFunction( 5,1 ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test024.ast b/asteroid/test-suites/redundant-pattern-test/test024.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test024.ast
rename to asteroid/test-suites/redundant-pattern-test/test024.ast
index 8ac4c577..2c6ebd41 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test024.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test024.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function testFunction
@@ -25,11 +25,11 @@ try
     let x = testFunction( (5,1) ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
\ No newline at end of file
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test025.ast b/asteroid/test-suites/redundant-pattern-test/test025.ast
similarity index 86%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test025.ast
rename to asteroid/test-suites/redundant-pattern-test/test025.ast
index 5be5b5db..f16a04b8 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test025.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test025.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 function testFunction
@@ -25,10 +25,10 @@ try
     let x = testFunction( (5,1) ).
 
     -- If the function test worked, print the output we got.
-    println( "The value returned is: " + x  ). 
+    io @println( "The value returned is: " + x  ). 
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test026.ast b/asteroid/test-suites/redundant-pattern-test/test026.ast
similarity index 89%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test026.ast
rename to asteroid/test-suites/redundant-pattern-test/test026.ast
index 89b92ca1..d5ae7057 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test026.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test026.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -23,7 +23,7 @@ let people = [
 
 -- print names that contain 'p'
 -- for Person(name:".*p.*",_,_) in people do
---  println name.
+--  io @println name.
 --  end
   
 function testFunction
@@ -37,11 +37,11 @@ function testFunction
 
 try    
     let x = testFunction( Person("George", 32, "M") ).
-    println ( x ).
+    io @println ( x ).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
 
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test027.ast b/asteroid/test-suites/redundant-pattern-test/test027.ast
similarity index 85%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test027.ast
rename to asteroid/test-suites/redundant-pattern-test/test027.ast
index 3da9c0ee..b1eba2aa 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test027.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test027.ast
@@ -6,7 +6,7 @@
 --------------------------------------
 --------------------------------------
 -- implements Peano addition on terms
-load "io".
+load system io.
 load "util".
 
 structure S with
@@ -30,10 +30,10 @@ function reduce
     end 
     
 try    
-    println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
+    io @println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test028.ast b/asteroid/test-suites/redundant-pattern-test/test028.ast
similarity index 93%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test028.ast
rename to asteroid/test-suites/redundant-pattern-test/test028.ast
index fa87e13b..944c33bf 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test028.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test028.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 structure Dog
@@ -36,8 +36,8 @@ try
   -- Fido the dog
   let fido = Dog("Fido").
 catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
 catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
 end.
diff --git a/asteroid/test-suites/redundant-pattern-tests/programs/test029.ast b/asteroid/test-suites/redundant-pattern-test/test029.ast
similarity index 89%
rename from asteroid/test-suites/redundant-pattern-tests/programs/test029.ast
rename to asteroid/test-suites/redundant-pattern-test/test029.ast
index 0d91c8fa..97a44a28 100644
--- a/asteroid/test-suites/redundant-pattern-tests/programs/test029.ast
+++ b/asteroid/test-suites/redundant-pattern-test/test029.ast
@@ -5,7 +5,7 @@
 -- subsumption detection in Asteroid.
 --------------------------------------
 --------------------------------------
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -37,11 +37,11 @@ let loopCounter = 0.
 -- print names that contain 'p'
 for Person(_,_,_) in people do
   try
-    println (test_function( people @loopCounter )).
+    io @println (test_function( people @loopCounter )).
   catch Exception("RedundantPatternFound",s) do
-    println("PASS.").
+    io @println("PASS.").
   catch e do
-    println("FAIL.").
+    io @println("FAIL.").
     throw Error("FAIL: unexpected error "+e).
   end.
   let loopCounter = loopCounter + 1.
diff --git a/asteroid/test-suites/redundant-pattern-tests/run-tests.py b/asteroid/test-suites/redundant-pattern-tests/run-tests.py
deleted file mode 100755
index b5b988bc..00000000
--- a/asteroid/test-suites/redundant-pattern-tests/run-tests.py
+++ /dev/null
@@ -1,41 +0,0 @@
-#!/usr/bin/env python3
-# coding: utf-8
-
-# # Regression Tests
-
-
-import sys
-import os
-
-# uncomment if tim
-#sys.path[0] ='/Users/Timothy/Documents/GitHub/asteroid/code'
-
-# uncomment if running on SageMaker
-#sys.path[0] = '/home/ec2-user/SageMaker/asteroid/code'
-#sys.path[0] = '/Users/lutz/Dropbox/URI/Projects/Asteroid/asteroid-git/code'
-
-# 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 two levels above (the code directory)
-sys.path[0] = "../../"
-
-from interp import interp
-
-programs = os.listdir("programs")
-programs.sort()
-
-for pname in programs:
-    f = open("programs/"+pname,"r")
-    p = f.read()
-    print("**********"+pname+"************")
-    #print(p)
-    #print("**********output***********")
-    try:
-        interp(p, exceptions=True)
-    except:
-        pass
-    f.close()
diff --git a/asteroid/test-suites/ref-programs/format.ast b/asteroid/test-suites/ref-programs/format.ast
new file mode 100644
index 00000000..98c5d197
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/format.ast
@@ -0,0 +1,20 @@
+    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.
diff --git a/asteroid/test-suites/ref-programs/math.ast b/asteroid/test-suites/ref-programs/math.ast
new file mode 100644
index 00000000..ff4e64c2
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/math.ast
@@ -0,0 +1,5 @@
+    load system io.
+    load system math.
+
+    let x = math @sin( math @pi / 2 ).
+    io @println("The sine of pi / 2 is " + x + ".").
diff --git a/asteroid/test-suites/ref-programs/pick.ast b/asteroid/test-suites/ref-programs/pick.ast
new file mode 100644
index 00000000..6378639c
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/pick.ast
@@ -0,0 +1,7 @@
+   load system io.
+   load system pick.
+
+   let po = pick @pick([1 to 10]).
+   let objects = po @pick(3).
+   io @println objects.
+   
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/sort.ast b/asteroid/test-suites/ref-programs/sort.ast
new file mode 100644
index 00000000..34ac21f7
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/sort.ast
@@ -0,0 +1,5 @@
+   load system io.
+   load system sort.
+   let sl = sort @sort((lambda with (x,y) do return true if x<y else false),
+                       [10,5,110,50]).
+    io @println sl.
diff --git a/asteroid/test-suites/ref-programs/stream.ast b/asteroid/test-suites/ref-programs/stream.ast
new file mode 100644
index 00000000..b4d85cd0
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/stream.ast
@@ -0,0 +1,9 @@
+   load system io.
+   load system stream.
+
+   let s = stream @stream([1 to 10]).
+   while not s @ eof() do
+      io @ print (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
new file mode 100644
index 00000000..28b79870
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/type.ast
@@ -0,0 +1,5 @@
+   load system type.
+
+   let i = 1.
+   assert(type @gettype(i) == "integer").
+   
\ No newline at end of file
diff --git a/asteroid/test-suites/ref-programs/vector.ast b/asteroid/test-suites/ref-programs/vector.ast
new file mode 100644
index 00000000..add54cb0
--- /dev/null
+++ b/asteroid/test-suites/ref-programs/vector.ast
@@ -0,0 +1,8 @@
+   load system io.
+   load system vector.
+
+   let a = [1,0].
+   let b = [0,1].
+
+   io @println (vector @dot (a,b)).
+   
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/programs/test001.ast b/asteroid/test-suites/regression-tests/programs/test001.ast
deleted file mode 100644
index 0dd4f4f2..00000000
--- a/asteroid/test-suites/regression-tests/programs/test001.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-
-let x = 1.
-println x.
diff --git a/asteroid/test-suites/regression-tests/programs/test004.ast b/asteroid/test-suites/regression-tests/programs/test004.ast
deleted file mode 100644
index a4bbf3f2..00000000
--- a/asteroid/test-suites/regression-tests/programs/test004.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-let l:"\[.*\]" = [1,2,3].
-println l.
diff --git a/asteroid/test-suites/regression-tests/programs/test013.ast b/asteroid/test-suites/regression-tests/programs/test013.ast
deleted file mode 100644
index d23569ec..00000000
--- a/asteroid/test-suites/regression-tests/programs/test013.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-let i:%integer = 1.
-print i.
diff --git a/asteroid/test-suites/regression-tests/programs/test014.ast b/asteroid/test-suites/regression-tests/programs/test014.ast
deleted file mode 100644
index 0efcc562..00000000
--- a/asteroid/test-suites/regression-tests/programs/test014.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-try
-    let (1,y) = '(1,x).
-catch e do
-    println e.
-end
diff --git a/asteroid/test-suites/regression-tests/programs/test021.ast b/asteroid/test-suites/regression-tests/programs/test021.ast
deleted file mode 100644
index 92a30473..00000000
--- a/asteroid/test-suites/regression-tests/programs/test021.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-
-let a:%list = [1,2] .
-println a.
diff --git a/asteroid/test-suites/regression-tests/programs/test025.ast b/asteroid/test-suites/regression-tests/programs/test025.ast
deleted file mode 100644
index 9350caa8..00000000
--- a/asteroid/test-suites/regression-tests/programs/test025.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-
-let q:%integer = 3.
-println q.
diff --git a/asteroid/test-suites/regression-tests/programs/test034.ast b/asteroid/test-suites/regression-tests/programs/test034.ast
deleted file mode 100644
index 682cd268..00000000
--- a/asteroid/test-suites/regression-tests/programs/test034.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-let a = [1,2,3].
-println (a @length()).
-a @append(3).
-a @insert(2,4).
-println a.
-a @sort(true).
-println a.
diff --git a/asteroid/test-suites/regression-tests/programs/test035.ast b/asteroid/test-suites/regression-tests/programs/test035.ast
deleted file mode 100644
index b6a2e726..00000000
--- a/asteroid/test-suites/regression-tests/programs/test035.ast
+++ /dev/null
@@ -1,7 +0,0 @@
-
-load "io".
-let a = [].
-
-if a is [b|rest] do
-    println "yes".
-end
diff --git a/asteroid/test-suites/regression-tests/programs/test037.ast b/asteroid/test-suites/regression-tests/programs/test037.ast
deleted file mode 100644
index 471f1823..00000000
--- a/asteroid/test-suites/regression-tests/programs/test037.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-let fst = (1,2)@0.
-println fst.
diff --git a/asteroid/test-suites/regression-tests/programs/test038.ast b/asteroid/test-suites/regression-tests/programs/test038.ast
deleted file mode 100644
index 03378736..00000000
--- a/asteroid/test-suites/regression-tests/programs/test038.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-let t = (1,2).
-println ("tuple = " + t).
diff --git a/asteroid/test-suites/regression-tests/programs/test044.ast b/asteroid/test-suites/regression-tests/programs/test044.ast
deleted file mode 100644
index bcd077e0..00000000
--- a/asteroid/test-suites/regression-tests/programs/test044.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".      
-load "util".
-let slice = [4 to 0 step -1].
-println slice.
-assert(slice is [4,3,2,1,0]).
diff --git a/asteroid/test-suites/regression-tests/programs/test047.ast b/asteroid/test-suites/regression-tests/programs/test047.ast
deleted file mode 100644
index fdb9c424..00000000
--- a/asteroid/test-suites/regression-tests/programs/test047.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "random".
-load "io".
-
-let v = random().
-
-println v.
-assert(v <= 1.0 and v >= 0.0).
-
diff --git a/asteroid/test-suites/regression-tests/programs/test048.ast b/asteroid/test-suites/regression-tests/programs/test048.ast
deleted file mode 100644
index 73a31c9c..00000000
--- a/asteroid/test-suites/regression-tests/programs/test048.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "io".
-load "util".
-
-let inc = (lambda with n do return n+1).
-
-
-println (eval ('inc 1)).
-
-assert(eval ('inc 1) is 2).
diff --git a/asteroid/test-suites/regression-tests/programs/test050.ast b/asteroid/test-suites/regression-tests/programs/test050.ast
deleted file mode 100644
index 28364a13..00000000
--- a/asteroid/test-suites/regression-tests/programs/test050.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-
-try 
-    let 2 = 1 + 1. 
-catch _ do
-    println "pattern match failed".
-end 
-
diff --git a/asteroid/test-suites/regression-tests/programs/test054.ast b/asteroid/test-suites/regression-tests/programs/test054.ast
deleted file mode 100644
index 35ae57ce..00000000
--- a/asteroid/test-suites/regression-tests/programs/test054.ast
+++ /dev/null
@@ -1,35 +0,0 @@
-
--- implements Peano addition using a lookup table for the rewrite rules
-
-load "util".
-load "io".
-
-structure S with
-    data x.
-    end 
-    
-structure add with
-    data left.
-    data right.
-    end .
-
-let rule_table = [
-    ('add(x,0), 'reduce(x)),
-    ('add(x,S(y)), 'S(reduce(add(x,y))))
-    ].
-
-function reduce 
-    with term do
-        for i in 0 to rule_table @length()-1 do
-            -- limit visibility of free variables of the rewrite rules
-            -- to the with block scope
-            let (lhs, rhs) = rule_table@i.
-            if term is *lhs do
-                return eval rhs.
-            end 
-        end 
-        return term.
-    end 
-
-println (reduce('add(S(S(0)),S(S(S(0)))))).
-assert (reduce('add(S(S(0)),S(S(S(0))))) is S(S(S(S(S(0)))))).
diff --git a/asteroid/test-suites/regression-tests/programs/test056.ast b/asteroid/test-suites/regression-tests/programs/test056.ast
deleted file mode 100644
index 6e02c29d..00000000
--- a/asteroid/test-suites/regression-tests/programs/test056.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-
-load "io".
-load "util".
-
-function match
-    with (subject, p) do
-        return subject is *p.
-    end 
-    
-println (match('1+1, '_+_)).
-assert (match('1+1, '_+_) is true).
diff --git a/asteroid/test-suites/regression-tests/programs/test058.ast b/asteroid/test-suites/regression-tests/programs/test058.ast
deleted file mode 100644
index a723c166..00000000
--- a/asteroid/test-suites/regression-tests/programs/test058.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-
-try
-    let i = 10/0.
-    println i.
-catch e do
-    println e.
-end 
diff --git a/asteroid/test-suites/regression-tests/programs/test062.ast b/asteroid/test-suites/regression-tests/programs/test062.ast
deleted file mode 100644
index 2a74defc..00000000
--- a/asteroid/test-suites/regression-tests/programs/test062.ast
+++ /dev/null
@@ -1,7 +0,0 @@
-
-load "io".
-load "util".
-
-let true = ('1 + 2) is x + y.
-println (x,y).
-assert ((x,y) is (1,2)).
diff --git a/asteroid/test-suites/regression-tests/programs/test067.ast b/asteroid/test-suites/regression-tests/programs/test067.ast
deleted file mode 100644
index cb261ea9..00000000
--- a/asteroid/test-suites/regression-tests/programs/test067.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "type".
-load "io".
-
-let cnt = tointeger(input("Please enter an integer value: ")).
-
-for i in 1 to cnt do
-    println i.
-end
-assert (i is cnt).
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/programs/test068.ast b/asteroid/test-suites/regression-tests/programs/test068.ast
deleted file mode 100644
index 61264c9c..00000000
--- a/asteroid/test-suites/regression-tests/programs/test068.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-
-let name = input("Please enter your name: ").
-println("Hello " + name + "!").
diff --git a/asteroid/test-suites/regression-tests/programs/test069.ast b/asteroid/test-suites/regression-tests/programs/test069.ast
deleted file mode 100644
index 5823963f..00000000
--- a/asteroid/test-suites/regression-tests/programs/test069.ast
+++ /dev/null
@@ -1,16 +0,0 @@
-
-load "util".
-load "io".
-
-structure S with
-    data x.
-    end 
-    
-let x = 'S(S(0)).
-let y = 'S(S(x)).
-let z = y.
-
-println y.
-println z.
-println (eval (z)).
-assert ((eval (z)) is S(S(S(S(0))))).
diff --git a/asteroid/test-suites/regression-tests/programs/test079.ast b/asteroid/test-suites/regression-tests/programs/test079.ast
deleted file mode 100644
index 12a73c93..00000000
--- a/asteroid/test-suites/regression-tests/programs/test079.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".
-
-for x in 1 to 10 do
-    println x.
-end 
diff --git a/asteroid/test-suites/regression-tests/programs/test081.ast b/asteroid/test-suites/regression-tests/programs/test081.ast
deleted file mode 100644
index fcb9873e..00000000
--- a/asteroid/test-suites/regression-tests/programs/test081.ast
+++ /dev/null
@@ -1,20 +0,0 @@
-
-load "io".
-
-let x = 42.
-
-if x < 0 do
-    let x = 0.
-    println("Negative changed to zero").
-
-elif x == 0 do
-    println("Zero").
-
-elif x == 1 do
-    println("Single").
-
-else do
-    println("More").
-    
-end 
-
diff --git a/asteroid/test-suites/regression-tests/programs/test085.ast b/asteroid/test-suites/regression-tests/programs/test085.ast
deleted file mode 100644
index 053acc31..00000000
--- a/asteroid/test-suites/regression-tests/programs/test085.ast
+++ /dev/null
@@ -1,14 +0,0 @@
-
-load "io".
-load "util".
-
-structure A with
-    data x.
-    data y.
-    end 
-
-let a = A(999, (lambda with (self) do return "Hello World!")).
-println (a@1()).
-
-assert(a@1() is "Hello World!").
-
diff --git a/asteroid/test-suites/regression-tests/programs/test086.ast b/asteroid/test-suites/regression-tests/programs/test086.ast
deleted file mode 100644
index 5aa6b541..00000000
--- a/asteroid/test-suites/regression-tests/programs/test086.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-
-println (1,2,3).
diff --git a/asteroid/test-suites/regression-tests/programs/test090.ast b/asteroid/test-suites/regression-tests/programs/test090.ast
deleted file mode 100644
index fb9f80df..00000000
--- a/asteroid/test-suites/regression-tests/programs/test090.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-load "util".
-
-let a = [0,1,2,3].
-let b = a@[0 to 3 step 2].
-println b.
-assert (b is [0,2]).
diff --git a/asteroid/test-suites/regression-tests/programs/test091.ast b/asteroid/test-suites/regression-tests/programs/test091.ast
deleted file mode 100644
index 885bcd71..00000000
--- a/asteroid/test-suites/regression-tests/programs/test091.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-load "util".
-
-let y = [0 to 10 step 2].
-let z = 4 in y.
-println z.
-assert z.
diff --git a/asteroid/test-suites/regression-tests/programs/test099.ast b/asteroid/test-suites/regression-tests/programs/test099.ast
deleted file mode 100644
index 4de2d911..00000000
--- a/asteroid/test-suites/regression-tests/programs/test099.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-
-let v = 'a@[3].
-__raw_print__ v.
diff --git a/asteroid/test-suites/regression-tests/programs/test107.ast b/asteroid/test-suites/regression-tests/programs/test107.ast
deleted file mode 100644
index e10f0aab..00000000
--- a/asteroid/test-suites/regression-tests/programs/test107.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".
-load "util".
-
-println ((lambda with n do return n+1) 1).
-assert ((lambda with n do return n+1) 1 is 2).
diff --git a/asteroid/test-suites/regression-tests/programs/test113.ast b/asteroid/test-suites/regression-tests/programs/test113.ast
deleted file mode 100644
index b1032a58..00000000
--- a/asteroid/test-suites/regression-tests/programs/test113.ast
+++ /dev/null
@@ -1,14 +0,0 @@
--- Bitwise operations regression test
-load "bitwise".
-
-assert(band(2,4) == 0).
-assert(bor(2,4)  == 6).
-assert(bnot(2)   == -3).
-assert(bxor(15,3) == 12).
-assert(brshift(32,2) == 8).
-assert(blshift(2,4)   == 32).
-assert(blrotate(242, 1) == 229).
-assert(brrotate(242, 1) == 121).
-assert(bsetbit(10,2) == 14).
-assert(bclearbit(5,1) == 4).
-assert(bsize(8) == 4).
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/programs/test116.ast b/asteroid/test-suites/regression-tests/programs/test116.ast
deleted file mode 100644
index c8f2377e..00000000
--- a/asteroid/test-suites/regression-tests/programs/test116.ast
+++ /dev/null
@@ -1,65 +0,0 @@
--- Tests for file i/o
-
-load system io.
-
-let filename = escape
-"
-global __retval__
-
-import tempfile
-
-new_file, filename = tempfile.mkstemp()
-
-__retval__ = ('string', filename)
-".
-
--- Open up the temporary file for appending
-let file = open(filename, "a").
-
--- Write some content and close the file
-writeln(file, "Asteroid!").
-write(file, "Asteroid!!").
-write(file, "Asteroid!!!").
-close(file).
-
-----------------------------------------------------
-
--- Open the file for reading
-let file = open(filename, "r").
-
--- Seek to the next line
-readln(file).
-
--- Assert that the remaining content is the last two lines
-assert read(file) == "Asteroid!!Asteroid!!!".
-
--- Close the file
-close(file).
-
-----------------------------------------------------
-
--- Check that print(X) is write(__STDOUT__, X)
-print("Hello,").
-write(__STDOUT__, " world!" + "\n").
-
--- Check that println(X) is writeln(__STDOUT__, X)
-println("First-class patterns").
-writeln(__STDOUT__, "are pretty cool!").
-
--- Check that input() is the same as read(__STDIN__).
-println("Please enter your name: ").
-let name = readln(__STDIN__).
-println("Hello, " + name).
-
--- Write to STDERR
-writeln(__STDERR__, "Oh no, you've encountered an error!").
-writeln(__STDERR__, "^ This is just a test. You're doing fine").
-
-
-----------------------------------------------------
-
--- Test implicit write and read
-writeln("What's your favorite color?").
-let x = readln().
-write("Wow! I like ").
-writeln(x + " too!").
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/run-tests.py b/asteroid/test-suites/regression-tests/run-tests.py
deleted file mode 100755
index 8b18a444..00000000
--- a/asteroid/test-suites/regression-tests/run-tests.py
+++ /dev/null
@@ -1,31 +0,0 @@
-#!/usr/bin/env python3
-# coding: utf-8
-
-# # Regression Tests
-
-
-import sys
-import os
-
-# 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 two levels above (the code directory)
-sys.path[0] = "../../"
-
-from interp import interp
-
-programs = os.listdir("programs")
-programs.sort()
-
-for pname in programs:
-    f = open("programs/"+pname,"r")
-    p = f.read()
-    print("**********"+pname+"************")
-    print(p)
-    print("**********output***********")
-    interp(p)
-    f.close()
diff --git a/asteroid/test-suites/regression-tests/test001.ast b/asteroid/test-suites/regression-tests/test001.ast
new file mode 100644
index 00000000..f31d24c0
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test001.ast
@@ -0,0 +1,5 @@
+
+load system io.
+
+let x = 1.
+io @println x.
diff --git a/asteroid/test-suites/regression-tests/programs/test002.ast b/asteroid/test-suites/regression-tests/test002.ast
similarity index 96%
rename from asteroid/test-suites/regression-tests/programs/test002.ast
rename to asteroid/test-suites/regression-tests/test002.ast
index aba67605..a8f98724 100644
--- a/asteroid/test-suites/regression-tests/programs/test002.ast
+++ b/asteroid/test-suites/regression-tests/test002.ast
@@ -1,6 +1,10 @@
 
 load system io.
 load system util.
+load system type.
+
+let isnone = type @isnone.
+
 -----------------------------------------------------------------------
 let x = [1,2].
 let %[ x ]% = (2,1).
@@ -81,7 +85,7 @@ try
   let v = 1 if v == 2.
   throw Error("FAIL: no expected error ").
 catch Exception("SystemError", s) do
-  if not isnone(s @index("else clause")) do
+  if not isnone(s @index("'else' clause")) do
   . -- pass
   else
     throw Error("FAIL: unexpected error "+s).
@@ -97,7 +101,7 @@ catch Exception("SystemError", s) do
   else
     throw Error("FAIL: unexpected error "+s).
   end.
-end.  
+end.
 -----------------------------------------------------------------------
 try
   let v = %[ 1 ]%.
@@ -117,7 +121,7 @@ try
     return 2*number. -- error: no unifier for 'number'
   end.
   assert(20 == g(10)).
-  
+
   throw Error("FAIL: no expected error ").
 catch Exception("SystemError", s) do
   if not isnone(s @index("not defined")) do
@@ -128,5 +132,4 @@ catch Exception("SystemError", s) do
 end.
 -----------------------------------------------------------------------
 
-println("PASSED.").
-
+io @println("PASSED.").
diff --git a/asteroid/test-suites/regression-tests/programs/test003.ast b/asteroid/test-suites/regression-tests/test003.ast
similarity index 55%
rename from asteroid/test-suites/regression-tests/programs/test003.ast
rename to asteroid/test-suites/regression-tests/test003.ast
index 400d07ce..26df1b40 100644
--- a/asteroid/test-suites/regression-tests/programs/test003.ast
+++ b/asteroid/test-suites/regression-tests/test003.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 let digits = "332211" @explode() @sort().
-println digits.
+io @println digits.
diff --git a/asteroid/test-suites/regression-tests/test004.ast b/asteroid/test-suites/regression-tests/test004.ast
new file mode 100644
index 00000000..50483b8c
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test004.ast
@@ -0,0 +1,4 @@
+
+load system io.
+let l:"\[.*\]" = [1,2,3].
+io @println l.
diff --git a/asteroid/test-suites/regression-tests/programs/test005.ast b/asteroid/test-suites/regression-tests/test005.ast
similarity index 71%
rename from asteroid/test-suites/regression-tests/programs/test005.ast
rename to asteroid/test-suites/regression-tests/test005.ast
index 2c87d3bb..81d3b76f 100644
--- a/asteroid/test-suites/regression-tests/programs/test005.ast
+++ b/asteroid/test-suites/regression-tests/test005.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 let r = [1,2,3] @reduce (lambda with (x,y) do return x*y).
-println r.
+io @println r.
 assert (r == 6).
diff --git a/asteroid/test-suites/regression-tests/programs/test006.ast b/asteroid/test-suites/regression-tests/test006.ast
similarity index 71%
rename from asteroid/test-suites/regression-tests/programs/test006.ast
rename to asteroid/test-suites/regression-tests/test006.ast
index 326923a6..7b63fcfe 100644
--- a/asteroid/test-suites/regression-tests/programs/test006.ast
+++ b/asteroid/test-suites/regression-tests/test006.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 let r = [1,2,3] @map (lambda with x do return x+1).
-println r.
+io @println r.
 assert (r == [2,3,4]).
diff --git a/asteroid/test-suites/regression-tests/programs/test007.ast b/asteroid/test-suites/regression-tests/test007.ast
similarity index 92%
rename from asteroid/test-suites/regression-tests/programs/test007.ast
rename to asteroid/test-suites/regression-tests/test007.ast
index 120fa95b..c1d494bb 100644
--- a/asteroid/test-suites/regression-tests/programs/test007.ast
+++ b/asteroid/test-suites/regression-tests/test007.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 structure Dog with
 
@@ -38,5 +38,5 @@ fifi @add_trick("sit stay").
 let dogs = [fido, buddy, fifi].
 
 for Dog(name, ["roll over"|_]) in dogs do
-    println (name + " does roll over").
+    io @println (name + " does roll over").
 end
diff --git a/asteroid/test-suites/regression-tests/programs/test008.ast b/asteroid/test-suites/regression-tests/test008.ast
similarity index 88%
rename from asteroid/test-suites/regression-tests/programs/test008.ast
rename to asteroid/test-suites/regression-tests/test008.ast
index 59268b70..91de08d5 100644
--- a/asteroid/test-suites/regression-tests/programs/test008.ast
+++ b/asteroid/test-suites/regression-tests/test008.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 structure Family with
   data parent1.
@@ -23,5 +23,5 @@ let PARENT1 = pattern with Parent(p1).
 let p1 = "Harry".
 let family = eval(FAMILY).
 --__raw_print__(family).
-println (family @members()).
+io @println (family @members()).
 
diff --git a/asteroid/test-suites/regression-tests/programs/test009.ast b/asteroid/test-suites/regression-tests/test009.ast
similarity index 69%
rename from asteroid/test-suites/regression-tests/programs/test009.ast
rename to asteroid/test-suites/regression-tests/test009.ast
index 8b9ad14a..76830333 100644
--- a/asteroid/test-suites/regression-tests/programs/test009.ast
+++ b/asteroid/test-suites/regression-tests/test009.ast
@@ -1,8 +1,8 @@
 
-load "io".
+load system io.
 structure A with
     data a.
     end
 
 let A(x:%string) = A("hello").
-println x.
+io @println x.
diff --git a/asteroid/test-suites/regression-tests/programs/test010.ast b/asteroid/test-suites/regression-tests/test010.ast
similarity index 86%
rename from asteroid/test-suites/regression-tests/programs/test010.ast
rename to asteroid/test-suites/regression-tests/test010.ast
index a5f4559d..c9ab5483 100644
--- a/asteroid/test-suites/regression-tests/programs/test010.ast
+++ b/asteroid/test-suites/regression-tests/test010.ast
@@ -1,6 +1,6 @@
 
 -- load modules
-load "io".
+load system io.
 
 structure Family with
   data parent1.
@@ -18,4 +18,4 @@ structure Parent with
   end
 
 let family = Family(Parent("Harry")).
-println (family @members()).
+io @println (family @members()).
diff --git a/asteroid/test-suites/regression-tests/programs/test011.ast b/asteroid/test-suites/regression-tests/test011.ast
similarity index 67%
rename from asteroid/test-suites/regression-tests/programs/test011.ast
rename to asteroid/test-suites/regression-tests/test011.ast
index c37c25a6..c77b3392 100644
--- a/asteroid/test-suites/regression-tests/programs/test011.ast
+++ b/asteroid/test-suites/regression-tests/test011.ast
@@ -1,6 +1,6 @@
 
-load "io".
+load system io.
 
 let foo = "abc".
 let l = foo @explode() @reverse() @join("").
-println l.
+io @println l.
diff --git a/asteroid/test-suites/regression-tests/programs/test012.ast b/asteroid/test-suites/regression-tests/test012.ast
similarity index 83%
rename from asteroid/test-suites/regression-tests/programs/test012.ast
rename to asteroid/test-suites/regression-tests/test012.ast
index 2afad3a8..f5bc7a54 100644
--- a/asteroid/test-suites/regression-tests/programs/test012.ast
+++ b/asteroid/test-suites/regression-tests/test012.ast
@@ -1,6 +1,6 @@
 
 -- Palindrome list filter
-load "io".
+load io.
 
 function filter 
     with (x:%string) if x @explode() == x @explode() @reverse() do
@@ -9,4 +9,4 @@ function filter
         return false.
     end
     
-print (filter "radar").
+io @print (filter "radar").
diff --git a/asteroid/test-suites/regression-tests/test013.ast b/asteroid/test-suites/regression-tests/test013.ast
new file mode 100644
index 00000000..3b7251e2
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test013.ast
@@ -0,0 +1,4 @@
+
+load io.
+let i:%integer = 1.
+io @print i.
diff --git a/asteroid/test-suites/regression-tests/test014.ast b/asteroid/test-suites/regression-tests/test014.ast
new file mode 100644
index 00000000..cfa5a679
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test014.ast
@@ -0,0 +1,8 @@
+
+load system io.
+
+try
+    let (1,y) = pattern (1,x).
+catch e do
+    io @println e.
+end
diff --git a/asteroid/test-suites/regression-tests/programs/test015.ast b/asteroid/test-suites/regression-tests/test015.ast
similarity index 78%
rename from asteroid/test-suites/regression-tests/programs/test015.ast
rename to asteroid/test-suites/regression-tests/test015.ast
index f3b9ee8f..61c1b43b 100644
--- a/asteroid/test-suites/regression-tests/programs/test015.ast
+++ b/asteroid/test-suites/regression-tests/test015.ast
@@ -1,44 +1,44 @@
 
-load "io".
+load system io.
 load "util".
 
 -- UPDATED 6-28-21 to reflect issue #27 resolution
 --------------------------------------------------TEST1--
 try
     let (x,x) = (1,1).
-    println x.
+    io @println x.
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST2--
 try
     let [x,w,y,[a,b,x]] = [1,2,3,[1,2,1]].
-    println x.
+    io @println x.
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST3--
 try
     let (name:%string,name:%string) = ("a","a").
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST4--
@@ -48,24 +48,24 @@ try
     let p3 = pattern with (*p1,*p2).
     let *p3 = ("a","a").
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST5--
 try
     let false = ((1,1) is (x,x)).
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST6--
@@ -81,12 +81,12 @@ try
 
     foo( (1,1) ).
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST7--
@@ -106,12 +106,12 @@ try
 
     assert(counter == 3).
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST8--
@@ -127,24 +127,24 @@ try
 
     foo( [1,1,1,1] ).
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------TEST9--
 try
     let (x,x:%integer) = (1,1).
 
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: no error").
 catch Exception("NonLinearPatternError", s) do
-    println("PASSED.").
+    io @println("PASSED.").
 catch _ do
-    println("FAILED.").
+    io @println("FAILED.").
     throw Error("FAIL: unexpected error").
 end.
 --------------------------------------------------END----
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/programs/test016.ast b/asteroid/test-suites/regression-tests/test016.ast
similarity index 53%
rename from asteroid/test-suites/regression-tests/programs/test016.ast
rename to asteroid/test-suites/regression-tests/test016.ast
index 24f59f84..1de41e3f 100644
--- a/asteroid/test-suites/regression-tests/programs/test016.ast
+++ b/asteroid/test-suites/regression-tests/test016.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 let (x,y) if x is y = ([1],[1]).
-println x.
+io @println x.
diff --git a/asteroid/test-suites/regression-tests/programs/test017.ast b/asteroid/test-suites/regression-tests/test017.ast
similarity index 78%
rename from asteroid/test-suites/regression-tests/programs/test017.ast
rename to asteroid/test-suites/regression-tests/test017.ast
index 1c3668fd..d32904e9 100644
--- a/asteroid/test-suites/regression-tests/programs/test017.ast
+++ b/asteroid/test-suites/regression-tests/test017.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 let (l:%list) if l is "\[.*2.*\]" = [1,2,3].
diff --git a/asteroid/test-suites/regression-tests/programs/test018.ast b/asteroid/test-suites/regression-tests/test018.ast
similarity index 74%
rename from asteroid/test-suites/regression-tests/programs/test018.ast
rename to asteroid/test-suites/regression-tests/test018.ast
index 254cff2a..22fb2cd3 100644
--- a/asteroid/test-suites/regression-tests/programs/test018.ast
+++ b/asteroid/test-suites/regression-tests/test018.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 structure A with
     data a.
     data b.
@@ -8,5 +8,5 @@ structure A with
 let a = A(1,2).
 let (v:%A) if v @a + 1 > 1 = a.
 let A(x:%string,_) = A("hello",2).
-println v.
-println x.
+io @println v.
+io @println x.
diff --git a/asteroid/test-suites/regression-tests/programs/test019.ast b/asteroid/test-suites/regression-tests/test019.ast
similarity index 79%
rename from asteroid/test-suites/regression-tests/programs/test019.ast
rename to asteroid/test-suites/regression-tests/test019.ast
index ae7605b4..ac1342b7 100644
--- a/asteroid/test-suites/regression-tests/programs/test019.ast
+++ b/asteroid/test-suites/regression-tests/test019.ast
@@ -1,7 +1,7 @@
 
 -- Factorial
 
-load "io".
+load system io.
 load "util".
 
 function fact 
@@ -13,6 +13,6 @@ function fact
         throw Error("factorial is not defined for "+n).
     end 
 
-println ("The factorial of 3 is: " + fact (3)).
+io @println ("The factorial of 3 is: " + fact (3)).
 assert (fact(3) == 6).
 
diff --git a/asteroid/test-suites/regression-tests/programs/test020.ast b/asteroid/test-suites/regression-tests/test020.ast
similarity index 51%
rename from asteroid/test-suites/regression-tests/programs/test020.ast
rename to asteroid/test-suites/regression-tests/test020.ast
index b764a8be..742a8161 100644
--- a/asteroid/test-suites/regression-tests/programs/test020.ast
+++ b/asteroid/test-suites/regression-tests/test020.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 let (x:%integer) if x > 0 = 2.
-println x.
+io @println x.
diff --git a/asteroid/test-suites/regression-tests/test021.ast b/asteroid/test-suites/regression-tests/test021.ast
new file mode 100644
index 00000000..a5d6264a
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test021.ast
@@ -0,0 +1,5 @@
+
+load system io.
+
+let a:%list = [1,2] .
+io @println a.
diff --git a/asteroid/test-suites/regression-tests/programs/test022.ast b/asteroid/test-suites/regression-tests/test022.ast
similarity index 72%
rename from asteroid/test-suites/regression-tests/programs/test022.ast
rename to asteroid/test-suites/regression-tests/test022.ast
index ca9f576a..b0591428 100644
--- a/asteroid/test-suites/regression-tests/programs/test022.ast
+++ b/asteroid/test-suites/regression-tests/test022.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 structure A with
     data a.
     data b.
@@ -7,4 +7,4 @@ structure A with
 
 let a = A(1,2).
 let v:%A = a.
-println v.
+io @println v.
diff --git a/asteroid/test-suites/regression-tests/programs/test023.ast b/asteroid/test-suites/regression-tests/test023.ast
similarity index 84%
rename from asteroid/test-suites/regression-tests/programs/test023.ast
rename to asteroid/test-suites/regression-tests/test023.ast
index f4e834e2..3f455940 100644
--- a/asteroid/test-suites/regression-tests/programs/test023.ast
+++ b/asteroid/test-suites/regression-tests/test023.ast
@@ -1,5 +1,5 @@
 
--- load "io".
+-- load system io.
 structure A with
     data a.
     data b.
diff --git a/asteroid/test-suites/regression-tests/programs/test024.ast b/asteroid/test-suites/regression-tests/test024.ast
similarity index 61%
rename from asteroid/test-suites/regression-tests/programs/test024.ast
rename to asteroid/test-suites/regression-tests/test024.ast
index 96e33200..66cc262a 100644
--- a/asteroid/test-suites/regression-tests/programs/test024.ast
+++ b/asteroid/test-suites/regression-tests/test024.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 
 function ident with i do return i end
 
 try
     let p = not ident(1).
-    println p.
+    io @println p.
 catch e do
-    println e.
+    io @println e.
 end
diff --git a/asteroid/test-suites/regression-tests/test025.ast b/asteroid/test-suites/regression-tests/test025.ast
new file mode 100644
index 00000000..eed2ebd0
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test025.ast
@@ -0,0 +1,5 @@
+
+load system io.
+
+let q:%integer = 3.
+io @println q.
diff --git a/asteroid/test-suites/regression-tests/programs/test026.ast b/asteroid/test-suites/regression-tests/test026.ast
similarity index 60%
rename from asteroid/test-suites/regression-tests/programs/test026.ast
rename to asteroid/test-suites/regression-tests/test026.ast
index 8c844228..5a7b5971 100644
--- a/asteroid/test-suites/regression-tests/programs/test026.ast
+++ b/asteroid/test-suites/regression-tests/test026.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 
 function ident with i do return i end
 
 try
     let p = - ident(1).
-    println p.
+    io @println p.
 catch e do
-    println e.
+    io @println e.
 end
diff --git a/asteroid/test-suites/regression-tests/programs/test027.ast b/asteroid/test-suites/regression-tests/test027.ast
similarity index 65%
rename from asteroid/test-suites/regression-tests/programs/test027.ast
rename to asteroid/test-suites/regression-tests/test027.ast
index 79860e95..3b53c07b 100644
--- a/asteroid/test-suites/regression-tests/programs/test027.ast
+++ b/asteroid/test-suites/regression-tests/test027.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 structure A with
     data a.
@@ -13,6 +13,6 @@ structure B with
 let q = B([1,2,3]).
 let p = B(A(1)).
 
-println (q @ b).
-println (q @b @length()). 
-println (p @b @hello()).
+io @println (q @ b).
+io @println (q @b @length()). 
+io @println (p @b @hello()).
diff --git a/asteroid/test-suites/regression-tests/programs/test028.ast b/asteroid/test-suites/regression-tests/test028.ast
similarity index 69%
rename from asteroid/test-suites/regression-tests/programs/test028.ast
rename to asteroid/test-suites/regression-tests/test028.ast
index 5ba3e7c0..9ca8e4f8 100644
--- a/asteroid/test-suites/regression-tests/programs/test028.ast
+++ b/asteroid/test-suites/regression-tests/test028.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
     
 structure B with
     data b.
@@ -8,4 +8,4 @@ structure B with
     
 let q = B([1,2,3]).
 
-println (q @get() @length()). 
+io @println (q @get() @length()). 
diff --git a/asteroid/test-suites/regression-tests/programs/test029.ast b/asteroid/test-suites/regression-tests/test029.ast
similarity index 53%
rename from asteroid/test-suites/regression-tests/programs/test029.ast
rename to asteroid/test-suites/regression-tests/test029.ast
index 8c6ca0ba..2c42d8b0 100644
--- a/asteroid/test-suites/regression-tests/programs/test029.ast
+++ b/asteroid/test-suites/regression-tests/test029.ast
@@ -1,9 +1,9 @@
 
-load "io".
-load "hash".
+load system io.
+load system hash.
 
-let h = HashTable().
+let h = hash @hash().
 h @insert("hello","there").
 let result = h @get("hello").
-println (result).
+io @println (result).
 assert (result is "there").
diff --git a/asteroid/test-suites/regression-tests/programs/test030.ast b/asteroid/test-suites/regression-tests/test030.ast
similarity index 59%
rename from asteroid/test-suites/regression-tests/programs/test030.ast
rename to asteroid/test-suites/regression-tests/test030.ast
index 998f0485..363ed28f 100644
--- a/asteroid/test-suites/regression-tests/programs/test030.ast
+++ b/asteroid/test-suites/regression-tests/test030.ast
@@ -1,6 +1,6 @@
 
-load "io".
+load system io.
 
 let name:"a.*" = "abc".
-println name.
+io @println name.
 assert (name is "abc")
diff --git a/asteroid/test-suites/regression-tests/programs/test031.ast b/asteroid/test-suites/regression-tests/test031.ast
similarity index 88%
rename from asteroid/test-suites/regression-tests/programs/test031.ast
rename to asteroid/test-suites/regression-tests/test031.ast
index c42c05a1..b51c835e 100644
--- a/asteroid/test-suites/regression-tests/programs/test031.ast
+++ b/asteroid/test-suites/regression-tests/test031.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -15,6 +15,6 @@ let people = [
     ].
 
 for Person(name:".*p.*",_,_) in people do
-  println name.
+  io @println name.
 end
 assert(name is "Sophie")
diff --git a/asteroid/test-suites/regression-tests/programs/test032.ast b/asteroid/test-suites/regression-tests/test032.ast
similarity index 76%
rename from asteroid/test-suites/regression-tests/programs/test032.ast
rename to asteroid/test-suites/regression-tests/test032.ast
index 3681d254..8eede35d 100644
--- a/asteroid/test-suites/regression-tests/programs/test032.ast
+++ b/asteroid/test-suites/regression-tests/test032.ast
@@ -1,7 +1,7 @@
 
-load "io".
+load system io.
 
 function addc with x do return lambda with y do return x + y end
 let a = (addc 1) 1.
-println a.
+io @println a.
 assert(a is 2).
diff --git a/asteroid/test-suites/regression-tests/programs/test033.ast b/asteroid/test-suites/regression-tests/test033.ast
similarity index 55%
rename from asteroid/test-suites/regression-tests/programs/test033.ast
rename to asteroid/test-suites/regression-tests/test033.ast
index d085141e..8404d25f 100644
--- a/asteroid/test-suites/regression-tests/programs/test033.ast
+++ b/asteroid/test-suites/regression-tests/test033.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 let a = "abcde".
 let i = a @1.
-println i.
+io @println i.
 let b = a @[0,2,4].
-println b.
+io @println b.
 let i = a @length().
-println i.
+io @println i.
 let e = a @explode().
-println e.
+io @println e.
diff --git a/asteroid/test-suites/regression-tests/test034.ast b/asteroid/test-suites/regression-tests/test034.ast
new file mode 100644
index 00000000..9e733d20
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test034.ast
@@ -0,0 +1,9 @@
+
+load system io.
+let a = [1,2,3].
+io @println (a @length()).
+a @append(3).
+a @insert(2,4).
+io @println a.
+a @sort(true).
+io @println a.
diff --git a/asteroid/test-suites/regression-tests/test035.ast b/asteroid/test-suites/regression-tests/test035.ast
new file mode 100644
index 00000000..dea03449
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test035.ast
@@ -0,0 +1,7 @@
+
+load system io.
+let a = [].
+
+if a is [b|rest] do
+    io @println "yes".
+end
diff --git a/asteroid/test-suites/regression-tests/programs/test036.ast b/asteroid/test-suites/regression-tests/test036.ast
similarity index 53%
rename from asteroid/test-suites/regression-tests/programs/test036.ast
rename to asteroid/test-suites/regression-tests/test036.ast
index c3d9e944..c1098e21 100644
--- a/asteroid/test-suites/regression-tests/programs/test036.ast
+++ b/asteroid/test-suites/regression-tests/test036.ast
@@ -1,7 +1,7 @@
 
-load "io".
+load system io.
 let a = [1,2].
 
 if a is [b|c|d|rest] do
-    println "yes".
+    io @println "yes".
 end
diff --git a/asteroid/test-suites/regression-tests/test037.ast b/asteroid/test-suites/regression-tests/test037.ast
new file mode 100644
index 00000000..e94bff2f
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test037.ast
@@ -0,0 +1,4 @@
+
+load system io.
+let fst = (1,2)@0.
+io @println fst.
diff --git a/asteroid/test-suites/regression-tests/test038.ast b/asteroid/test-suites/regression-tests/test038.ast
new file mode 100644
index 00000000..6ab55e07
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test038.ast
@@ -0,0 +1,4 @@
+
+load system io.
+let t = (1,2).
+io @println ("tuple = " + t).
diff --git a/asteroid/test-suites/regression-tests/programs/test039.ast b/asteroid/test-suites/regression-tests/test039.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test039.ast
rename to asteroid/test-suites/regression-tests/test039.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test040.ast b/asteroid/test-suites/regression-tests/test040.ast
similarity index 82%
rename from asteroid/test-suites/regression-tests/programs/test040.ast
rename to asteroid/test-suites/regression-tests/test040.ast
index ae00c854..cd5b92ea 100644
--- a/asteroid/test-suites/regression-tests/programs/test040.ast
+++ b/asteroid/test-suites/regression-tests/test040.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure Dog with
@@ -32,9 +32,9 @@ let buddy = Dog("Buddy").
 buddy @add_trick("roll over").
 buddy @add_trick("sit stay").
 
--- println out the tricks
-println ("Fido: " + fido @tricks).
-println ("Buddy: " + buddy @tricks).
+-- io @println out the tricks
+io @println ("Fido: " + fido @tricks).
+io @println ("Buddy: " + 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/programs/test041.ast b/asteroid/test-suites/regression-tests/test041.ast
similarity index 54%
rename from asteroid/test-suites/regression-tests/programs/test041.ast
rename to asteroid/test-suites/regression-tests/test041.ast
index 014ab7dc..e55c8064 100644
--- a/asteroid/test-suites/regression-tests/programs/test041.ast
+++ b/asteroid/test-suites/regression-tests/test041.ast
@@ -1,16 +1,16 @@
 
-load "io".
+load system io.
 
 structure A with
     data x.
-    function dump with none do println (this@x) end .
+    function dump with none do io @println (this@x) end .
     end 
 
 let obj = A(2).
 obj @dump().
 
 let A(x) = obj.
-println x.
+io @println x.
 
 assert(x is 2).
 
diff --git a/asteroid/test-suites/regression-tests/programs/test042.ast b/asteroid/test-suites/regression-tests/test042.ast
similarity index 88%
rename from asteroid/test-suites/regression-tests/programs/test042.ast
rename to asteroid/test-suites/regression-tests/test042.ast
index 40871c4a..ba333767 100644
--- a/asteroid/test-suites/regression-tests/programs/test042.ast
+++ b/asteroid/test-suites/regression-tests/test042.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure A with
@@ -18,9 +18,9 @@ structure A with
     end 
 
 let obj1 = A("hello","world").
-println obj1.
+io @println obj1.
 let obj2 = A().
-println obj2.
+io @println obj2.
 
 assert((obj1 @x is "hello") and (obj1 @y is "world")).
 assert((obj2 @x is 1) and (obj2 @y is 2)).
diff --git a/asteroid/test-suites/regression-tests/programs/test043.ast b/asteroid/test-suites/regression-tests/test043.ast
similarity index 91%
rename from asteroid/test-suites/regression-tests/programs/test043.ast
rename to asteroid/test-suites/regression-tests/test043.ast
index 3d3e1b7b..23eba019 100644
--- a/asteroid/test-suites/regression-tests/programs/test043.ast
+++ b/asteroid/test-suites/regression-tests/test043.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -16,5 +16,5 @@ 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") + ".".
-println output_str.
+io @println output_str.
 assert(output_str is "Sophie is 46 years old and is female.")
diff --git a/asteroid/test-suites/regression-tests/test044.ast b/asteroid/test-suites/regression-tests/test044.ast
new file mode 100644
index 00000000..c488a5ec
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test044.ast
@@ -0,0 +1,6 @@
+
+load system io.      
+load "util".
+let slice = [4 to 0 stride 1].
+io @println slice.
+assert(slice is [4,3,2,1,0]).
diff --git a/asteroid/test-suites/regression-tests/programs/test045.ast b/asteroid/test-suites/regression-tests/test045.ast
similarity index 72%
rename from asteroid/test-suites/regression-tests/programs/test045.ast
rename to asteroid/test-suites/regression-tests/test045.ast
index fa99f22f..c7ebc46b 100644
--- a/asteroid/test-suites/regression-tests/programs/test045.ast
+++ b/asteroid/test-suites/regression-tests/test045.ast
@@ -1,8 +1,8 @@
 
-load "io".
+load system io.
 load "util".
 
 let a = [[1,2],[3,4],[5,6]].
 let l = (a @0).
-println l.
+io @println l.
 assert(l is [1,2]).
diff --git a/asteroid/test-suites/regression-tests/programs/test046.ast b/asteroid/test-suites/regression-tests/test046.ast
similarity index 53%
rename from asteroid/test-suites/regression-tests/programs/test046.ast
rename to asteroid/test-suites/regression-tests/test046.ast
index c739f505..84471d96 100644
--- a/asteroid/test-suites/regression-tests/programs/test046.ast
+++ b/asteroid/test-suites/regression-tests/test046.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 load "util".
 
 let a = [10,20,30].
 let x = a @(1).
 let y = a @[1].
 
-println x. -- prints out a scalar 
-println y. -- prints out a list
+io @println x. -- prints out a scalar 
+io @println y. -- prints out a list
 assert((x is 20) and (y is [20])).
diff --git a/asteroid/test-suites/regression-tests/test047.ast b/asteroid/test-suites/regression-tests/test047.ast
new file mode 100644
index 00000000..e1096b8c
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test047.ast
@@ -0,0 +1,8 @@
+
+load system random.
+load system io.
+
+let v = random @random().
+
+io @println v.
+assert(v <= 1.0 and v >= 0.0).
diff --git a/asteroid/test-suites/regression-tests/programs/test049.ast b/asteroid/test-suites/regression-tests/test049.ast
similarity index 82%
rename from asteroid/test-suites/regression-tests/programs/test049.ast
rename to asteroid/test-suites/regression-tests/test049.ast
index 79f3eb5e..e311755f 100644
--- a/asteroid/test-suites/regression-tests/programs/test049.ast
+++ b/asteroid/test-suites/regression-tests/test049.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 let (f,g) = (1,2).
 
@@ -10,6 +10,6 @@ function foobar
     end 
     
 foobar(none).
-println (f,g).
+io @println (f,g).
 
 assert((f,g) is (2,2)).
diff --git a/asteroid/test-suites/regression-tests/test050.ast b/asteroid/test-suites/regression-tests/test050.ast
new file mode 100644
index 00000000..709b38c4
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test050.ast
@@ -0,0 +1,9 @@
+
+load system io.
+
+try 
+    let 2 = 1 + 1. 
+catch _ do
+    io @println "pattern match failed".
+end 
+
diff --git a/asteroid/test-suites/regression-tests/programs/test051.ast b/asteroid/test-suites/regression-tests/test051.ast
similarity index 75%
rename from asteroid/test-suites/regression-tests/programs/test051.ast
rename to asteroid/test-suites/regression-tests/test051.ast
index 856aac35..346305ab 100644
--- a/asteroid/test-suites/regression-tests/programs/test051.ast
+++ b/asteroid/test-suites/regression-tests/test051.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 
 let 2 = 1 + 1. -- (*@\label{patternmatching-models:let1a}@*)
 
 try 
     let 1 + 1 = 1 + 1. -- throws an exception (*@\label{patternmatching-models:let3}@*)
 catch _ do
-    println "pattern match failed".
+    io @println "pattern match failed".
 end 
 
diff --git a/asteroid/test-suites/regression-tests/programs/test052.ast b/asteroid/test-suites/regression-tests/test052.ast
similarity index 53%
rename from asteroid/test-suites/regression-tests/programs/test052.ast
rename to asteroid/test-suites/regression-tests/test052.ast
index 04627480..e2908b8d 100644
--- a/asteroid/test-suites/regression-tests/programs/test052.ast
+++ b/asteroid/test-suites/regression-tests/test052.ast
@@ -1,8 +1,8 @@
 
-load "io".
+load system io.
 
 try
     let -1 = -1 .
 catch e do
-    println e.
+    io @println e.
 end 
diff --git a/asteroid/test-suites/regression-tests/programs/test053.ast b/asteroid/test-suites/regression-tests/test053.ast
similarity index 83%
rename from asteroid/test-suites/regression-tests/programs/test053.ast
rename to asteroid/test-suites/regression-tests/test053.ast
index a4e99e9a..2933a0de 100644
--- a/asteroid/test-suites/regression-tests/programs/test053.ast
+++ b/asteroid/test-suites/regression-tests/test053.ast
@@ -1,10 +1,10 @@
 
-load "io".
+load system io.
 load "util".
 let p = -1.
 let w = p - 1.
 let q = [-1].
-println (p,w,q).
+io @println (p,w,q).
 
 -- NOTE: workaround, pattern matching does not work on negative constants.
 assert(p == -1).
diff --git a/asteroid/test-suites/regression-tests/programs/test055.ast b/asteroid/test-suites/regression-tests/test055.ast
similarity index 68%
rename from asteroid/test-suites/regression-tests/programs/test055.ast
rename to asteroid/test-suites/regression-tests/test055.ast
index 3c5640af..a17662ec 100644
--- a/asteroid/test-suites/regression-tests/programs/test055.ast
+++ b/asteroid/test-suites/regression-tests/test055.ast
@@ -1,10 +1,10 @@
 
-load "io".
+load system io.
 load "util".
 
 let cl = 1 + 2.
 let cr = 3.
 let p = cl + cr.
 
-println (1+2+3 is *p).
+io @println (1+2+3 is *p).
 assert ((1+2+3 is *p) is true).
diff --git a/asteroid/test-suites/regression-tests/programs/test057.ast b/asteroid/test-suites/regression-tests/test057.ast
similarity index 77%
rename from asteroid/test-suites/regression-tests/programs/test057.ast
rename to asteroid/test-suites/regression-tests/test057.ast
index 4f7af629..71f0717a 100644
--- a/asteroid/test-suites/regression-tests/programs/test057.ast
+++ b/asteroid/test-suites/regression-tests/test057.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 
 structure MyException with 
     data e.
@@ -8,5 +8,5 @@ structure MyException with
 try
     throw MyException("Hello There!").
 catch MyException(v) do
-    println v.
+    io @println v.
 end 
diff --git a/asteroid/test-suites/regression-tests/test058.ast b/asteroid/test-suites/regression-tests/test058.ast
new file mode 100644
index 00000000..2e8b1758
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test058.ast
@@ -0,0 +1,9 @@
+
+load system io.
+
+try
+    let i = 10/0.
+    io @println i.
+catch e do
+    io @println e.
+end 
diff --git a/asteroid/test-suites/regression-tests/programs/test059.ast b/asteroid/test-suites/regression-tests/test059.ast
similarity index 50%
rename from asteroid/test-suites/regression-tests/programs/test059.ast
rename to asteroid/test-suites/regression-tests/test059.ast
index 3a444c6a..73e6f735 100644
--- a/asteroid/test-suites/regression-tests/programs/test059.ast
+++ b/asteroid/test-suites/regression-tests/test059.ast
@@ -1,9 +1,9 @@
 
-load "io".
+load system io.
 
 try
     let i = 10/0.
-    println i.
+    io @println i.
 catch Exception(_, v) do
-    println v.
+    io @println v.
 end 
diff --git a/asteroid/test-suites/regression-tests/programs/test060.ast b/asteroid/test-suites/regression-tests/test060.ast
similarity index 82%
rename from asteroid/test-suites/regression-tests/programs/test060.ast
rename to asteroid/test-suites/regression-tests/test060.ast
index 5d824910..947e5bf8 100644
--- a/asteroid/test-suites/regression-tests/programs/test060.ast
+++ b/asteroid/test-suites/regression-tests/test060.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure Person with
@@ -21,9 +21,9 @@ for Person(_,age,_) in people do
     let sum = sum + age.
 end 
 
-println ("Average Age: " + (sum/n)).
+io @println ("Average Age: " + (sum/n)).
 assert ((sum/n) == 33).
 
 for Person(name,_,"M") in people do
-    println name.
+    io @println name.
 end 
diff --git a/asteroid/test-suites/regression-tests/programs/test061.ast b/asteroid/test-suites/regression-tests/test061.ast
similarity index 63%
rename from asteroid/test-suites/regression-tests/programs/test061.ast
rename to asteroid/test-suites/regression-tests/test061.ast
index a9c103d5..a31fae2d 100644
--- a/asteroid/test-suites/regression-tests/programs/test061.ast
+++ b/asteroid/test-suites/regression-tests/test061.ast
@@ -1,9 +1,9 @@
 
-load "io".
+load system io.
 
 let l = [1,2,3].
 
 repeat do
     let [head|l] = l.
-    println head.
+    io @println head.
 until l is [].
diff --git a/asteroid/test-suites/regression-tests/programs/test063.ast b/asteroid/test-suites/regression-tests/test063.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test063.ast
rename to asteroid/test-suites/regression-tests/test063.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test064.ast b/asteroid/test-suites/regression-tests/test064.ast
similarity index 83%
rename from asteroid/test-suites/regression-tests/programs/test064.ast
rename to asteroid/test-suites/regression-tests/test064.ast
index 02ad4cfd..282a1db9 100644
--- a/asteroid/test-suites/regression-tests/programs/test064.ast
+++ b/asteroid/test-suites/regression-tests/test064.ast
@@ -1,6 +1,6 @@
 
 -- implements Peano addition on terms
-load "io".
+load system io.
 load "util".
 
 structure S with
@@ -21,5 +21,5 @@ function reduce
         return term.
     end 
 
-println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
+io @println(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0)))).
 assert(reduce(add(add(add(S(S(0)),S(S(S(0)))),S(0)),S(0))) is S(S(S(S(S(S(S(0)))))))).
diff --git a/asteroid/test-suites/regression-tests/programs/test065.ast b/asteroid/test-suites/regression-tests/test065.ast
similarity index 91%
rename from asteroid/test-suites/regression-tests/programs/test065.ast
rename to asteroid/test-suites/regression-tests/test065.ast
index 04a0ec2a..318b0446 100644
--- a/asteroid/test-suites/regression-tests/programs/test065.ast
+++ b/asteroid/test-suites/regression-tests/test065.ast
@@ -1,7 +1,7 @@
 
 -- Quicksort
 
-load "io".
+load system io.
 load "util".
 
 function qsort
@@ -24,5 +24,5 @@ function qsort
         return qsort less + [pivot] + qsort more.
     end 
     
-println (qsort [3,2,1,0]).
+io @println (qsort [3,2,1,0]).
 assert (qsort [3,2,1,0] == [0,1,2,3]).
diff --git a/asteroid/test-suites/regression-tests/programs/test066.ast b/asteroid/test-suites/regression-tests/test066.ast
similarity index 83%
rename from asteroid/test-suites/regression-tests/programs/test066.ast
rename to asteroid/test-suites/regression-tests/test066.ast
index 634e35eb..70597741 100644
--- a/asteroid/test-suites/regression-tests/programs/test066.ast
+++ b/asteroid/test-suites/regression-tests/test066.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 function postfix
@@ -11,5 +11,5 @@ function postfix
         return (v,)
 end 
 
-println (postfix ("+", (1,), (2,))).
+io @println (postfix ("+", (1,), (2,))).
 assert ((postfix ("+", (1,), (2,))) is ((1,),(2,),"\+")). -- strings in patterns are REs!
diff --git a/asteroid/test-suites/regression-tests/test067-io.txt b/asteroid/test-suites/regression-tests/test067-io.txt
new file mode 100644
index 00000000..8148ef7a
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test067-io.txt
@@ -0,0 +1,2 @@
+3
+
diff --git a/asteroid/test-suites/regression-tests/test067.ast b/asteroid/test-suites/regression-tests/test067.ast
new file mode 100644
index 00000000..c5edecd9
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test067.ast
@@ -0,0 +1,10 @@
+
+load system type.
+load system io.
+
+let cnt = type @tointeger(io @input("Please enter an integer value: ")).
+
+for i in 1 to cnt do
+    io @println i.
+end
+assert (i is cnt).
diff --git a/asteroid/test-suites/regression-tests/test068-io.txt b/asteroid/test-suites/regression-tests/test068-io.txt
new file mode 100644
index 00000000..599f87bf
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test068-io.txt
@@ -0,0 +1,2 @@
+Leo
+
diff --git a/asteroid/test-suites/regression-tests/test068.ast b/asteroid/test-suites/regression-tests/test068.ast
new file mode 100644
index 00000000..d05b7e2b
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test068.ast
@@ -0,0 +1,5 @@
+
+load system io.
+
+let name = io @input("Please enter your name: ").
+io @println("Hello " + name + "!").
diff --git a/asteroid/test-suites/regression-tests/programs/test070.ast b/asteroid/test-suites/regression-tests/test070.ast
similarity index 79%
rename from asteroid/test-suites/regression-tests/programs/test070.ast
rename to asteroid/test-suites/regression-tests/test070.ast
index f8dc6f4e..d00b2ee8 100644
--- a/asteroid/test-suites/regression-tests/programs/test070.ast
+++ b/asteroid/test-suites/regression-tests/test070.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 function ident 
@@ -9,5 +9,5 @@ function ident
 
 let y = ident ident  0.
 
-println y.
+io @println y.
 assert (y is 0).
diff --git a/asteroid/test-suites/regression-tests/programs/test071.ast b/asteroid/test-suites/regression-tests/test071.ast
similarity index 81%
rename from asteroid/test-suites/regression-tests/programs/test071.ast
rename to asteroid/test-suites/regression-tests/test071.ast
index 898ee551..fe32dff3 100644
--- a/asteroid/test-suites/regression-tests/programs/test071.ast
+++ b/asteroid/test-suites/regression-tests/test071.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 function ident 
@@ -10,5 +10,5 @@ function ident
 let y = ident(ident (0)).
 let x = ident ident 0.
 
-println (x,y).
+io @println (x,y).
 assert ((x,y) is (0,0)).
diff --git a/asteroid/test-suites/regression-tests/programs/test072.ast b/asteroid/test-suites/regression-tests/test072.ast
similarity index 69%
rename from asteroid/test-suites/regression-tests/programs/test072.ast
rename to asteroid/test-suites/regression-tests/test072.ast
index aeece61d..8bb43baa 100644
--- a/asteroid/test-suites/regression-tests/programs/test072.ast
+++ b/asteroid/test-suites/regression-tests/test072.ast
@@ -1,7 +1,7 @@
 
 -- Factorial
 
-load "io".
+load system io.
 load "util".
 
 function fact 
@@ -11,5 +11,5 @@ function fact
         return n * fact (n-1).
     end 
 
-println ("The factorial of 3 is: " + fact (3)).
+io @println ("The factorial of 3 is: " + fact (3)).
 assert (fact(3) == 6).
diff --git a/asteroid/test-suites/regression-tests/programs/test073.ast b/asteroid/test-suites/regression-tests/test073.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test073.ast
rename to asteroid/test-suites/regression-tests/test073.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test074.ast b/asteroid/test-suites/regression-tests/test074.ast
similarity index 81%
rename from asteroid/test-suites/regression-tests/programs/test074.ast
rename to asteroid/test-suites/regression-tests/test074.ast
index 91c34f7b..482f7b64 100644
--- a/asteroid/test-suites/regression-tests/programs/test074.ast
+++ b/asteroid/test-suites/regression-tests/test074.ast
@@ -1,6 +1,6 @@
 
 load "util".
-load "io".
+load system io.
 
 structure MyError with 
     data e.
@@ -11,7 +11,7 @@ try
     throw Error "--- error ---".
     
 catch Error(msg) do
-    println msg.
+    io @println msg.
     assert (msg == "--- error ---")
 end 
 
diff --git a/asteroid/test-suites/regression-tests/programs/test075.ast b/asteroid/test-suites/regression-tests/test075.ast
similarity index 52%
rename from asteroid/test-suites/regression-tests/programs/test075.ast
rename to asteroid/test-suites/regression-tests/test075.ast
index 28d5bb82..95b4ff34 100644
--- a/asteroid/test-suites/regression-tests/programs/test075.ast
+++ b/asteroid/test-suites/regression-tests/test075.ast
@@ -1,7 +1,7 @@
 
-load "io".
+load system io.
 load "util".
 
 let [h|t] = [1,2,3].
-println ("head: " + h + " tail: " + t).
+io @println ("head: " + h + " tail: " + t).
 assert(h == 1 and t == [2,3]).
diff --git a/asteroid/test-suites/regression-tests/programs/test076.ast b/asteroid/test-suites/regression-tests/test076.ast
similarity index 69%
rename from asteroid/test-suites/regression-tests/programs/test076.ast
rename to asteroid/test-suites/regression-tests/test076.ast
index 0bdd47d6..dd641c21 100644
--- a/asteroid/test-suites/regression-tests/programs/test076.ast
+++ b/asteroid/test-suites/regression-tests/test076.ast
@@ -1,8 +1,8 @@
 
-load "io".
+load system io.
 load "util".
 
 let y = -1.
 let x = 4 if y == 3 else 0.
-println x.
+io @println x.
 assert (x == 0).
diff --git a/asteroid/test-suites/regression-tests/programs/test077.ast b/asteroid/test-suites/regression-tests/test077.ast
similarity index 73%
rename from asteroid/test-suites/regression-tests/programs/test077.ast
rename to asteroid/test-suites/regression-tests/test077.ast
index 27a294cb..e01a1301 100644
--- a/asteroid/test-suites/regression-tests/programs/test077.ast
+++ b/asteroid/test-suites/regression-tests/test077.ast
@@ -1,9 +1,9 @@
 
-load "io".
+load system io.
 load "util".
 
 for x in 0 to 10 do
-    println x.
+    io @println x.
     if x == 5 do
         break.
     end 
diff --git a/asteroid/test-suites/regression-tests/programs/test078.ast b/asteroid/test-suites/regression-tests/test078.ast
similarity index 71%
rename from asteroid/test-suites/regression-tests/programs/test078.ast
rename to asteroid/test-suites/regression-tests/test078.ast
index dc5d6fe2..80fd440f 100644
--- a/asteroid/test-suites/regression-tests/programs/test078.ast
+++ b/asteroid/test-suites/regression-tests/test078.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 
 for (x,y) in [(1,1), (2,2), (3,3)]  do
-    println (x,y).
+    io @println (x,y).
 end 
 
 -- use unification as a filter
 for (2,y) in [(1,11), (1,12), (1,13), (2,21), (2,22), (2,23)]  do
-    println y.
+    io @println y.
 end 
diff --git a/asteroid/test-suites/regression-tests/test079.ast b/asteroid/test-suites/regression-tests/test079.ast
new file mode 100644
index 00000000..042e1f1b
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test079.ast
@@ -0,0 +1,6 @@
+
+load system io.
+
+for x in 1 to 10 do
+    io @println x.
+end 
diff --git a/asteroid/test-suites/regression-tests/programs/test080.ast b/asteroid/test-suites/regression-tests/test080.ast
similarity index 56%
rename from asteroid/test-suites/regression-tests/programs/test080.ast
rename to asteroid/test-suites/regression-tests/test080.ast
index 490ba6b0..7ea8a332 100644
--- a/asteroid/test-suites/regression-tests/programs/test080.ast
+++ b/asteroid/test-suites/regression-tests/test080.ast
@@ -1,6 +1,6 @@
 
-load "io".
+load system io.
 
 for bird in ["turkey","duck","chicken"] do
-    println bird.
+    io @println bird.
 end 
diff --git a/asteroid/test-suites/regression-tests/test081.ast b/asteroid/test-suites/regression-tests/test081.ast
new file mode 100644
index 00000000..6699bf21
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test081.ast
@@ -0,0 +1,20 @@
+
+load system io.
+
+let x = 42.
+
+if x < 0 do
+    let x = 0.
+    io @println("Negative changed to zero").
+
+elif x == 0 do
+    io @println("Zero").
+
+elif x == 1 do
+    io @println("Single").
+
+else do
+    io @println("More").
+    
+end 
+
diff --git a/asteroid/test-suites/regression-tests/programs/test082.ast b/asteroid/test-suites/regression-tests/test082.ast
similarity index 70%
rename from asteroid/test-suites/regression-tests/programs/test082.ast
rename to asteroid/test-suites/regression-tests/test082.ast
index eb3a4fb5..6f5b6f62 100644
--- a/asteroid/test-suites/regression-tests/programs/test082.ast
+++ b/asteroid/test-suites/regression-tests/test082.ast
@@ -1,10 +1,10 @@
 
-load "io".
+load system io.
 load "util".
 
 let x = 1.
 while x <= 10 do
-    println x.
+    io @println x.
     let x = x + 1.
 end 
 assert (x == 11).
diff --git a/asteroid/test-suites/regression-tests/programs/test083.ast b/asteroid/test-suites/regression-tests/test083.ast
similarity index 76%
rename from asteroid/test-suites/regression-tests/programs/test083.ast
rename to asteroid/test-suites/regression-tests/test083.ast
index 005645a9..bc947b7b 100644
--- a/asteroid/test-suites/regression-tests/programs/test083.ast
+++ b/asteroid/test-suites/regression-tests/test083.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 let x = 1.
@@ -7,7 +7,7 @@ loop
     if x > 10 do
         break.
     end
-    println x.
+    io @println x.
     let x = x + 1.
 end 
 assert (x == 11).
diff --git a/asteroid/test-suites/regression-tests/programs/test084.ast b/asteroid/test-suites/regression-tests/test084.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test084.ast
rename to asteroid/test-suites/regression-tests/test084.ast
diff --git a/asteroid/test-suites/regression-tests/test085.ast b/asteroid/test-suites/regression-tests/test085.ast
new file mode 100644
index 00000000..b34cb522
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test085.ast
@@ -0,0 +1,14 @@
+
+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/test086.ast b/asteroid/test-suites/regression-tests/test086.ast
new file mode 100644
index 00000000..69291ce9
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test086.ast
@@ -0,0 +1,4 @@
+
+load system io.
+
+io @println (1,2,3).
diff --git a/asteroid/test-suites/regression-tests/programs/test087.ast b/asteroid/test-suites/regression-tests/test087.ast
similarity index 67%
rename from asteroid/test-suites/regression-tests/programs/test087.ast
rename to asteroid/test-suites/regression-tests/test087.ast
index d1e206ca..ceca84f1 100644
--- a/asteroid/test-suites/regression-tests/programs/test087.ast
+++ b/asteroid/test-suites/regression-tests/test087.ast
@@ -1,6 +1,6 @@
 
-load "io".
+load system io.
 load "util".
 let nl = [[1 to 5]].
-println nl.
+io @println nl.
 assert (nl is [[1,2,3,4,5]]).
diff --git a/asteroid/test-suites/regression-tests/programs/test088.ast b/asteroid/test-suites/regression-tests/test088.ast
similarity index 87%
rename from asteroid/test-suites/regression-tests/programs/test088.ast
rename to asteroid/test-suites/regression-tests/test088.ast
index 867b6e18..8d60d189 100644
--- a/asteroid/test-suites/regression-tests/programs/test088.ast
+++ b/asteroid/test-suites/regression-tests/test088.ast
@@ -1,11 +1,11 @@
 
 -- TODO: should this work similar to Rust?
-load "io".
+load system io.
 load "util".
 try
     let [1 to 3] = [1,2,3].
 catch Exception(_, v) do
-    println v.
+    io @println v.
     assert (v is "pattern match failed: pattern of type 'to-list' not allowed in pattern matching").
 end
 
diff --git a/asteroid/test-suites/regression-tests/programs/test089.ast b/asteroid/test-suites/regression-tests/test089.ast
similarity index 81%
rename from asteroid/test-suites/regression-tests/programs/test089.ast
rename to asteroid/test-suites/regression-tests/test089.ast
index 2bd40c9a..d1225d87 100644
--- a/asteroid/test-suites/regression-tests/programs/test089.ast
+++ b/asteroid/test-suites/regression-tests/test089.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure A with
@@ -10,5 +10,5 @@ structure A with
 
 let a = A(1,2,3).
 let b = a@[0 to 2].
-println b.
+io @println b.
 assert (b is [1,2,3]).
diff --git a/asteroid/test-suites/regression-tests/test090.ast b/asteroid/test-suites/regression-tests/test090.ast
new file mode 100644
index 00000000..e3bbee67
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test090.ast
@@ -0,0 +1,8 @@
+
+load system io.
+load "util".
+
+let a = [0,1,2,3].
+let b = a@[0 to 3 stride 2].
+io @println b.
+assert (b is [0,2]).
diff --git a/asteroid/test-suites/regression-tests/test091.ast b/asteroid/test-suites/regression-tests/test091.ast
new file mode 100644
index 00000000..81d22b2c
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test091.ast
@@ -0,0 +1,8 @@
+
+load system io.
+load "util".
+
+let y = [0 to 10 stride 2].
+let z = 4 in y.
+io @println z.
+assert z.
diff --git a/asteroid/test-suites/regression-tests/programs/test092.ast b/asteroid/test-suites/regression-tests/test092.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test092.ast
rename to asteroid/test-suites/regression-tests/test092.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test093.ast b/asteroid/test-suites/regression-tests/test093.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test093.ast
rename to asteroid/test-suites/regression-tests/test093.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test094.ast b/asteroid/test-suites/regression-tests/test094.ast
similarity index 80%
rename from asteroid/test-suites/regression-tests/programs/test094.ast
rename to asteroid/test-suites/regression-tests/test094.ast
index 76e49ca2..dda75905 100644
--- a/asteroid/test-suites/regression-tests/programs/test094.ast
+++ b/asteroid/test-suites/regression-tests/test094.ast
@@ -1,10 +1,10 @@
 
-load "io".
+load system io.
 load "util".
 
 let b = [[1,2,3],
          [4,5,6],
          [7,8,9]].
 let b@1@1 = 0.
-println b.
+io @println b.
 assert (b is [[1,2,3],[4,0,6],[7,8,9]]).
diff --git a/asteroid/test-suites/regression-tests/programs/test095.ast b/asteroid/test-suites/regression-tests/test095.ast
similarity index 71%
rename from asteroid/test-suites/regression-tests/programs/test095.ast
rename to asteroid/test-suites/regression-tests/test095.ast
index 2f305cf8..db643b09 100644
--- a/asteroid/test-suites/regression-tests/programs/test095.ast
+++ b/asteroid/test-suites/regression-tests/test095.ast
@@ -1,15 +1,15 @@
 
-load "io".
+load system io.
 -- -1 is a value
 try
     let -1 = -1.
 catch e do
-    println e.
+    io @println e.
 end 
 
 -- not true is a computation
 try
     let not true = not true.
 catch e do
-    println e.
+    io @println e.
 end 
diff --git a/asteroid/test-suites/regression-tests/programs/test096.ast b/asteroid/test-suites/regression-tests/test096.ast
similarity index 79%
rename from asteroid/test-suites/regression-tests/programs/test096.ast
rename to asteroid/test-suites/regression-tests/test096.ast
index 02ff502a..16b7fac8 100644
--- a/asteroid/test-suites/regression-tests/programs/test096.ast
+++ b/asteroid/test-suites/regression-tests/test096.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure A with
@@ -8,5 +8,5 @@ structure A with
     
 let a = A([1,2,3]).
 let a@0@1 = 0.
-println a.
+io @println a.
 assert (a is A([1,0,3])).
diff --git a/asteroid/test-suites/regression-tests/programs/test097.ast b/asteroid/test-suites/regression-tests/test097.ast
similarity index 75%
rename from asteroid/test-suites/regression-tests/programs/test097.ast
rename to asteroid/test-suites/regression-tests/test097.ast
index dad1178f..ed05c6b2 100644
--- a/asteroid/test-suites/regression-tests/programs/test097.ast
+++ b/asteroid/test-suites/regression-tests/test097.ast
@@ -1,9 +1,9 @@
 
-load "io".
+load system io.
 load "util".
 
 let a = [1,2,3].
 let b = [0,0,0].
 let [b@2,b@1,b@0] = a.
-println b.
+io @println b.
 assert (b is [3,2,1]).
diff --git a/asteroid/test-suites/regression-tests/programs/test098.ast b/asteroid/test-suites/regression-tests/test098.ast
similarity index 86%
rename from asteroid/test-suites/regression-tests/programs/test098.ast
rename to asteroid/test-suites/regression-tests/test098.ast
index ebd5d87d..d4e01890 100644
--- a/asteroid/test-suites/regression-tests/programs/test098.ast
+++ b/asteroid/test-suites/regression-tests/test098.ast
@@ -1,5 +1,5 @@
 
-load "io".
+load system io.
 load "util".
 
 structure A with 
@@ -20,5 +20,5 @@ let B(v,w) = y.
 let xx = x@0.
 let yy = y@[0,1].
 
-println (x,y,xx,yy).
+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/programs/test100.ast b/asteroid/test-suites/regression-tests/test100.ast
similarity index 77%
rename from asteroid/test-suites/regression-tests/programs/test100.ast
rename to asteroid/test-suites/regression-tests/test100.ast
index a20c432a..3d9e2371 100644
--- a/asteroid/test-suites/regression-tests/programs/test100.ast
+++ b/asteroid/test-suites/regression-tests/test100.ast
@@ -1,10 +1,10 @@
 
-load "io".
+load system io.
 load "util".
 
 function inc with n do return n+1 end 
 
 let v = inc(inc(0)).
 let q = 1 + 1 + 1.
-println (v, q).
+io @println (v, q).
 assert ((v, q) is (2,3)).
diff --git a/asteroid/test-suites/regression-tests/programs/test101.ast b/asteroid/test-suites/regression-tests/test101.ast
similarity index 78%
rename from asteroid/test-suites/regression-tests/programs/test101.ast
rename to asteroid/test-suites/regression-tests/test101.ast
index 462a16fa..a3c66a48 100644
--- a/asteroid/test-suites/regression-tests/programs/test101.ast
+++ b/asteroid/test-suites/regression-tests/test101.ast
@@ -1,19 +1,19 @@
 
 -- show off our overloaded '+' operator
-load "io".
+load system io.
 load "util".
 
-println (1 + 1).
+io @println (1 + 1).
 assert ((1+1) == 2).
 
 let s1 = "hello".
 let s2 = "world".
 let s3 = s1 + " " + s2 +"!".
-println s3.
+io @println s3.
 assert (s3 == "hello world!").
 
 let l1 = [1,2,3].
 let l2 = [4,5,6].
 let l3 = l1 + l2.
-println l3.
+io @println l3.
 assert (l3 == [1,2,3,4,5,6]).
diff --git a/asteroid/test-suites/regression-tests/programs/test102.ast b/asteroid/test-suites/regression-tests/test102.ast
similarity index 75%
rename from asteroid/test-suites/regression-tests/programs/test102.ast
rename to asteroid/test-suites/regression-tests/test102.ast
index 9b80cbce..67c8b391 100644
--- a/asteroid/test-suites/regression-tests/programs/test102.ast
+++ b/asteroid/test-suites/regression-tests/test102.ast
@@ -1,9 +1,9 @@
 
-load "io".
+load system io.
 load "util".
 
 -- reverse the list
 let a = [1,2,3].
 let a = a@[2,1,0].
-println a.
+io @println a.
 assert (a is [3,2,1]).
diff --git a/asteroid/test-suites/regression-tests/programs/test103.ast b/asteroid/test-suites/regression-tests/test103.ast
similarity index 81%
rename from asteroid/test-suites/regression-tests/programs/test103.ast
rename to asteroid/test-suites/regression-tests/test103.ast
index d11de781..063d827b 100644
--- a/asteroid/test-suites/regression-tests/programs/test103.ast
+++ b/asteroid/test-suites/regression-tests/test103.ast
@@ -1,11 +1,11 @@
 
-load "io".
+load system io.
 load "util".
 
 -- reverse the list
 let a = [1,2,3].
 let a = a@[2,1,0].
-println a.
+io @println a.
 assert (a is [3,2,1]).
 
 -- access multidim array
@@ -13,5 +13,5 @@ let b = [[1,2,3],
          [4,5,6],
          [7,8,9]].
 let e = b@1@1.
-println e.
+io @println e.
 assert (e is 5).
diff --git a/asteroid/test-suites/regression-tests/programs/test104.ast b/asteroid/test-suites/regression-tests/test104.ast
similarity index 81%
rename from asteroid/test-suites/regression-tests/programs/test104.ast
rename to asteroid/test-suites/regression-tests/test104.ast
index edb75a28..e00c618e 100644
--- a/asteroid/test-suites/regression-tests/programs/test104.ast
+++ b/asteroid/test-suites/regression-tests/test104.ast
@@ -1,10 +1,10 @@
 
-load "io".
+load system io.
 load "util".
 
 try
     let 1 = 1.0 .
 catch Exception(_,v) do
-    println v.
+    io @println v.
     assert(v is "pattern match failed: nodes 'real' and 'integer' are not the same").
 end
diff --git a/asteroid/test-suites/regression-tests/programs/test105.ast b/asteroid/test-suites/regression-tests/test105.ast
similarity index 66%
rename from asteroid/test-suites/regression-tests/programs/test105.ast
rename to asteroid/test-suites/regression-tests/test105.ast
index 93aca835..c641dd1c 100644
--- a/asteroid/test-suites/regression-tests/programs/test105.ast
+++ b/asteroid/test-suites/regression-tests/test105.ast
@@ -1,7 +1,7 @@
 
-load "io".
+load system io.
 load "util".
 
 function ident with n do return n end 
-println (ident(2)).
+io @println (ident(2)).
 assert (ident(2) is 2).
diff --git a/asteroid/test-suites/regression-tests/programs/test106.ast b/asteroid/test-suites/regression-tests/test106.ast
similarity index 66%
rename from asteroid/test-suites/regression-tests/programs/test106.ast
rename to asteroid/test-suites/regression-tests/test106.ast
index 10cfe57c..62da1d14 100644
--- a/asteroid/test-suites/regression-tests/programs/test106.ast
+++ b/asteroid/test-suites/regression-tests/test106.ast
@@ -1,7 +1,7 @@
 
-load "io".
+load system io.
 load "util".
 let x = 1. 
 function ident with n do return n end.
-println (ident( ident (x))) .
+io @println (ident( ident (x))) .
 assert (ident( ident (x)) is 1) .
diff --git a/asteroid/test-suites/regression-tests/test107.ast b/asteroid/test-suites/regression-tests/test107.ast
new file mode 100644
index 00000000..a13b08ff
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test107.ast
@@ -0,0 +1,6 @@
+
+load system io.
+load "util".
+
+io @println ((lambda with n do return n+1) 1).
+assert ((lambda with n do return n+1) 1 is 2).
diff --git a/asteroid/test-suites/regression-tests/programs/test108.ast b/asteroid/test-suites/regression-tests/test108.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test108.ast
rename to asteroid/test-suites/regression-tests/test108.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test109.ast b/asteroid/test-suites/regression-tests/test109.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test109.ast
rename to asteroid/test-suites/regression-tests/test109.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test110.ast b/asteroid/test-suites/regression-tests/test110.ast
similarity index 88%
rename from asteroid/test-suites/regression-tests/programs/test110.ast
rename to asteroid/test-suites/regression-tests/test110.ast
index 0992badf..94049023 100644
--- a/asteroid/test-suites/regression-tests/programs/test110.ast
+++ b/asteroid/test-suites/regression-tests/test110.ast
@@ -1,4 +1,4 @@
-load "io".
+load system io.
 
 structure A with
 	data x.
diff --git a/asteroid/test-suites/regression-tests/programs/test111.ast b/asteroid/test-suites/regression-tests/test111.ast
similarity index 64%
rename from asteroid/test-suites/regression-tests/programs/test111.ast
rename to asteroid/test-suites/regression-tests/test111.ast
index 6e8f2570..5f1fd2f4 100644
--- a/asteroid/test-suites/regression-tests/programs/test111.ast
+++ b/asteroid/test-suites/regression-tests/test111.ast
@@ -1,4 +1,4 @@
-load "io".
+load system io.
 
 let entries = [(1,2), (3,4),(5,6)].
 
@@ -7,4 +7,4 @@ function foo
 		return (y,x).
 		end
 
-println(entries @map(foo)). 
\ No newline at end of file
+io @println(entries @map(foo)). 
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/programs/test112.ast b/asteroid/test-suites/regression-tests/test112.ast
similarity index 57%
rename from asteroid/test-suites/regression-tests/programs/test112.ast
rename to asteroid/test-suites/regression-tests/test112.ast
index de024b4d..813d910f 100644
--- a/asteroid/test-suites/regression-tests/programs/test112.ast
+++ b/asteroid/test-suites/regression-tests/test112.ast
@@ -1,7 +1,7 @@
-load "io".
+load system io.
 
 let array = [1,2,3].
 
 array @extend((4,5,6)). 
-println(array).
+io @println(array).
 
diff --git a/asteroid/test-suites/regression-tests/test113.ast b/asteroid/test-suites/regression-tests/test113.ast
new file mode 100644
index 00000000..a362dd8f
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test113.ast
@@ -0,0 +1,14 @@
+-- Bitwise operations regression test
+load system bitwise.
+
+assert(bitwise @band(2,4) == 0).
+assert(bitwise @bor(2,4)  == 6).
+assert(bitwise @bnot(2)   == -3).
+assert(bitwise @bxor(15,3) == 12).
+assert(bitwise @brshift(32,2) == 8).
+assert(bitwise @blshift(2,4)   == 32).
+assert(bitwise @blrotate(242, 1) == 229).
+assert(bitwise @brrotate(242, 1) == 121).
+assert(bitwise @bsetbit(10,2) == 14).
+assert(bitwise @bclearbit(5,1) == 4).
+assert(bitwise @bsize(8) == 4).
diff --git a/asteroid/test-suites/regression-tests/programs/test114.ast b/asteroid/test-suites/regression-tests/test114.ast
similarity index 65%
rename from asteroid/test-suites/regression-tests/programs/test114.ast
rename to asteroid/test-suites/regression-tests/test114.ast
index 9787acac..d11d40f9 100644
--- a/asteroid/test-suites/regression-tests/programs/test114.ast
+++ b/asteroid/test-suites/regression-tests/test114.ast
@@ -4,18 +4,21 @@ load system io.
 load system type.
 load system math.
 
+let tostring = type @tostring.
+let stringformat = type @stringformat.
+
 let b = tostring(true,stringformat(10)).
-println b.
+io @println b.
 assert(b is "      true").
 
 let i = tostring(5,stringformat(5)).
-println i.
+io @println i.
 assert(i is "    5").
 
 let s = tostring("hello there!",stringformat(30)).
-println s.
+io @println s.
 assert(s is "                  hello there!").
 
-let r = tostring(pi,stringformat(6,3)).
-println r.
+let r = tostring(math @pi,stringformat(6,3)).
+io @println r.
 assert(r is " 3.142").
diff --git a/asteroid/test-suites/regression-tests/programs/test115.ast b/asteroid/test-suites/regression-tests/test115.ast
similarity index 80%
rename from asteroid/test-suites/regression-tests/programs/test115.ast
rename to asteroid/test-suites/regression-tests/test115.ast
index 5e5ee80e..4a1dede9 100644
--- a/asteroid/test-suites/regression-tests/programs/test115.ast
+++ b/asteroid/test-suites/regression-tests/test115.ast
@@ -3,13 +3,15 @@
 load system io.
 load system type.
 
+let tostring = type @tostring.
+
 structure Foo with
    data one.
    data two.
    data three.
    function hello
       with none do
-        println (tostring(this @one)+
+        io @println (tostring(this @one)+
                  tostring(this @two)+
                  tostring(this @three)).
       end
@@ -17,15 +19,15 @@ structure Foo with
 
 let ll = len [1,2,3].
 assert (ll == 3).
-println ll.
+io @println ll.
 
 let lt = len (1,2,3).
 assert (lt == 3).
-println lt.
+io @println lt.
 
 let ls = len "123".
 assert (ls == 3).
-println ls.
+io @println ls.
 
 let f = Foo(1,2,3).
 f @hello().
diff --git a/asteroid/test-suites/regression-tests/test116-io.txt b/asteroid/test-suites/regression-tests/test116-io.txt
new file mode 100644
index 00000000..2727e25d
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test116-io.txt
@@ -0,0 +1,3 @@
+Leo
+Blue
+
diff --git a/asteroid/test-suites/regression-tests/test116.ast b/asteroid/test-suites/regression-tests/test116.ast
new file mode 100644
index 00000000..ec4cd35c
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test116.ast
@@ -0,0 +1,65 @@
+-- Tests for file i/o
+
+load system io.
+
+let filename = escape
+"
+global __retval__
+
+import tempfile
+
+new_file, filename = tempfile.mkstemp()
+
+__retval__ = ('string', filename)
+".
+
+-- Open up the temporary file for appending
+let file = io @open(filename, "a").
+
+-- Write some content and close the file
+io @writeln(file, "Asteroid!").
+io @write(file, "Asteroid!!").
+io @write(file, "Asteroid!!!").
+io @close(file).
+
+----------------------------------------------------
+
+-- Open the file for reading
+let file = io @open(filename, "r").
+
+-- Seek to the next line
+io @readln(file).
+
+-- Assert that the remaining content is the last two lines
+assert (io @read(file) == "Asteroid!!Asteroid!!!").
+
+-- Close the file
+io @close(file).
+
+----------------------------------------------------
+
+-- Check that print(X) is write(__STDOUT__, X)
+io @print("Hello,").
+io @write(io @__STDOUT__, " world!" + "\n").
+
+-- Check that io @println(X) is writeln(__STDOUT__, X)
+io @println("First-class patterns").
+io @writeln(io @__STDOUT__, "are pretty cool!").
+
+-- Check that input() is the same as read(__STDIN__).
+io @println("Please enter your name: ").
+let name = io @readln(io @__STDIN__).
+io @println("Hello, " + name).
+
+-- Write to STDERR
+io @writeln(io @__STDERR__, "Oh no, you've encountered an error!").
+io @writeln(io @__STDERR__, "^ This is just a test. You're doing fine").
+
+
+----------------------------------------------------
+
+-- Test implicit write and read
+io @writeln("What's your favorite color?").
+let x = io @readln().
+io @write("Wow! I like ").
+io @writeln(x + " too!").
diff --git a/asteroid/test-suites/regression-tests/programs/test117.ast b/asteroid/test-suites/regression-tests/test117.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test117.ast
rename to asteroid/test-suites/regression-tests/test117.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test118.ast b/asteroid/test-suites/regression-tests/test118.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test118.ast
rename to asteroid/test-suites/regression-tests/test118.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test119.ast b/asteroid/test-suites/regression-tests/test119.ast
similarity index 83%
rename from asteroid/test-suites/regression-tests/programs/test119.ast
rename to asteroid/test-suites/regression-tests/test119.ast
index 14489b7b..f46c953c 100644
--- a/asteroid/test-suites/regression-tests/programs/test119.ast
+++ b/asteroid/test-suites/regression-tests/test119.ast
@@ -12,9 +12,9 @@ let THREE_POINTS = pattern with ( *POINT_ONE , *POINT_TWO , *POINT_THREE ).
 
 function foo
     with x:%pattern do
-        println("is a pattern").
-    with _ do
-        println("not a pattern").
+        io @println("is a pattern").
+    with x if not(x is %pattern) do
+        io @println("not a pattern").
         end
 
 -- Should match as a pattern
@@ -23,4 +23,4 @@ foo(THREE_POINTS).
 -- Should not match as a pattern
 foo("Asteroid").
 foo(123).
-foo((1,2,3)).
\ No newline at end of file
+foo((1,2,3)).
diff --git a/asteroid/test-suites/regression-tests/programs/test120.ast b/asteroid/test-suites/regression-tests/test120.ast
similarity index 92%
rename from asteroid/test-suites/regression-tests/programs/test120.ast
rename to asteroid/test-suites/regression-tests/test120.ast
index a769a851..2deee960 100644
--- a/asteroid/test-suites/regression-tests/programs/test120.ast
+++ b/asteroid/test-suites/regression-tests/test120.ast
@@ -1,4 +1,4 @@
-load "io".
+load system io.
 
 let x = +2.
 assert(x == 2).
diff --git a/asteroid/test-suites/regression-tests/programs/test121.ast b/asteroid/test-suites/regression-tests/test121.ast
similarity index 69%
rename from asteroid/test-suites/regression-tests/programs/test121.ast
rename to asteroid/test-suites/regression-tests/test121.ast
index 0d258c51..5a4d2a7f 100644
--- a/asteroid/test-suites/regression-tests/programs/test121.ast
+++ b/asteroid/test-suites/regression-tests/test121.ast
@@ -4,10 +4,10 @@ let p = (pattern with (x, y)).
 
 function foo
 	with *p do
-		println("matched").
+		io @println("matched").
 		assert(true).
 	with _ do
-		println("did not match").
+		io @println("did not match").
 		assert(false).
 end
 
diff --git a/asteroid/test-suites/regression-tests/programs/test122.ast b/asteroid/test-suites/regression-tests/test122.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test122.ast
rename to asteroid/test-suites/regression-tests/test122.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test123.ast b/asteroid/test-suites/regression-tests/test123.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test123.ast
rename to asteroid/test-suites/regression-tests/test123.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test124.ast b/asteroid/test-suites/regression-tests/test124.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test124.ast
rename to asteroid/test-suites/regression-tests/test124.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test125.ast b/asteroid/test-suites/regression-tests/test125.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test125.ast
rename to asteroid/test-suites/regression-tests/test125.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test126.ast b/asteroid/test-suites/regression-tests/test126.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test126.ast
rename to asteroid/test-suites/regression-tests/test126.ast
diff --git a/asteroid/test-suites/regression-tests/programs/test127.ast b/asteroid/test-suites/regression-tests/test127.ast
similarity index 100%
rename from asteroid/test-suites/regression-tests/programs/test127.ast
rename to asteroid/test-suites/regression-tests/test127.ast
diff --git a/asteroid/test-suites/regression-tests/test128.ast b/asteroid/test-suites/regression-tests/test128.ast
new file mode 100644
index 00000000..5d528e0b
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test128.ast
@@ -0,0 +1,9 @@
+-- testing function calls within patterns
+
+function goo with none do
+  return pattern x.
+end
+
+let *goo() = 4.
+assert (x==4).
+
diff --git a/asteroid/test-suites/regression-tests/test129.ast b/asteroid/test-suites/regression-tests/test129.ast
new file mode 100644
index 00000000..4baa699a
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test129.ast
@@ -0,0 +1,23 @@
+load system io.
+
+let E = 10.3e-12.
+let e = -3E+1.
+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)).
+io @println(s).
+assert(s == "-6.9900000000e+01").
+
+let s = type @tostring(n,type @stringformat(10,10,false)).
+io @println(s).
+assert(s == "-69.9000000000").
+
+let y = 1.
+io @println(type @gettype(y)).
+assert(type @gettype(y) == "integer").
+
+let z = 1.0.
+io @println(type @gettype(z)).
+assert(type @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
new file mode 100644
index 00000000..7ace9a41
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test130.ast
@@ -0,0 +1,8 @@
+-- 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
new file mode 100644
index 00000000..1eec448e
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test131.ast
@@ -0,0 +1,4 @@
+-- patterns can always match themselves.
+let z = pattern (p,q).
+assert(z is %[*z]%).
+
diff --git a/asteroid/test-suites/regression-tests/test132.ast b/asteroid/test-suites/regression-tests/test132.ast
new file mode 100644
index 00000000..ee49eedf
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test132.ast
@@ -0,0 +1,17 @@
+structure A with
+  data a.
+  data b.
+end
+
+let zp = pattern A(p,q). -- pattern constructed purely structural
+let zo = A(pattern p, pattern q). -- pattern constructed as an object
+
+-- both patterns can match objects
+assert(A(1,2) is %[*zp]%).
+assert(A(1,2) is %[*zo]%).
+
+-- two patterns are equivalent if they can match each other, 
+-- but these patterns are not equivalent: they cannot match each other
+assert(zo is %[*zp]%).
+assert(not(zp is %[*zo]%)).
+
diff --git a/asteroid/test-suites/regression-tests/test133.ast b/asteroid/test-suites/regression-tests/test133.ast
new file mode 100644
index 00000000..643acb69
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test133.ast
@@ -0,0 +1,13 @@
+-- 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/test134.ast b/asteroid/test-suites/regression-tests/test134.ast
new file mode 100644
index 00000000..e9706849
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test134.ast
@@ -0,0 +1,102 @@
+load system io.
+
+function foo
+    with %pattern do
+        io @println("is a pattern").
+    with _ do
+        io @println("not a pattern").
+    end
+
+foo (pattern x).
+foo (lambda with x do return x).
+
+function foo
+    with %pattern do
+        io @println("is a pattern").
+    with %function do
+        io @println("not a pattern").
+    end
+
+foo (pattern x).
+foo (lambda with x do return x).
+
+
+function foo
+    with %function do
+        io @println("not a pattern").
+    with %pattern do
+        io @println("is a pattern").
+    end
+
+foo (pattern x).
+foo (lambda with x do return x).
+
+function foo
+    with %pattern do
+        io @println("not a pattern").
+    with %pattern do
+        io @println("is a pattern").
+    end
+
+try
+    foo (pattern x).
+    throw Error("Redundanct pattern not detected!").
+catch e do
+    io @println("Success!").
+end
+
+let x:%pattern = 1.
+
+
+function foo
+    with %pattern do
+        io @println("not a pattern").
+    with %integer do
+        io @println("is a pattern").
+    end
+
+try
+    foo (pattern x).
+    foo (1).
+catch e do
+    io @println("Success!").
+end
+
+function foo
+    with %pattern do
+        io @println("not a pattern").
+    with %real do
+        io @println("is a pattern").
+    end
+
+try
+    foo (pattern x).
+    foo (1.1).
+catch e do
+    io @println("Success!").
+end
+
+function foo
+    with %integer do
+        io @println("not a pattern").
+    with %pattern do
+        io @println("is a pattern").
+    end
+
+
+foo (pattern x).
+foo (1).
+
+function foo
+    with %pattern do
+        io @println("not a pattern").
+    with %string do
+        io @println("is a pattern").
+    end
+
+try
+    foo (pattern x).
+    foo ("hello").
+catch e do
+    io @println("Success!").
+end
\ No newline at end of file
diff --git a/asteroid/test-suites/regression-tests/test135.ast b/asteroid/test-suites/regression-tests/test135.ast
new file mode 100644
index 00000000..05b0c027
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test135.ast
@@ -0,0 +1,13 @@
+-- pattern matching does not work with undeclared types
+
+structure A with
+  data a.
+  data b.
+end
+
+try
+   let B(x,y) = A(1,2).
+catch Exception(t,m) do
+   assert(m is "'B' is not defined").
+end
+
diff --git a/asteroid/test-suites/regression-tests/test136.ast b/asteroid/test-suites/regression-tests/test136.ast
new file mode 100644
index 00000000..05212d1f
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test136.ast
@@ -0,0 +1,3 @@
+-- test expressions computing return values
+let x = (lambda with i do i+1) 1.
+assert(x is 2).
diff --git a/asteroid/test-suites/regression-tests/test137.ast b/asteroid/test-suites/regression-tests/test137.ast
new file mode 100644
index 00000000..58258031
--- /dev/null
+++ b/asteroid/test-suites/regression-tests/test137.ast
@@ -0,0 +1,18 @@
+-- test expressions computing return values
+
+load system io.
+
+function f1 with () do
+   3+3.
+   io @println "hello".
+   5.
+end
+
+function f2 with () do
+   3+3.
+   io @println "hello".
+end
+
+assert(f1() is 5).
+assert(f2() is none).
+
diff --git a/asteroid/test-suites/run-tests.py b/asteroid/test-suites/run-tests.py
new file mode 100755
index 00000000..b17eb248
--- /dev/null
+++ b/asteroid/test-suites/run-tests.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+# coding: utf-8
+################################
+# general testsuite driver
+################################
+
+# the following is a list of directories of test cases the script will run
+
+dirs = [
+	'action-tests',
+        'first-class-redundant-pattern-tests',
+        'redundant-pattern-test',
+        'ref-programs',
+        'regression-tests',
+        'ug-programs',
+       ]
+
+# set the following to True if you encounter failed test cases. It will
+# give you details and a stack dump.
+verbose_failure = False
+
+# control whether to do redundancy checks
+redundancy = True
+
+# if your test case needs input from stdin please provide
+# a file named,
+#
+#    <testname>-io.txt
+#
+# For example, if your test case file is test-024.ast and it
+# requires input on stdin then provide a file test-024-io.txt
+# with one line of input for each require input.
+
+# TODO: capture stdout and compare it to a given
+# output file.
+
+import sys
+import os
+
+# Get the path of this file and temporarily change
+# the working directory to that path
+file_path = os.path.dirname(os.path.abspath( __file__ ))
+os.chdir(file_path)
+
+from asteroid.interp import interp
+
+for d in dirs:
+    tests = os.listdir(d)
+    tests.sort()
+
+    for testname in tests:
+        # check that we are actually looking at test case
+        if testname[-3:] == "ast":
+            # if a <testname>-io.txt file exists map stdin to it
+            stdin_file = file_path+'/'+d+'/'+testname[0:-4]+"-io.txt"
+            if os.path.exists(stdin_file):
+                sys.stdin = open(stdin_file, "r")
+            f = open(d+"/"+testname,"r")
+            p = f.read()
+            print("**********"+d+"/"+testname+"************")
+            print(p)
+            print("**********output***********")
+            interp(p,exceptions=verbose_failure,redundancy=redundancy)
+            f.close()
diff --git a/asteroid/test-suites/ug-programs/prgm-001.ast b/asteroid/test-suites/ug-programs/prgm-001.ast
new file mode 100644
index 00000000..4ed66bac
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-001.ast
@@ -0,0 +1,1 @@
+    let [x,2,y] = [1,2,3].
diff --git a/asteroid/test-suites/ug-programs/prgm-002.ast b/asteroid/test-suites/ug-programs/prgm-002.ast
new file mode 100644
index 00000000..7a3b91e6
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-002.ast
@@ -0,0 +1,1 @@
+    let [1,2,3] = [1,2,3].
diff --git a/asteroid/test-suites/ug-programs/prgm-003.ast b/asteroid/test-suites/ug-programs/prgm-003.ast
new file mode 100644
index 00000000..f3779ce0
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-003.ast
@@ -0,0 +1,13 @@
+    -- define first-class patterns
+    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
+            return n * fact (n-1).
+        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
new file mode 100644
index 00000000..3e655040
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-004.ast
@@ -0,0 +1,1 @@
+    let x:%string = "value: " + 1.
diff --git a/asteroid/test-suites/ug-programs/prgm-005.ast b/asteroid/test-suites/ug-programs/prgm-005.ast
new file mode 100644
index 00000000..4f263f47
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-005.ast
@@ -0,0 +1,2 @@
+    let l = [1,2,3].  -- this is a list
+    let t = (1,2,3).  -- this is a tuple
diff --git a/asteroid/test-suites/ug-programs/prgm-006.ast b/asteroid/test-suites/ug-programs/prgm-006.ast
new file mode 100644
index 00000000..78cd2903
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-006.ast
@@ -0,0 +1,1 @@
+    let one_tuple = (1,).  -- this is a 1-tuple
diff --git a/asteroid/test-suites/ug-programs/prgm-007.ast b/asteroid/test-suites/ug-programs/prgm-007.ast
new file mode 100644
index 00000000..befc0059
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-007.ast
@@ -0,0 +1,2 @@
+    load system io.
+    io @println ("this is my list: " + [1,2,3]).
diff --git a/asteroid/test-suites/ug-programs/prgm-008.ast b/asteroid/test-suites/ug-programs/prgm-008.ast
new file mode 100644
index 00000000..254f816d
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-008.ast
@@ -0,0 +1,2 @@
+    let none = ().
+    let () = none.
diff --git a/asteroid/test-suites/ug-programs/prgm-009.ast b/asteroid/test-suites/ug-programs/prgm-009.ast
new file mode 100644
index 00000000..48962bf3
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-009.ast
@@ -0,0 +1,5 @@
+    load system io.    -- load the io module so we can print
+
+    let a = [1,2,3].             -- construct list a
+    let b = [a @2, a @1, a @0].  -- reverse list a
+    io @println b.
diff --git a/asteroid/test-suites/ug-programs/prgm-009a.ast b/asteroid/test-suites/ug-programs/prgm-009a.ast
new file mode 100644
index 00000000..126df5f9
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-009a.ast
@@ -0,0 +1,5 @@
+    load system io.    -- load the io module so we can print
+
+    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.
diff --git a/asteroid/test-suites/ug-programs/prgm-010.ast b/asteroid/test-suites/ug-programs/prgm-010.ast
new file mode 100644
index 00000000..4fa9e71b
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-010.ast
@@ -0,0 +1,5 @@
+    load system io.
+
+    let a = [1,2,3].
+    let b = a @reverse(). -- reverse list using member function 'reverse'
+    io @println b.
diff --git a/asteroid/test-suites/ug-programs/prgm-011.ast b/asteroid/test-suites/ug-programs/prgm-011.ast
new file mode 100644
index 00000000..ecf613d5
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-011.ast
@@ -0,0 +1,10 @@
+    load system io.
+
+    -- build a list of odd values
+    let a = [1 to 10 stride 2].  -- list comprehension
+    io @println ("list: " + a).
+
+    -- reverse the list using a slice computed as comprehension
+    let slice = [4 to 0 stride 1]. -- list comprehension
+    let b = a @slice.
+    io @println ("reversed list: " + b).
diff --git a/asteroid/test-suites/ug-programs/prgm-012.ast b/asteroid/test-suites/ug-programs/prgm-012.ast
new file mode 100644
index 00000000..bd980355
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-012.ast
@@ -0,0 +1,7 @@
+    load system io.
+    load system math.
+
+    let a = [1 to 10] @map(lambda with x do return math @mod(x,2))
+                      @map(lambda with x do return 1 if x else -1).
+
+    io @println a.
diff --git a/asteroid/test-suites/ug-programs/prgm-013.ast b/asteroid/test-suites/ug-programs/prgm-013.ast
new file mode 100644
index 00000000..335fe853
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-013.ast
@@ -0,0 +1,10 @@
+    load system io.
+
+    -- build a 2-D array
+    let b = [[1,2,3],
+             [4,5,6],
+             [7,8,9]].
+
+    -- modify an element in the array
+    let b @1 @1 = 0.
+    io @println ("["+b@0+"\n "+b@1+"\n "+b@2+"]").
diff --git a/asteroid/test-suites/ug-programs/prgm-014.ast b/asteroid/test-suites/ug-programs/prgm-014.ast
new file mode 100644
index 00000000..06b1d6a9
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-014.ast
@@ -0,0 +1,3 @@
+    let a = (1,2,3).    -- construct tuple a
+    let b = a @1.       -- access the second element in tuple a
+    assert(b == 2).     -- assert that the value of the second element is correct
diff --git a/asteroid/test-suites/ug-programs/prgm-015.ast b/asteroid/test-suites/ug-programs/prgm-015.ast
new file mode 100644
index 00000000..f46f73c1
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-015.ast
@@ -0,0 +1,6 @@
+    -- build a list of tuples
+    let b = [("a","b","c"),
+             ("d","e","f"),
+             ("g","h","i")].
+    -- Access an element in the nested structure.
+    assert(b @1 @1 == "e").
diff --git a/asteroid/test-suites/ug-programs/prgm-016.ast b/asteroid/test-suites/ug-programs/prgm-016.ast
new file mode 100644
index 00000000..0a6f25b9
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-016.ast
@@ -0,0 +1,9 @@
+    load system io.
+
+    let b = ("a","b","c"). -- build a tuple
+    
+    try
+        let b @1 = "z". -- attempt to modify an element in the tuple
+    catch Exception(kind,message) do
+        io @println (kind+": "+message).
+    end.
diff --git a/asteroid/test-suites/ug-programs/prgm-017.ast b/asteroid/test-suites/ug-programs/prgm-017.ast
new file mode 100644
index 00000000..02d72732
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-017.ast
@@ -0,0 +1,22 @@
+    load system io.
+
+    structure Person with
+        data name.
+        data age.
+        data gender.
+    end
+
+    -- make a list of persons
+    let people = [
+        -- use default constructors to construct Person instances
+        Person("George", 32, "man"),
+        Person("Sophie", 46, "woman"),
+        Person("Oliver", 21, "man")
+    ].
+
+    -- retrieve the second person on the list and use pattern
+    -- matching to extract member values
+    let Person(name,age,gender) = people @1.
+
+    -- print out the member values
+    io @println (name + " is " + age + " years old and is a " +  gender + ".").
diff --git a/asteroid/test-suites/ug-programs/prgm-017a.ast b/asteroid/test-suites/ug-programs/prgm-017a.ast
new file mode 100644
index 00000000..074d6751
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-017a.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 constructor
+    assert( obj @a == 1 ).  -- access first data member
+    assert( obj @b == 2 ).  -- access second data member
diff --git a/asteroid/test-suites/ug-programs/prgm-018.ast b/asteroid/test-suites/ug-programs/prgm-018.ast
new file mode 100644
index 00000000..ee65c533
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-018.ast
@@ -0,0 +1,4 @@
+    load system io.
+
+    let [x,2,y] = [1+0,1+1,1+2].
+    io @println (x,y).
diff --git a/asteroid/test-suites/ug-programs/prgm-019.ast b/asteroid/test-suites/ug-programs/prgm-019.ast
new file mode 100644
index 00000000..4d75b1c2
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-019.ast
@@ -0,0 +1,1 @@
+    let %integer = 1.
diff --git a/asteroid/test-suites/ug-programs/prgm-020.ast b/asteroid/test-suites/ug-programs/prgm-020.ast
new file mode 100644
index 00000000..8b0bba4b
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-020.ast
@@ -0,0 +1,4 @@
+    load system io.
+
+    let t:(1,2) = (1,2).  -- using a named pattern on lhs
+    io @println t.
diff --git a/asteroid/test-suites/ug-programs/prgm-021.ast b/asteroid/test-suites/ug-programs/prgm-021.ast
new file mode 100644
index 00000000..6410a980
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-021.ast
@@ -0,0 +1,6 @@
+    load system io.
+    load system math.
+    load system type.
+
+    let x:%real = math @pi.
+    io @println (type @tostring (x,type @stringformat (4,2))).
diff --git a/asteroid/test-suites/ug-programs/prgm-022.ast b/asteroid/test-suites/ug-programs/prgm-022.ast
new file mode 100644
index 00000000..b85264fb
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-022.ast
@@ -0,0 +1,5 @@
+    load system io.
+
+    for i in 0 to 10 stride 2 do
+        io @println i.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-023.ast b/asteroid/test-suites/ug-programs/prgm-023.ast
new file mode 100644
index 00000000..dbccbe5f
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-023.ast
@@ -0,0 +1,6 @@
+    load system io.
+    load system util
+
+    for (ix,bird) in util @zip (["first","second","third"],["turkey","duck","chicken"]) do
+        io @println ("the "+ix+" bird is a "+bird).
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-024-io.txt b/asteroid/test-suites/ug-programs/prgm-024-io.txt
new file mode 100644
index 00000000..8148ef7a
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-024-io.txt
@@ -0,0 +1,2 @@
+3
+
diff --git a/asteroid/test-suites/ug-programs/prgm-024.ast b/asteroid/test-suites/ug-programs/prgm-024.ast
new file mode 100644
index 00000000..bb610428
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-024.ast
@@ -0,0 +1,15 @@
+    load system io.
+    load system type.
+
+    let x = type @tointeger (io @input "Please enter an integer: ").
+
+    if x < 0 do
+        let x = 0.
+        io @println "Negative, changed to zero".
+    elif x == 0 do
+        io @println "Zero".
+    elif x == 1 do
+        io @println "One".
+    else do
+        io @println "Something else".
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-025a.ast b/asteroid/test-suites/ug-programs/prgm-025a.ast
new file mode 100644
index 00000000..696076da
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-025a.ast
@@ -0,0 +1,7 @@
+    function double
+        with i do -- pattern match the actual arg with i
+            return 2*i.
+        end
+
+    let d = double 2.  -- function call via juxtaposition
+    assert( d == 4 ).
diff --git a/asteroid/test-suites/ug-programs/prgm-025b.ast b/asteroid/test-suites/ug-programs/prgm-025b.ast
new file mode 100644
index 00000000..91649958
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-025b.ast
@@ -0,0 +1,7 @@
+    function reduce
+        with (a,b) do -- pattern match the actual argument
+            return a*b.
+        end
+
+    let r = reduce (2,4).  -- function call via juxtaposition
+    assert( r == 8 ).
diff --git a/asteroid/test-suites/ug-programs/prgm-026.ast b/asteroid/test-suites/ug-programs/prgm-026.ast
new file mode 100644
index 00000000..1f1315a7
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-026.ast
@@ -0,0 +1,24 @@
+    load system io.
+
+    function qsort
+        with [] do -- empty list pattern
+            return [].
+        with [a] do -- single element list pattern
+            return [a].
+        with [pivot|rest] do -- separating the list into pivot and rest of list
+            let less=[].
+            let more=[].
+
+            for e in rest do
+                if e < pivot do
+                    let less = less + [e].
+                else
+                    let more = more + [e].
+                end
+            end
+
+            return qsort less + [pivot] + qsort more.
+        end
+
+    -- print the sorted list
+    io @println (qsort [3,2,1,0])
diff --git a/asteroid/test-suites/ug-programs/prgm-027.ast b/asteroid/test-suites/ug-programs/prgm-027.ast
new file mode 100644
index 00000000..57b2775f
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-027.ast
@@ -0,0 +1,3 @@
+    load system io.
+
+    io @println ((lambda with n do return n+1) 1).
diff --git a/asteroid/test-suites/ug-programs/prgm-028.ast b/asteroid/test-suites/ug-programs/prgm-028.ast
new file mode 100644
index 00000000..3660b923
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-028.ast
@@ -0,0 +1,11 @@
+    load system io.
+
+    let p = (1,2).
+
+    if p is (x,y,z) do
+        io @println ("it's a triple with: "+x+","+y+","+z)
+    elif p is (x,y) do
+        io @println ("it's a pair with: "+x+","+y).
+    else do
+        io @println "it's something else".
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-029.ast b/asteroid/test-suites/ug-programs/prgm-029.ast
new file mode 100644
index 00000000..3fc08045
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-029.ast
@@ -0,0 +1,9 @@
+    load system io.
+
+    let list = [1,2,3].
+
+    repeat do
+        let [head|tail] = list. -- pattern match with head/tail operator
+        io @println head.
+        let list = tail.
+    until list is []. -- pattern match with is predicate
diff --git a/asteroid/test-suites/ug-programs/prgm-030.ast b/asteroid/test-suites/ug-programs/prgm-030.ast
new file mode 100644
index 00000000..e7a5681d
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-030.ast
@@ -0,0 +1,23 @@
+    -- implements Peano addition on terms
+    load system io.
+
+    structure s with
+        data val.
+        end
+
+    structure add with
+        data left.
+        data right.
+        end
+
+    function reduce
+        with add(x,0) do
+            return reduce(x).
+        with add(x,s(y))  do
+            return s(reduce(add(x,y))).
+        with term do
+            return term.
+        end
+
+    -- add 2 3
+    io @println (reduce(add(s(s(0)),s(s(s(0)))))).
diff --git a/asteroid/test-suites/ug-programs/prgm-031.ast b/asteroid/test-suites/ug-programs/prgm-031.ast
new file mode 100644
index 00000000..287e7ec8
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-031.ast
@@ -0,0 +1,12 @@
+    load system io.
+
+    function factorial
+        with 0 do
+            return 1
+        with (n:%integer) if n > 0 do
+            return n * factorial (n-1).
+        with (n:%integer) if n < 0 do
+            throw Error("factorial is not defined for "+n).
+        end
+
+    io @println ("The factorial of 3 is: " + factorial 3).
diff --git a/asteroid/test-suites/ug-programs/prgm-032.ast b/asteroid/test-suites/ug-programs/prgm-032.ast
new file mode 100644
index 00000000..333784c4
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-032.ast
@@ -0,0 +1,18 @@
+    load system io.
+
+    structure Person with
+        data name.
+        data age.
+        end
+
+    -- define a list of persons
+    let people = [
+        Person("George", 32),
+        Person("Sophie", 46),
+        Person("Oliver", 21)
+        ].
+
+    -- print names that contain 'p'
+    for Person(name:".*p.*",_) in people do
+        io @println name.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-033.ast b/asteroid/test-suites/ug-programs/prgm-033.ast
new file mode 100644
index 00000000..5ac29575
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-033.ast
@@ -0,0 +1,24 @@
+    load system io.
+    load system random.
+    load system type.
+
+    structure Head with
+        data val.
+        end
+
+    structure Tail with
+        data val.
+        end
+
+    try
+        let i = random @random().
+        if i >= 0.5 do
+            throw Head(i).
+        else do
+            throw Tail(i).
+        end
+    catch Head(v) do
+        io @println("you win with "+type @tostring(v,type @stringformat(4,2))).
+    catch Tail(v) do
+        io @println("you loose with "+type @tostring(v,type @stringformat(4,2))).
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-034.ast b/asteroid/test-suites/ug-programs/prgm-034.ast
new file mode 100644
index 00000000..f04f9415
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-034.ast
@@ -0,0 +1,11 @@
+    load system io.
+
+    structure Person with
+        data name.
+        data age.
+        data gender.
+        end
+
+    let scarlett = Person("Scarlett",28,"F").
+    -- access the name field of the structure instance
+    io @println (scarlett @name).
diff --git a/asteroid/test-suites/ug-programs/prgm-035.ast b/asteroid/test-suites/ug-programs/prgm-035.ast
new file mode 100644
index 00000000..21776cd7
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-035.ast
@@ -0,0 +1,15 @@
+    load system io.
+
+    structure Person with
+        data name.
+        data age.
+        data gender.
+        function hello
+            with none do
+                io @println ("Hello, my name is "+this @name).
+            end
+        end
+
+    let scarlett = Person("Scarlett",28,"F").
+    -- call the member function
+    scarlett @hello().
diff --git a/asteroid/test-suites/ug-programs/prgm-036.ast b/asteroid/test-suites/ug-programs/prgm-036.ast
new file mode 100644
index 00000000..8cfa4f16
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-036.ast
@@ -0,0 +1,16 @@
+    load system io.
+
+    structure Person with
+        data name.
+        -- the function is defined in the middle of the data fields
+        function hello
+            with none do
+                io @println ("Hello, my name is "+this @name).
+            end
+        data age.
+        data gender.
+        end
+
+    -- pattern matching ignores function definitions
+    let Person(name,age,_) = Person("Scarlett",28,"F").
+    io @println (name+" is "+age+" years old").
diff --git a/asteroid/test-suites/ug-programs/prgm-037.ast b/asteroid/test-suites/ug-programs/prgm-037.ast
new file mode 100644
index 00000000..2dcf0e58
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-037.ast
@@ -0,0 +1,33 @@
+    load system io.
+    load system type.
+
+    structure Dog with
+
+       data name.
+       data tricks.
+
+       function add_trick
+          with new_trick:%string do
+             this @tricks @append new_trick.
+          end
+
+       function __init__
+          with name:%string do
+             let this @name = name.
+             let this @tricks = [].
+          end
+
+    end
+
+    let fido = Dog "Fido".
+    fido @add_trick "play dead".
+    fido @add_trick "fetch".
+
+    let buddy = Dog "Buddy".
+    buddy @add_trick "sit stay".
+    buddy @add_trick "roll over".
+
+    -- print out all the dogs that know how to fetch
+    for (Dog(name,tricks) if type @tostring(tricks) is ".*fetch.*") in [fido,buddy] do
+        io @println (name+" knows how to fetch").
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-038.ast b/asteroid/test-suites/ug-programs/prgm-038.ast
new file mode 100644
index 00000000..89b17f1c
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-038.ast
@@ -0,0 +1,17 @@
+    function fact
+        with 0 do
+            return 1
+        with (n:%integer) if n > 0 do
+            return n * fact (n-1).
+        with (n:%integer) if n < 0 do
+            throw Error("fact undefined for negative values").
+        end
+
+    function sign
+        with 0 do
+            return 1
+        with (n:%integer) if n > 0 do
+            return 1.
+        with (n:%integer) if n < 0 do
+            return -1.
+        end
diff --git a/asteroid/test-suites/ug-programs/prgm-039.ast b/asteroid/test-suites/ug-programs/prgm-039.ast
new file mode 100644
index 00000000..252bfd21
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-039.ast
@@ -0,0 +1,20 @@
+    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
+            return n * fact (n-1).
+        with *NEG_INT do
+            throw Error("fact undefined for negative values").
+        end
+
+    function sign
+        with 0 do
+                return 1
+            with *POS_INT do
+                return 1.
+            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
new file mode 100644
index 00000000..f1ed709a
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-040.ast
@@ -0,0 +1,6 @@
+    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-041.ast b/asteroid/test-suites/ug-programs/prgm-041.ast
new file mode 100644
index 00000000..b5175cdc
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-041.ast
@@ -0,0 +1,6 @@
+    load system io.
+    let P = pattern ([a],[b]).
+    let v = ([1],[2]).
+    let *P = v.
+    io @println a.
+    io @println b.
diff --git a/asteroid/test-suites/ug-programs/prgm-042.ast b/asteroid/test-suites/ug-programs/prgm-042.ast
new file mode 100644
index 00000000..34161b42
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-042.ast
@@ -0,0 +1,72 @@
+    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
new file mode 100644
index 00000000..d85223e3
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-043.ast
@@ -0,0 +1,9 @@
+   load system io.
+
+   let POS_INT = pattern %[v if (v is %integer) and v > 0]%.
+
+   function add with (a:*POS_INT,b:*POS_INT) do
+      return a+b.
+   end
+
+   io @println (add(1,2)).
\ No newline at end of file
diff --git a/asteroid/test-suites/ug-programs/prgm-044.ast b/asteroid/test-suites/ug-programs/prgm-044.ast
new file mode 100644
index 00000000..dc29d9f8
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-044.ast
@@ -0,0 +1,46 @@
+    load system io.
+    load system type.
+
+    let pos_num = pattern %[x if type @isscalar(x) and x > 0]%.
+   
+    structure Asteroid with
+       data size.
+       function __init_
+          with v:*pos_num do
+             let this @size = v.
+          end
+    end
+
+    structure Spaceship with
+        data size.
+       function __init_
+          with v:*pos_num do
+             let this @size = v.
+          end
+    end
+
+    -- we use first-class pattern SpaceObject to
+    -- express that both asteroids and space ships are space objects.
+    let SpaceObject = pattern %[x if (x is %Asteroid) or (x is %Spaceship)]%.
+
+    -- multi-dispatch function
+    function collide_with
+      with (a:%Asteroid, b:%Spaceship) do
+        return "a/s".
+      with (a:%Spaceship, b:%Asteroid) do
+        return "s/a".
+      with (a:%Spaceship, b:%Spaceship) do
+        return "s/s".
+      with (a:%Asteroid, b:%Asteroid) do
+        return "a/a".
+      end
+
+    -- here we use the first-class pattern SpaceObject as a
+    -- constraint on the function parameters.
+    function collide with (x:*SpaceObject, y:*SpaceObject) do
+      return "Big boom!" if (x@size > 100 and y@size > 100) else collide_with(x, y).
+    end
+
+    io @println (collide(Asteroid(101), Spaceship(300))).
+    io @println (collide(Asteroid(10), Spaceship(10))).
+    io @println (collide(Spaceship(101), Spaceship(10))).
diff --git a/asteroid/test-suites/ug-programs/prgm-045.ast b/asteroid/test-suites/ug-programs/prgm-045.ast
new file mode 100644
index 00000000..df829c1f
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-045.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/ug-programs/prgm-046.ast b/asteroid/test-suites/ug-programs/prgm-046.ast
new file mode 100644
index 00000000..42ebcab1
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-046.ast
@@ -0,0 +1,7 @@
+    load system io.
+
+    try
+        throw Error("something worth throwing").
+    catch Error(s) do
+        io @println s.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-047.ast b/asteroid/test-suites/ug-programs/prgm-047.ast
new file mode 100644
index 00000000..99a44ef2
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-047.ast
@@ -0,0 +1,7 @@
+    load system io.
+
+    try
+        throw Exception("MyException","something worth throwing").
+    catch Exception("MyException",s) do
+        io @println s.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-048.ast b/asteroid/test-suites/ug-programs/prgm-048.ast
new file mode 100644
index 00000000..5bce1261
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-048.ast
@@ -0,0 +1,7 @@
+    load system io.
+
+    try
+        throw ("funny exception", 42).
+    catch ("funny exception", v) do
+        io @println v.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-049.ast b/asteroid/test-suites/ug-programs/prgm-049.ast
new file mode 100644
index 00000000..9ab9b24b
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-049.ast
@@ -0,0 +1,7 @@
+    load system io.
+
+    try
+        let (x,y) = (1,2,3).
+    catch _ do
+        io @println "something happened".
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-050.ast b/asteroid/test-suites/ug-programs/prgm-050.ast
new file mode 100644
index 00000000..7e2d67f1
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-050.ast
@@ -0,0 +1,8 @@
+    load system io.
+    load system type.
+
+    try
+        let (x,y) = (1,2,3).
+    catch e do
+        io @println ("something happened: "+type @tostring(e)).
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-051.ast b/asteroid/test-suites/ug-programs/prgm-051.ast
new file mode 100644
index 00000000..9b8599c0
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-051.ast
@@ -0,0 +1,5 @@
+    load system io.
+
+    let a = 1.
+    let b = 2.
+    io @println ("a + b = " + (a + b)).
diff --git a/asteroid/test-suites/ug-programs/prgm-052.ast b/asteroid/test-suites/ug-programs/prgm-052.ast
new file mode 100644
index 00000000..98c5d197
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-052.ast
@@ -0,0 +1,20 @@
+    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.
diff --git a/asteroid/test-suites/ug-programs/prgm-053-io.txt b/asteroid/test-suites/ug-programs/prgm-053-io.txt
new file mode 100644
index 00000000..599f87bf
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-053-io.txt
@@ -0,0 +1,2 @@
+Leo
+
diff --git a/asteroid/test-suites/ug-programs/prgm-053.ast b/asteroid/test-suites/ug-programs/prgm-053.ast
new file mode 100644
index 00000000..61ad02dd
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-053.ast
@@ -0,0 +1,4 @@
+    load system io.
+
+    let name = io @input("What is your name? ").
+    io @println ("Hello " + name + "!").
diff --git a/asteroid/test-suites/ug-programs/prgm-054-io.txt b/asteroid/test-suites/ug-programs/prgm-054-io.txt
new file mode 100644
index 00000000..8148ef7a
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-054-io.txt
@@ -0,0 +1,2 @@
+3
+
diff --git a/asteroid/test-suites/ug-programs/prgm-054.ast b/asteroid/test-suites/ug-programs/prgm-054.ast
new file mode 100644
index 00000000..bac775a6
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-054.ast
@@ -0,0 +1,8 @@
+    load system io.
+    load system type.
+
+    let i if i > 0  = type @tointeger(io @input("Please enter a positive integer value: ")).
+
+    for k in 1 to i do
+        io @println k.
+    end
diff --git a/asteroid/test-suites/ug-programs/prgm-055.ast b/asteroid/test-suites/ug-programs/prgm-055.ast
new file mode 100644
index 00000000..ff4e64c2
--- /dev/null
+++ b/asteroid/test-suites/ug-programs/prgm-055.ast
@@ -0,0 +1,5 @@
+    load system io.
+    load system math.
+
+    let x = math @sin( math @pi / 2 ).
+    io @println("The sine of pi / 2 is " + x + ".").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test001.ast b/asteroid/test-suites/using-asteroid-tests/programs/test001.ast
deleted file mode 100644
index 1a9aaff7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test001.ast
+++ /dev/null
@@ -1,3 +0,0 @@
-
-load "io".
-println "Hello, World!".
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test002.ast b/asteroid/test-suites/using-asteroid-tests/programs/test002.ast
deleted file mode 100644
index c84838f7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test002.ast
+++ /dev/null
@@ -1,3 +0,0 @@
-
-load "io".
-__raw_print__ "Hello, World!".
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test003.ast b/asteroid/test-suites/using-asteroid-tests/programs/test003.ast
deleted file mode 100644
index c29f35a8..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test003.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-print ("Enter your name: ").
-let name = input().
-print ("Hello, "+name+"!").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test004.ast b/asteroid/test-suites/using-asteroid-tests/programs/test004.ast
deleted file mode 100644
index 5451006f..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test004.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-let name = input("Enter your name: ").
-print ("Hello, "+name+"!").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test005.ast b/asteroid/test-suites/using-asteroid-tests/programs/test005.ast
deleted file mode 100644
index 5e082cfc..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test005.ast
+++ /dev/null
@@ -1,3 +0,0 @@
-
-load "io".
-print ("Hello, "+input("Enter your name: ")+"!").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test006.ast b/asteroid/test-suites/using-asteroid-tests/programs/test006.ast
deleted file mode 100644
index 79cc7a1d..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test006.ast
+++ /dev/null
@@ -1,4 +0,0 @@
-
-load "io".
-load "util".
-println (len("Hello!")).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test007.ast b/asteroid/test-suites/using-asteroid-tests/programs/test007.ast
deleted file mode 100644
index 2c9dad29..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test007.ast
+++ /dev/null
@@ -1,3 +0,0 @@
-
-load "io".
-println ("Hello!" @length()).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test008.ast b/asteroid/test-suites/using-asteroid-tests/programs/test008.ast
deleted file mode 100644
index c45964b2..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test008.ast
+++ /dev/null
@@ -1,16 +0,0 @@
-
-load "io".
-
-function unique with (x,y) do
-    if not (x @member(y)) do
-        return x @append(y).
-    else do
-        return x.
-    end
-end
-        
-let digits = "332211" @explode() 
-                      @sort() 
-                      @reduce(unique,[]).
-println digits.
-assert(digits == ["1","2","3"]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test009.ast b/asteroid/test-suites/using-asteroid-tests/programs/test009.ast
deleted file mode 100644
index 2806b5d2..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test009.ast
+++ /dev/null
@@ -1,7 +0,0 @@
-
-load "io".
-let str = "Hello, World!" @explode() 
-                          @reverse() 
-                          @join("").
-println str.
-assert(str == "!dlroW ,olleH").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test010.ast b/asteroid/test-suites/using-asteroid-tests/programs/test010.ast
deleted file mode 100644
index efe2cbb9..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test010.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".
-let str = "   Hello  ,   World    !   " @trim() 
-                                        @replace("  ","").
-println str.
-assert(str == "Hello, World!").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test011.ast b/asteroid/test-suites/using-asteroid-tests/programs/test011.ast
deleted file mode 100644
index c53acb32..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test011.ast
+++ /dev/null
@@ -1,22 +0,0 @@
-
-load "io".
-
-function title with w do
-    let letter_list = w @tolower() 
-                        @explode().
-    let first_letter = letter_list @0 
-                                   @toupper().
-    if letter_list @length() > 1 do
-        let title_case = ([first_letter] + letter_list @[1 to letter_list@length()-1]) @join("").
-    else
-        let title_case = first_letter.
-    end
-    return title_case.
-end
-
-let str = "once upon a time".
-let camel_str = str @split() 
-                    @map(title) 
-                    @join("").
-println camel_str.
-assert(camel_str == "OnceUponATime").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test012.ast b/asteroid/test-suites/using-asteroid-tests/programs/test012.ast
deleted file mode 100644
index 0f0f1e59..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test012.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-
-let root = "file".
-let ext = ".txt".
-
-for i in 1 to 5 do
-    println (root+i+ext).
-end
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test013.ast b/asteroid/test-suites/using-asteroid-tests/programs/test013.ast
deleted file mode 100644
index 1529b12f..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test013.ast
+++ /dev/null
@@ -1,22 +0,0 @@
-
-load "io".
-load "type".
-load "util".
-load "pick".
-
-seed(42).
-
--- make up lists of symbols useful for password construction
-let int_list = [0 to 9] @map(tostring).
-let lc_list = [97 to 122] @map(achar). -- lower case characters
-let uc_list = [65 to 90] @map(achar). --upper case characters
-let sp_list = ["!","_","#","$","%","*"].
--- build the overall pick list of symbols
-let pick_list = int_list+lc_list+uc_list+sp_list.
-
--- generate the password and print it.
-let pwd = Pick pick_list @pick(15)
-                         @join("").
-println pwd.
-
-assert (pwd == "e3zvshdbS43brt#")
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test014.ast b/asteroid/test-suites/using-asteroid-tests/programs/test014.ast
deleted file mode 100644
index 44fe67a1..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test014.ast
+++ /dev/null
@@ -1,27 +0,0 @@
-
-load "io".
-
-let dna2rna_table = 
-    [
-    ("A","U"),
-    ("C","G"),
-    ("G","C"),
-    ("T","A")
-    ].
-
-function dna2rna with x do
-    for (dna,rna) in dna2rna_table do
-        if x is *dna do
-            return rna.
-        end
-    end
-    throw Error("unknown dna char "+x).
-end
-
-let dna_seq = "ACCATCAGTC".
-let rna_seq = dna_seq @explode() 
-                      @map(dna2rna) 
-                      @join("").
-println rna_seq.
-
-assert(rna_seq == "UGGUAGUCAG").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test015.ast b/asteroid/test-suites/using-asteroid-tests/programs/test015.ast
deleted file mode 100644
index 48b36074..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test015.ast
+++ /dev/null
@@ -1,38 +0,0 @@
-
-load "io".
-load "util".
-
-let encode_table = [119 to 122] @map(achar) + [97 to 118] @map(achar).
-
-function encode with (v:%string) if len(v) == 1 do
-    -- only lowercase letters are encoded
-    if not (ascii(v) in [97 to 122]) do
-        return v.
-    else 
-        return encode_table @(ascii(v)-ascii("a")).
-    end
-end
-
-function decode with (v:%string) if len(v) == 1 do
-    -- only lowercase letters are decoded
-    if not (ascii(v) in [97 to 122]) do
-        return v.
-    else 
-        return encode_table @(ascii(v)-ascii("w")+4).
-    end
-end
-
-let message = "hello, world!"
-let secret = message @explode() 
-                     @map(encode) 
-                     @join("").
-println secret.
-
-assert (secret == "dahhk, sknhz!")
-
-let decoded_msg = secret @explode()
-                         @map(decode)
-                         @join("").
-println decoded_msg.
-
-assert (decoded_msg == "hello, world!")
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test016.ast b/asteroid/test-suites/using-asteroid-tests/programs/test016.ast
deleted file mode 100644
index e85fbeb7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test016.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".
-
-for n in 0 to 5 do
-    println (n+" file"+("s " if n>1 or n==0 else " ")+"found").
-end
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test017.ast b/asteroid/test-suites/using-asteroid-tests/programs/test017.ast
deleted file mode 100644
index 03fa6b18..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test017.ast
+++ /dev/null
@@ -1,37 +0,0 @@
-
-load "io".
-load "util".
-load "hash".
-
--- text generated at 'https://www.lipsum.com/'
-let text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed accumsan magna quis risus commodo, et pellentesque dui cursus. Sed quis risus libero. Cras et mattis libero, eget varius nisi. Phasellus ultrices, augue non dictum eleifend, nunc elit blandit velit, a viverra risus enim in tellus. Maecenas quis ante eget turpis rhoncus rhoncus eget ut mauris. Suspendisse nec erat sed nunc tempus hendrerit. Nunc dictum nunc molestie eleifend tempus. Praesent cursus lorem diam, sed mattis velit vehicula scelerisque. Nunc iaculis rhoncus ante. Etiam quam nisi, fermentum et euismod a, vulputate eu elit. Suspendisse tincidunt ligula quis interdum blandit. Quisque sed aliquam tellus. Pellentesque ac lacus pulvinar, ornare purus ac, viverra ex. Donec quis pharetra dolor.
-
-In ac massa tortor. Cras sagittis luctus scelerisque. Morbi a neque sed tortor ultrices dapibus. Mauris pretium vitae massa non auctor. Cras egestas ex ante, ac ullamcorper ante dignissim eget. Fusce bibendum justo ut enim luctus, id volutpat diam lacinia. Mauris sit amet ante risus.
-
-Nullam rhoncus ultricies dui. Etiam vel metus vehicula, pellentesque felis ut, suscipit nunc. Sed nec interdum lorem. Maecenas odio erat, vestibulum nec dapibus id, commodo vitae libero. Nulla sed urna sit amet nunc commodo finibus sed vel elit. Aliquam euismod feugiat nisi quis placerat. Aliquam libero nisl, ultrices non est at, sagittis hendrerit dui. Quisque id sem lorem. Nam ultricies metus id ultrices molestie. Pellentesque elementum consequat nibh, nec convallis lorem ullamcorper in. Etiam vitae mi tellus. Etiam accumsan massa sit amet dolor tincidunt iaculis. Nam ullamcorper blandit sem id bibendum. Quisque elementum ipsum ac sapien blandit vehicula."
-
--- get rid of punctuation, turn to lower case, and split into words.
--- Note: we could have employed richer regular expressions to clean up the text here
-let wl = text @replace("\.","")
-              @replace(",","")
-              @tolower()
-              @split().
-
--- put the words into a hash table, the value is the count of the words
-let ht = HashTable().
-for w in wl do
-    if not ht @get(w) do
-        ht @insert(w,1).
-    else do
-        ht @insert(w,ht @get(w)+1).
-    end
-end
-
--- get the contents of hash table and find the most frequent word
-let (keys,values) = unzip(ht@aslist()).
-let values_sorted = values @copy()
-                           @sort(true).
-let most_frequent_word = keys @(values @index(values_sorted @0)).
-println most_frequent_word.
-
-assert (most_frequent_word == "sed").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test018.ast b/asteroid/test-suites/using-asteroid-tests/programs/test018.ast
deleted file mode 100644
index 1a0455ee..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test018.ast
+++ /dev/null
@@ -1,23 +0,0 @@
-
-load "io".
-
-let stra = "the quick brown fox jumps over the lazy dog".
-let strb = "what does the fox say?".
-let common = "".
-
-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
-            let common = s.
-        end
-    end
-end
-
-if common do
-    println ("The longest common substring is '"+common+"'.").
-else do
-    println ("There are no common substrings.").
-end
-
-assert (common == " fox ").
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test019.ast b/asteroid/test-suites/using-asteroid-tests/programs/test019.ast
deleted file mode 100644
index 04fda0bd..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test019.ast
+++ /dev/null
@@ -1,19 +0,0 @@
-
-load "io".
-
-let str1 = "cinema".
-let str2 = "iceman".
-
-function normalize with str do
-    return str @explode()
-               @sort() 
-               @join("").
-end
-
-if normalize(str1) == normalize(str2) do
-    println "Anagrams".
-else do
-    println "Not anagrams".
-end
-
-assert (normalize(str1) == normalize(str2)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test020.ast b/asteroid/test-suites/using-asteroid-tests/programs/test020.ast
deleted file mode 100644
index d79bb2f3..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test020.ast
+++ /dev/null
@@ -1,21 +0,0 @@
-
-load "io".
-
-let str = "Was it a rat I saw?".
-
-function clean with str:%string do
-    return str @tolower()
-               @replace("[^a-z]","").
-end
-
--- only keep lower case letters
-let clean_str = clean(str).
-
--- check if it is palidromic
-if clean_str == clean_str @flip() do
-    println "Palindromic".
-else do
-    println "Not palindromic".
-end
-
-assert (clean_str == clean_str @flip()).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test021.ast b/asteroid/test-suites/using-asteroid-tests/programs/test021.ast
deleted file mode 100644
index 3b47bc5f..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test021.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
-load "io".
-
-let str = "Hello, World!".
-
-function clean with str:%string do
-    return str @tolower()
-               @replace("[^a-z]","").
-end
-
-function palindrome_test with str:%string do
-    let clean_str = clean(str).
-    if clean_str == clean_str @flip() do
-        return true.
-    else do
-        return false.
-    end
-end
-
--- create the moving window over the string
-let longest_palindrome = "".
-
-for i in 0 to str @length()-2 do
-    for j in i+1 to str @length()-1 do
-        let str1 = str @[i to j].
-        if palindrome_test(str1) and 
-           str1 @length() > longest_palindrome @length() do 
-            let longest_palindrome = str1.
-        end
-    end
-end
-
-println longest_palindrome.
-
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test022.ast b/asteroid/test-suites/using-asteroid-tests/programs/test022.ast
deleted file mode 100644
index ffce1bc8..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test022.ast
+++ /dev/null
@@ -1,47 +0,0 @@
-
-load "io".
-load "hash".
-
--- text from "www.lipsum.com"
-
-let str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed malesuada sapien nec neque suscipit, non rutrum arcu scelerisque. Nam feugiat sapien porta ipsum accumsan, eget maximus diam volutpat. Pellentesque elementum in orci quis pretium. Donec dignissim nunc lectus, id ornare urna varius ut. Praesent semper faucibus vehicula. Aliquam luctus sapien at lorem malesuada, eget suscipit felis facilisis. Suspendisse velit lectus, mollis sit amet tempor eget, faucibus ut nulla. Vestibulum et elementum dolor, a vehicula ipsum. Morbi ut fringilla nisi. Fusce congue rutrum orci nec porta. Ut laoreet justo vel turpis sodales vehicula. Nulla porttitor nisl id odio eleifend sodales.
-
-Suspendisse blandit tristique enim id laoreet. Etiam vel aliquet dui, quis tempus magna. Donec blandit volutpat felis egestas tincidunt. Integer placerat luctus mi non pharetra. Donec aliquet nisl orci, egestas elementum nunc bibendum a. Morbi nec risus aliquet, viverra nunc in, molestie odio. Curabitur pellentesque, ante eget dictum aliquam, felis leo bibendum libero, vel bibendum lorem velit eget ex. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vestibulum pretium tellus quis ante vulputate, pretium tincidunt ipsum dapibus. Praesent congue, ipsum ut sagittis tempus, lacus nisi dapibus dui, aliquam porta metus odio ut neque. Aliquam vitae faucibus dolor. Nulla iaculis lorem non mauris viverra, ut malesuada nibh aliquam. Nam bibendum sit amet massa in dignissim. Nam posuere nunc ante, at viverra diam rhoncus vel.
-
-Aliquam mollis sagittis nulla. Maecenas faucibus eu dui eget accumsan. Suspendisse sit amet fermentum sapien. Nunc vitae mi nibh. Mauris condimentum vestibulum imperdiet. Quisque at vehicula dui. Integer sit amet volutpat arcu. Maecenas efficitur leo tortor, non ullamcorper magna tempor non. Sed efficitur quis metus ut pulvinar. Proin nunc felis, congue sit amet nibh placerat, tincidunt mattis nunc. Duis efficitur lacus a orci porttitor, sed molestie risus tempor.
-
-Sed tincidunt ipsum at urna sollicitudin feugiat. Ut mollis orci quis massa dictum facilisis. Maecenas non elementum mauris. Sed rutrum orci faucibus, tristique nunc nec, mattis ante. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In hac habitasse platea dictumst. Morbi pellentesque dolor sit amet nunc tincidunt, ut rutrum ante vulputate. Nullam pretium, mi sed condimentum luctus, ipsum nunc dictum lorem, vel ultricies nibh mi ut sem. Nam volutpat id libero eget mollis.
-
-Vestibulum eget velit eros. Phasellus sit amet vestibulum odio, vel malesuada quam. Mauris dictum erat eu ligula mollis laoreet. Phasellus ut ante auctor, hendrerit ipsum et, fermentum magna. Etiam nec eros elementum, consectetur nibh ac, ullamcorper ligula. Aliquam sed porttitor sapien. Nulla tincidunt, turpis vitae venenatis aliquet, quam purus elementum diam, in tincidunt orci diam sed nulla. Cras pellentesque non diam quis sollicitudin. Duis suscipit lectus dui, eu varius metus pretium sit amet.
-
-Nulla eu ex velit. Ut non justo semper, gravida erat quis, vehicula est. Suspendisse nunc dui, iaculis id purus sit amet, rutrum commodo lacus. Aenean consequat turpis a est vestibulum, ac accumsan nibh dapibus. Nam blandit scelerisque lectus, eu pellentesque arcu ornare non. Fusce ac gravida diam. Ut in fringilla eros. Sed metus augue, porta quis vehicula at, pellentesque et mauris. Duis sodales lacus sit amet condimentum placerat. In blandit tristique nulla eget malesuada. Sed congue finibus neque at semper. Etiam pellentesque egestas urna, ut lobortis odio euismod et. Phasellus aliquet quam purus, quis ullamcorper sem mollis eu.
-
-Mauris quis ullamcorper nisi. Aenean quam nulla, sodales eu faucibus in, mattis a nulla. Nullam pulvinar pretium justo eu mattis. Aliquam rutrum ipsum vitae leo maximus ultrices. Donec ut pulvinar nisi. Sed pharetra, turpis dictum lobortis egestas, quam massa venenatis enim, dapibus efficitur dolor mauris eu felis. Donec vulputate ultrices justo sit amet condimentum. Donec id posuere nulla. In vestibulum mi in lectus commodo dignissim. Quisque vestibulum egestas arcu sit amet finibus. Proin commodo aliquet neque quis maximus.
-
-Nulla facilisi. Sed gravida aliquet diam in congue. Mauris vehicula justo ac sollicitudin laoreet. Mauris enim mi, auctor id magna eget, feugiat sollicitudin leo. Vivamus ornare ornare commodo. Suspendisse ut dui quis enim porta pretium. Praesent vitae lacus fermentum, posuere orci ac, imperdiet massa. Nulla hendrerit id nisl sed maximus. Vivamus commodo lacus eu condimentum bibendum. Suspendisse porttitor sem eget dolor aliquet congue. Pellentesque tristique augue at quam hendrerit dignissim. Aenean a congue dui. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Integer ante lacus, commodo et enim sed, auctor egestas metus.
-
-Aliquam a urna id risus tincidunt rutrum. Nunc facilisis, tortor ac suscipit aliquam, ante neque tincidunt mi, nec ullamcorper lectus ligula vel urna. Suspendisse lobortis at felis sit amet facilisis. Pellentesque velit lacus, porttitor vitae eros rutrum, convallis blandit erat. Pellentesque nec mi viverra, volutpat dui in, rutrum lacus. Ut non venenatis leo. Praesent sollicitudin magna porttitor lorem elementum molestie non a turpis. Suspendisse potenti.
-
-Donec malesuada iaculis laoreet. Nunc ut volutpat ante, ut consequat tortor. Phasellus posuere, ipsum quis dignissim iaculis, nisl felis ullamcorper ligula, quis placerat sem sapien nec ante. Cras suscipit ut magna nec lacinia. Donec ipsum nibh, imperdiet non aliquam eu, maximus id ante. Pellentesque vitae felis felis. Aliquam et diam sed nulla volutpat vestibulum molestie non lacus. Praesent porta et lacus auctor fermentum. In hac habitasse platea dictumst. Aliquam erat volutpat. Etiam at ligula orci. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos."
-
-
-let word_list = str @tolower()
-                    @replace("[^a-z0-9_]"," ")
-                    @split().
-let ht = HashTable().
-
--- create N-grams
-for i in 0 to word_list @length()-3 do
-    -- 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
-        ht @insert(n_gram,1).
-    else do
-        ht @insert(n_gram,ht @get(n_gram)+1).
-    end
-end
-
-for ((n_gram,cnt) if cnt > 1) in ht @aslist() do
-    println (n_gram+": "+cnt).
-end
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test023.ast b/asteroid/test-suites/using-asteroid-tests/programs/test023.ast
deleted file mode 100644
index 53d54329..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test023.ast
+++ /dev/null
@@ -1,5 +0,0 @@
-
-load "io".
-load "math". -- definition of pi
-
-println pi.
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test024.ast b/asteroid/test-suites/using-asteroid-tests/programs/test024.ast
deleted file mode 100644
index a84edbbf..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test024.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".
-load "math". 
-
-println e.
-println tau. -- tau=2*pi
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test025.ast b/asteroid/test-suites/using-asteroid-tests/programs/test025.ast
deleted file mode 100644
index 6c51a6e3..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test025.ast
+++ /dev/null
@@ -1,7 +0,0 @@
-
-load "io".
-
-let n = 3.
-let fact = [1 to n] @reduce(lambda with (a,b) do return a*b).
-println fact.
-assert (fact == 6).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test026.ast b/asteroid/test-suites/using-asteroid-tests/programs/test026.ast
deleted file mode 100644
index 5bb66e4d..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test026.ast
+++ /dev/null
@@ -1,17 +0,0 @@
-
-load "io".
-
-let POS_INT = pattern with (x:%integer) if x > 0.
-let NEG_INT = pattern with (x:%integer) if x < 0.
-
-function fact
-    with 0 do 
-        return 1
-    with n:*POS_INT do
-        return n * fact (n-1).
-    with n:*NEG_INT do
-        throw Error("factorial is not defined for "+n).
-    end
-
-println ("The factorial of 3 is: " + fact (3)).
-assert (fact(3) == 6).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test027.ast b/asteroid/test-suites/using-asteroid-tests/programs/test027.ast
deleted file mode 100644
index 110773f2..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test027.ast
+++ /dev/null
@@ -1,12 +0,0 @@
-
-load "io".
-
-let n = 10. -- compute the 10th Fib number
-
-let (f_1,f_2) = (1,1).
-for i in 3 to n do
-    let (f_1,f_2) = (f_1+f_2,f_1).
-end
-
-println f_1.
-assert (f_1 == 55)
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test028.ast b/asteroid/test-suites/using-asteroid-tests/programs/test028.ast
deleted file mode 100644
index 45b040bd..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test028.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-let sq = [1 to 10] @map(lambda with x do return x*x).
-
-println sq.
-
-assert (sq == [1,4,9,16,25,36,49,64,81,100])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test029.ast b/asteroid/test-suites/using-asteroid-tests/programs/test029.ast
deleted file mode 100644
index 03c8bb42..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test029.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "math".
-
-let p2 = [0 to 9] @map(lambda with x do return pow(2,x)).
-
-println p2.
-
-assert (p2 == [1,2,4,8,16,32,64,128,256,512])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test030.ast b/asteroid/test-suites/using-asteroid-tests/programs/test030.ast
deleted file mode 100644
index d1584e9b..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test030.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-
-load "io".
-load "math".
-
-let odd = []
-for (n if mod(n,2) =/= 0) in 1 to 10 do
-    let odd = odd + [n].
-end
-
-println odd.
-assert(odd == [1,3,5,7,9])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test031.ast b/asteroid/test-suites/using-asteroid-tests/programs/test031.ast
deleted file mode 100644
index e83a632b..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test031.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-
-load "io".
-load "math".
-
-let even = []
-for (n if mod(n,2) == 0) in 1 to 10 do
-    let even = even + [n].
-end
-
-println even.
-assert(even == [2,4,6,8,10])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test032.ast b/asteroid/test-suites/using-asteroid-tests/programs/test032.ast
deleted file mode 100644
index a177e8e3..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test032.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "math".
-
--- not equal under the default tolerance of 1E-09
-assert (not isclose(2.0,2.00001)).
-
--- equal under the user defined tolerance of 0.0001
-assert (isclose(2.0,2.00001,0.0001)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test033.ast b/asteroid/test-suites/using-asteroid-tests/programs/test033.ast
deleted file mode 100644
index 75f9526f..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test033.ast
+++ /dev/null
@@ -1,22 +0,0 @@
-
-load "io".
-load "math".
-
-function isprime with x do
-    if x >= 2 do
-        for y in range(2,x) do
-            if not mod(x,y) do
-                return false.
-            end
-        end
-    else do
-        return false.
-    end
-    return true.
-end
-
-println (isprime 17).
-println (isprime 15).
-
-assert (isprime(17)).
-assert (not isprime(15)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test034.ast b/asteroid/test-suites/using-asteroid-tests/programs/test034.ast
deleted file mode 100644
index fdd95570..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test034.ast
+++ /dev/null
@@ -1,26 +0,0 @@
-
-load "io".
-load "math".
-
-function isprime with x do
-    if x >= 2 do
-        for y in range(2,x) do
-            if not mod(x,y) do
-                return false.
-            end
-        end
-    else do
-        return false.
-    end
-    return true.
-end
-
-let cnt = 0.
-for (n if isprime(n)) in 1 to 1000000 do
-    println n.
-    let cnt = cnt+1.
-    if cnt == 10 do
-        break.
-    end
-end
-    
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test035.ast b/asteroid/test-suites/using-asteroid-tests/programs/test035.ast
deleted file mode 100644
index 32825103..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test035.ast
+++ /dev/null
@@ -1,42 +0,0 @@
-
-load "io".
-load "math".
-
-function isprime with x do
-    if x >= 2 do
-        for y in range(2,x) do
-            if not mod(x,y) do
-                return false.
-            end
-        end
-    else do
-        return false.
-    end
-    return true.
-end
-
-function primes with x do
-    let lp = [].
-    for (n if isprime(n)) in 1 to x do
-        let lp = lp+[n].
-    end
-    return lp.
-end
-
-let n = 165.
-let factors = [].
-let primes_list =  primes(n).
-let ix = 0.
-
-while n > 1 do
-    let factor = primes_list @ix.
-    let ix = ix+1.
-    if not mod(n,factor) do
-        let ix = 0.
-        let n = n/factor.
-        let factors = factors+[factor].
-    end
-end
-println factors.
-
-assert (factors == [3,5,11])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test036.ast b/asteroid/test-suites/using-asteroid-tests/programs/test036.ast
deleted file mode 100644
index 0d40eb3a..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test036.ast
+++ /dev/null
@@ -1,17 +0,0 @@
-
-load "io".
-load "math".
-
--- fraction a/b
-let a = 16.
-let b = 280.
-
--- reduce fraction
-let gcd_val = gcd(a,b).
-let numerator = a/gcd_val.
-let denominator = b/gcd_val.
-println numerator.
-println denominator.
-
--- show that original and reduced fraction are the same value
-assert (a/b == numerator/denominator).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test037.ast b/asteroid/test-suites/using-asteroid-tests/programs/test037.ast
deleted file mode 100644
index 20b50297..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test037.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-
-try
-    println (42/0).
-catch Exception(_,m) do
-    println m.
-end
-println "We are still alive...".
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test038.ast b/asteroid/test-suites/using-asteroid-tests/programs/test038.ast
deleted file mode 100644
index 7fcbf5b7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test038.ast
+++ /dev/null
@@ -1,16 +0,0 @@
-
-load "io".
-load "random".
-load "util".
-load "type".
-
-seed(42).
-
-println (random()).          -- random value in [0.0,1.0)
-println (randint(0.0,1.0)).  -- random value in [0.0,1.0]
-println (randint(0,1)).      -- always 0 or 1
-
--- generating a random number in the appropriate interval
-let n = 10.
-println (randint(0.0,toreal(n))).
-println (randint(0,n)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test039.ast b/asteroid/test-suites/using-asteroid-tests/programs/test039.ast
deleted file mode 100644
index 748c5e74..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test039.ast
+++ /dev/null
@@ -1,18 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-let n = 1234.
-let sq = n*n.
-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 = tointeger(rstr).
-println rval.
-
-assert (rval == 5227)
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test040.ast b/asteroid/test-suites/using-asteroid-tests/programs/test040.ast
deleted file mode 100644
index 4a493ee4..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test040.ast
+++ /dev/null
@@ -1,13 +0,0 @@
-
-load "io".
-load "random".
-
-let hist = [0 to 9] @map(lambda with _ do return 0).
-
-for _ in range(10000) do
-    let ix = randint(0,9).
-    let hist @ix = hist @ix +1
-end
-
-println hist.
-
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test041.ast b/asteroid/test-suites/using-asteroid-tests/programs/test041.ast
deleted file mode 100644
index 35ef6bd8..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test041.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "io".
-load "math".
-
-let x = [10, 3].
-let y = [9, 1].
-let d = (sqrt(pow(x@0-y@0,2) + pow(x@1-y@1,2))).
-println d.
-
-assert (d == 2.23606797749979)
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test042.ast b/asteroid/test-suites/using-asteroid-tests/programs/test042.ast
deleted file mode 100644
index 9406b08d..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test042.ast
+++ /dev/null
@@ -1,12 +0,0 @@
-
-load "io".
-load "math".
-load "vector".
-
-let x = [10, 3].
-let y = [9, 1].
-let a = vsub(x,y).
-let d = sqrt(dot(a,a)).
-println d.
-
-assert (d == 2.23606797749979)
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test043.ast b/asteroid/test-suites/using-asteroid-tests/programs/test043.ast
deleted file mode 100644
index 0458ba85..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test043.ast
+++ /dev/null
@@ -1,14 +0,0 @@
-
-load "io".
-load "math".
-
-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 diff_sq = values @map(lambda with x do return pow(x-avg,2)).
-let numerator = diff_sq @reduce(lambda with (x,y) do return x+y).
-let denominator = values @length() -1.
-let sigma = sqrt(numerator/denominator).
-println sigma.
-
-assert (sigma == 420.96248961952256)
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test044.ast b/asteroid/test-suites/using-asteroid-tests/programs/test044.ast
deleted file mode 100644
index 282e1406..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test044.ast
+++ /dev/null
@@ -1,22 +0,0 @@
-
-load "io".
-load "math".
-
-function polar_to_cartesian with (r,psi) do
-    -- return a tuple: (x,y)
-    return (r*cos(psi),r*sin(psi)).
-end
-
-function cartesian_to_polar with (x,y) do
-    -- return a tuple: (r,psi)
-    return (sqrt(pow(x,2)+pow(y,2)),atan(y/x)).
-end
-
-let (r,psi) = cartesian_to_polar(1,2).
-let (x,y) = polar_to_cartesian(r,psi).
-
-println (x,y).
-
--- show that the recovered coordinates are the same
--- we started with
-assert (isclose(1,x,0.0001) and isclose(2,y,0.0001)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test045.ast b/asteroid/test-suites/using-asteroid-tests/programs/test045.ast
deleted file mode 100644
index d6e6934d..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test045.ast
+++ /dev/null
@@ -1,38 +0,0 @@
-
-load "io".
-load "math".
-load "util".
-load "type".
-
-function polar_to_cartesian with (r,psi) do
-    -- return a tuple: (x,y)
-    return (r*cos(psi),r*sin(psi)).
-end
-
-function cartesian_to_polar with (x,y) do
-    return (sqrt(pow(x,2)+pow(y,2)),cartesian_to_psi(x,y)).
-end
-
-function cartesian_to_psi
-    with (x,y) if x > 0  do
-        return atan(toreal(y)/x).
-    with (x,y) if x < 0 and y >= 0 do
-        return atan(toreal(y)/x)+pi.
-    with (x,y) if x < 0 and y < 0 do
-        return atan(toreal(y)/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
-        return -pi/2.
-    with (x,y) if x == 0 and y == 0 do
-        return none.
-    end
-
-let (r,psi) = cartesian_to_polar(-3,5).
-let (x,y) = polar_to_cartesian(r,psi).
-
-println (x,y).
-
--- show that the recovered coordinates are the same
--- we started with
-assert (isclose(-3,x,0.0001) and isclose(5,y,0.0001)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test046.ast b/asteroid/test-suites/using-asteroid-tests/programs/test046.ast
deleted file mode 100644
index 84887151..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test046.ast
+++ /dev/null
@@ -1,19 +0,0 @@
-
-load "io".
-load "math".
-load "random".
-
-seed(42).
-
-let inside = 0. 
-let n = 10000.
-for _ in 1 to n do 
-    let point = (randint(-1.0,1.0),randint(-1.0,1.0)).
-    if sqrt(pow(point@0,2)+pow(point@1,2)) <= 1.0 do
-        let inside = inside+1.
-    end
-end
-let area = 4.0 * inside / n.
-println area.
-
-assert (area == 3.1392).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test047.ast b/asteroid/test-suites/using-asteroid-tests/programs/test047.ast
deleted file mode 100644
index e2eefee8..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test047.ast
+++ /dev/null
@@ -1,17 +0,0 @@
-
-load "io".
-load "random".
-load "util".
-load "type".
-
-let n = randint(0,10).
-let guess = tointeger(input("Guess my number between 0 and 10: ")).
-while guess =/= n do
-    if guess < n do
-        println "Too small.".
-    elif guess > n  do
-         println "Too big.".
-    end
-    let guess = tointeger(input("Try again: ")).
-end
-println "Yes, this is it!".
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test048.ast b/asteroid/test-suites/using-asteroid-tests/programs/test048.ast
deleted file mode 100644
index bf0c06e5..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test048.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-let bin = "101101".
-let int = tointeger(bin,2).
-println int.
-
-assert (int == 45).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test049.ast b/asteroid/test-suites/using-asteroid-tests/programs/test049.ast
deleted file mode 100644
index 11c9a3d7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test049.ast
+++ /dev/null
@@ -1,15 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-let val = 42.
-
-println (tobase(val,2)).  -- bin
-println (tobase(val,8)).  -- oct
-println (tobase(val,16)). -- hex
-
--- make sure that conversions are correct in both directions
-assert (tointeger(tobase(val,2),2) == val).
-assert (tointeger(tobase(val,8),8) == val).
-assert (tointeger(tobase(val,16),16) == val).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test050.ast b/asteroid/test-suites/using-asteroid-tests/programs/test050.ast
deleted file mode 100644
index 85ea9ba7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test050.ast
+++ /dev/null
@@ -1,14 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-let number = 139487854.
-
-
-let s = tostring number @explode()
-                        @map(tointeger)
-                        @reduce(lambda with (x,y) do return x+y).
-println s.
-
-assert (s == 49).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test051.ast b/asteroid/test-suites/using-asteroid-tests/programs/test051.ast
deleted file mode 100644
index d01bcfee..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test051.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-let bits = "1010101" @replace("0","")
-                     @length().
-println bits.
-
-assert (bits == 4).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test052.ast b/asteroid/test-suites/using-asteroid-tests/programs/test052.ast
deleted file mode 100644
index 73e9f64d..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test052.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-let a = tointeger([67, 8, 1, 5, 45] @map(tostring) @sort(true) @join("")).
-println a.
-
-assert (a == 8675451).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test053.ast b/asteroid/test-suites/using-asteroid-tests/programs/test053.ast
deleted file mode 100644
index 8280c46b..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test053.ast
+++ /dev/null
@@ -1,27 +0,0 @@
-
-load "io".
-load "math".
-load "util".
-load "hash".
-load "type".
-
-let roman_hash = HashTable().
-roman_hash @insert(1000,["","M","MM","MMM"]).
-roman_hash @insert(100,["","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"]).
-roman_hash @insert(10,["","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"]).
-roman_hash @insert(1,["","I","II","III","IV","V","VI","VII","VIII","IX"]).
-
-let n = 2018.
-let p10 = range(tostring n @length()) @map(lambda with x do return pow(10,x))
-                                      @reverse().
-let digits = tostring n @explode()
-                        @map(tointeger).
-let z = zip(digits, p10).
-println z.
-let roman = "".
-for (d,p) in z do
-    let roman = roman + roman_hash @get(p) @d.
-end
-println roman.
-
-assert (roman == "MMXVIII")
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test054.ast b/asteroid/test-suites/using-asteroid-tests/programs/test054.ast
deleted file mode 100644
index bd8ef1ff..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test054.ast
+++ /dev/null
@@ -1,32 +0,0 @@
-
-load "io".
-load "math".
-
-let names = ["zero","one","two","three","four","five","six","seven","eight","nine",
-             "ten","eleven","twelve","thirteen","fourteen","fifteen",
-             "sixteen","seventeen","eighteen","nineteen","twenty","thirty",
-             "forty","fifty","sixty","seventy","eighty","ninety"].
-
-function spell_number 
-    with (n:%integer) if n < 20 do
-        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 "".
-        return r.
-    with (n:%integer) if n < 1000 do  
-        return spell_part(n,100,"hundred").
-    with (n:%integer) if n < 1000000 do 
-        return spell_part(n,1000,"thousand").
-    end
-
-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.
-    end
-
-println (spell_number 15).
-println (spell_number 75).
-println (spell_number 987654).
-println (spell_number 1001).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test055.ast b/asteroid/test-suites/using-asteroid-tests/programs/test055.ast
deleted file mode 100644
index 1a09030e..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test055.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-let (a,b) = (10,20). 
-let (b,a) = (a,b).
-println ("a = "+a,"b = "+b).
-
-assert ((a,b) is (20,10)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test056.ast b/asteroid/test-suites/using-asteroid-tests/programs/test056.ast
deleted file mode 100644
index 3fd79560..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test056.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-let a = [3,5,7,4].
-let (a@2,a@3) = (a@3,a@2).
-println a. 
-
-assert (a is [3,5,4,7]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test057.ast b/asteroid/test-suites/using-asteroid-tests/programs/test057.ast
deleted file mode 100644
index d9105dfa..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test057.ast
+++ /dev/null
@@ -1,7 +0,0 @@
-
-load "io".
-
-let a = [10, 20, 30, 40, 50].
-println (a @reverse()). 
-
-assert(a == [50,40,30,20,10]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test058.ast b/asteroid/test-suites/using-asteroid-tests/programs/test058.ast
deleted file mode 100644
index 2c71e9f2..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test058.ast
+++ /dev/null
@@ -1,19 +0,0 @@
-
-load "io".
-load "math".
-
-function rotate with (l:%list,i:%integer) do 
-    let n = l @length().
-    let vix = range n @map(lambda with x do return mod(x+i,n)).
-    return l @vix.
-end
-
-
-let a = [1, 3, 5, 7, 9, 11, 13, 15].
-let b = rotate(a,3).
-let c = rotate(a,-3).
-println a.
-println b.
-println c.
-
-assert(b == [7,9,11,13,15,1,3,5] and c == [11,13,15,1,3,5,7,9]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test059.ast b/asteroid/test-suites/using-asteroid-tests/programs/test059.ast
deleted file mode 100644
index d49d541b..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test059.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "random".
-
-seed(42).
-let b = [1 to 20] @shuffle().
-println b.
-
-assert(b == [20,6,15,5,10,14,16,19,7,13,18,11,2,12,3,17,8,9,1,4]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test060.ast b/asteroid/test-suites/using-asteroid-tests/programs/test060.ast
deleted file mode 100644
index 588fd950..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test060.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "vector".
-
-let a = [1 to 10].
-let b = vadd(a,1).
-println b.
-
-assert(b == [2,3,4,5,6,7,8,9,10,11]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test061.ast b/asteroid/test-suites/using-asteroid-tests/programs/test061.ast
deleted file mode 100644
index e5ca9c99..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test061.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "io".
-load "vector".
-
-let a = [10 to 20].
-let b = [30 to 40].
-let c = vadd(a,b).
-println c.
-
-assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test062.ast b/asteroid/test-suites/using-asteroid-tests/programs/test062.ast
deleted file mode 100644
index 50cf284a..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test062.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "io".
-load "vector".
-
-let a = [10 to 20].
-let b = [30 to 40].
-let c = vop((lambda with (x,y) do return x+y),a,b).
-println c.
-
-assert(c == [40,42,44,46,48,50,52,54,56,58,60]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test063.ast b/asteroid/test-suites/using-asteroid-tests/programs/test063.ast
deleted file mode 100644
index 3be958d1..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test063.ast
+++ /dev/null
@@ -1,13 +0,0 @@
-
-load "io".
-load "vector".
-load "random".
-
-seed(42).
-
-let a = [1 to 10] @shuffle().
-let b = [1 to 10] @shuffle().
-let c = vop((lambda with (x,y) do return x<y),a,b).
-println c.
-
-assert(c == [false,true,false,false,false,true,false,false,true,true]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test064.ast b/asteroid/test-suites/using-asteroid-tests/programs/test064.ast
deleted file mode 100644
index d1c4c364..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test064.ast
+++ /dev/null
@@ -1,10 +0,0 @@
-
-load "io".
-load "set".
-
-let a = [1 to 10].
-let b = [5 to 15].
-let c = sdiff(a,b).
-println c.
-
-assert(c @sort() == [1,2,3,4]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test065.ast b/asteroid/test-suites/using-asteroid-tests/programs/test065.ast
deleted file mode 100644
index aeab9684..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test065.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
-let s = a @reduce(lambda with (x,y) do return x+y).
-println s.
-
-assert (s == 125).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test066.ast b/asteroid/test-suites/using-asteroid-tests/programs/test066.ast
deleted file mode 100644
index 89b93af9..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test066.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-
-let a = [4, 6, 8, 1, 0, 58, 1, 34, 7, 4, 2].
-let f = (lambda with (x,y) do return x+(y if y > 10 else 0)).
-let s = a @reduce(f,0).
-println s.
-
-assert (s == 92).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test067.ast b/asteroid/test-suites/using-asteroid-tests/programs/test067.ast
deleted file mode 100644
index 978fe307..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test067.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-
-let a = [7, 11, 34, 50, 200].
-let avg = a @reduce(lambda with (x,y) do return x+y)/a @length().
-println avg.
-
-assert (avg == 60).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test069.ast b/asteroid/test-suites/using-asteroid-tests/programs/test069.ast
deleted file mode 100644
index 84cf7f4d..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test069.ast
+++ /dev/null
@@ -1,6 +0,0 @@
-
-load "io".
-
-let array = [10, 14, 0, 15, 17, 20, 30, 35].
-let x = 17.
-println ((x+" is in the list") if array @member(x) else (x+" is not in the list")).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test070.ast b/asteroid/test-suites/using-asteroid-tests/programs/test070.ast
deleted file mode 100644
index d6ccf5d4..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test070.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-
-load "io".
-
-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
-    println (x+" is in the list"). 
-else 
-    println (x+" is not in the list").
-end
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test071.ast b/asteroid/test-suites/using-asteroid-tests/programs/test071.ast
deleted file mode 100644
index aa807242..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test071.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "math".
-load "util".
-load "type".
-
-let array = [2, 4, 18, 9, 16, 7, 10].
-let odd = array @reduce(lambda with (acc,i) do return i if isnone(acc) and mod(i,2) else acc,none).
-println odd.
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test072.ast b/asteroid/test-suites/using-asteroid-tests/programs/test072.ast
deleted file mode 100644
index 2185f3bc..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test072.ast
+++ /dev/null
@@ -1,8 +0,0 @@
-
-load "io".
-load "math".
-
-let array = [20 to 30] @filter(lambda with x do return mod(x,2)).
-println array.
-
-assert (array == [21,23,25,27,29]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test073.ast b/asteroid/test-suites/using-asteroid-tests/programs/test073.ast
deleted file mode 100644
index ccbb4918..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test073.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "math".
-
-let a = [20 to 30].
-let array = a @[1 to a @length()-1 step 2] .
-println array.
-
-assert (array == [21,23,25,27,29]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test074.ast b/asteroid/test-suites/using-asteroid-tests/programs/test074.ast
deleted file mode 100644
index eab5d1d3..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test074.ast
+++ /dev/null
@@ -1,9 +0,0 @@
-
-load "io".
-load "math".
-
-let dt = ["apple","pear","grape","lemon","peach","apple","banana","grape","pineapple","avocado"].
-let cnt = dt @count("grape").
-println cnt.
-
-assert (cnt == 2).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test075.ast b/asteroid/test-suites/using-asteroid-tests/programs/test075.ast
deleted file mode 100644
index 0344e870..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test075.ast
+++ /dev/null
@@ -1,13 +0,0 @@
-
-load "io".
-load "set".
-
-function unique with lst:%list do
-    return toset lst @sort().
-end
-
-let a = unique([2, 3, 7, 4, 5, 5, 6, 2, 10, 7]).
-
-println a.
-
-assert (a == [2,3,4,5,6,7,10])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test076.ast b/asteroid/test-suites/using-asteroid-tests/programs/test076.ast
deleted file mode 100644
index 566173ec..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test076.ast
+++ /dev/null
@@ -1,19 +0,0 @@
-
-load "io".
-
-function max with lst:%list do
-    return lst @sort(true) @0.
-end
-
-function min with lst:%list do
-    return lst @sort() @0.
-end
-
-let a = max [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
-let b = min [7, 6, 12, 3, 4, 10, 2, 5, 15, 6, 7, 8, 9, 3].
-
-
-println a.
-println b.
-
-assert (a == 15 and b == 2).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test077.ast b/asteroid/test-suites/using-asteroid-tests/programs/test077.ast
deleted file mode 100644
index b83afc2c..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test077.ast
+++ /dev/null
@@ -1,11 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-let a = [3, 7, 19, 20, 34].
-let b = toboolean(a @reduce(lambda with (x,y) do return y if x<y else false)).
-
-println b.
-
-assert (b).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test078.ast b/asteroid/test-suites/using-asteroid-tests/programs/test078.ast
deleted file mode 100644
index f3b7969e..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test078.ast
+++ /dev/null
@@ -1,60 +0,0 @@
-
-load "io".
-
-function transpose with m do
-    -- figure out the dimensions
-    let xdim = m @0 @length().
-    let ydim = m @length().
-    
-    -- reserve space for the transpose
-    -- first we do the ydim of new matrix
-    let mt = range(xdim).
-    for y in mt do
-        let mt @y = range(ydim).
-    end
-    
-    -- swap the elements
-    for x in range(xdim) do
-        for y in range(ydim) do
-            let mt @x @y = m @y @x.
-        end
-    end
-    
-    return mt.
-end
-
-function print_matrix with m do
-    println "".
-    for r in m do
-        for e in r do
-            print (e + " ").
-        end
-        println ("").
-    end
-    println "".
-end
-
-let m = [[1,2],
-         [3,4]].
-
-let mt = transpose(m).
-
-println ("The transpose of:").
-print_matrix m.
-println ("is:").
-print_matrix mt.
-println ("").
-
-let m = [[1,2],
-         [3,4],
-         [5,6]].
-         
-let mt = transpose(m).
-
-println ("The transpose of:").
-print_matrix m.
-println ("is:").
-print_matrix mt.
-println ("").
-
-assert(mt == [[1,3,5],[2,4,6]]).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test079.ast b/asteroid/test-suites/using-asteroid-tests/programs/test079.ast
deleted file mode 100644
index 2a31fe05..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test079.ast
+++ /dev/null
@@ -1,29 +0,0 @@
-
-load "io".
-load "hash".
-load "sort".
-load "random".
-
-seed(42).
-
--- hash of names with ages
-let ht = HashTable().
-ht @insert("Billie",randint(20,50)).
-ht @insert("Joe",randint(20,50)).
-ht @insert("Pete",randint(20,50)).
-ht @insert("Brandi",randint(20,50)).
-
--- export the hash as a list of pairs
-let lst = ht @aslist().
-
--- define our order predicate on a 
--- list of pairs where the second 
--- component holds the order info
-function pairs with ((_,x),(_,y)) do
-    return true if x < y else false.
-end
-
--- print out the sorted list
-println (sort(pairs,lst)).
-
-assert (sort(pairs,lst) == [("Pete",20),("Joe",23),("Billie",40),("Brandi",43)])
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test080.ast b/asteroid/test-suites/using-asteroid-tests/programs/test080.ast
deleted file mode 100644
index 38c7c7a7..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test080.ast
+++ /dev/null
@@ -1,34 +0,0 @@
-
-load "io".
-load "hash".
-load "sort".
-
-let fruit_hash = HashTable().
-fruit_hash @insert("apple","red").
-fruit_hash @insert("avocado","green").
-fruit_hash @insert("banana","yellow").
-fruit_hash @insert("grapefruit","orange").
-fruit_hash @insert("grapes","green").
-fruit_hash @insert("kiwi","green").
-fruit_hash @insert("lemon","yellow").
-fruit_hash @insert("orange","orange").
-fruit_hash @insert("pear","green").
-fruit_hash @insert("plum","purple").
-
-let fruit_lst = fruit_hash @aslist().
-
-let color_hash = HashTable().
-for (_,color) in fruit_lst do
-    if not color_hash @get(color) do
-        color_hash @insert(color,1).
-    else
-        color_hash @insert(color, color_hash @get(color) +1).
-    end
-end
-let color_lst = color_hash @aslist().
-
-function pairs with ((_,x),(_,y)) do
-    return true if x < y else false.
-end
-
-println (sort(pairs,color_lst)).
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test081.ast b/asteroid/test-suites/using-asteroid-tests/programs/test081.ast
deleted file mode 100644
index c3d96f98..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test081.ast
+++ /dev/null
@@ -1,14 +0,0 @@
-
-load "io".
-load "util".
-load "type".
-
-function format with v do
-    let maxlen = 3.
-    let vstr = tostring v.
-    return [1 to maxlen-len(vstr)] @map(lambda with _ do return " ") @join("") + vstr.
-end
-
-for i in 1 to 10 do
-    println ([1 to 10] @map(lambda with x do return format(i*x)) @join(" ")).
-end
diff --git a/asteroid/test-suites/using-asteroid-tests/programs/test082.ast b/asteroid/test-suites/using-asteroid-tests/programs/test082.ast
deleted file mode 100644
index 8b906f02..00000000
--- a/asteroid/test-suites/using-asteroid-tests/programs/test082.ast
+++ /dev/null
@@ -1,21 +0,0 @@
-
-load "io".
-load "vector".
-load "util".
-load "type".
-
-let triangle = [[1]].
-let ix = 0.
-
-for i in 1 to 6 do
-    let v = triangle @ix.
-    let v1 = [0] + v.
-    let v2 = v + [0].
-    let new_v = vadd(v1,v2).
-    let triangle = triangle + [new_v].
-    let ix = ix + 1.
-end
-
-for r in triangle do
-    println (r @map(lambda with v do return tostring v) @join(" ")).
-end
diff --git a/asteroid/test-suites/using-asteroid-tests/run-tests.py b/asteroid/test-suites/using-asteroid-tests/run-tests.py
deleted file mode 100755
index c78e242b..00000000
--- a/asteroid/test-suites/using-asteroid-tests/run-tests.py
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/usr/bin/env python3
-# coding: utf-8
-
-# # Regression Tests
-
-
-import sys
-import os
-
-# uncomment if running on SageMaker
-#sys.path[0] = '/home/ec2-user/SageMaker/asteroid/code'
-sys.path[0] = '/Users/lutz/Dropbox/URI/Projects/Asteroid/asteroid-git/code'
-from asteroid.interp import interp
-
-programs = os.listdir("programs")
-programs.sort()
-
-for pname in programs:
-    f = open("programs/"+pname,"r")
-    p = f.read()
-    print("**********"+pname+"************")
-    print(p)
-    print("**********output***********")
-    interp(p, exceptions=True)
-    f.close()