From 9937f344dcdf3df5cebc1ae339930ba1f712e449 Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Wed, 26 Dec 2018 20:30:14 +0000
Subject: [PATCH 1/6] Major refactoring. Major problems!

On the right path but it doesn't work yet.
---
 Makefile                     |   2 +-
 src/arith/peano.c            | 121 +++++++++---------
 src/arith/peano.h            |   8 +-
 src/arith/ratio.c            |  77 ++++++------
 src/arith/ratio.h            |  18 ++-
 src/init.c                   |   2 +
 src/memory/consspaceobject.c | 120 +++---------------
 src/memory/consspaceobject.h |  36 ++----
 src/memory/dump.c            | 120 ++++++++++++++++++
 src/memory/dump.h            |  29 +++++
 src/memory/stack.c           | 169 ++++++++++++++++++--------
 src/memory/stack.h           |  48 ++++----
 src/memory/vectorspace.c     |  26 ++--
 src/memory/vectorspace.h     |  16 ++-
 src/ops/lispops.c            | 229 ++++++++++++++++++++---------------
 src/ops/lispops.h            |  57 +++++----
 src/ops/print.c              |   8 +-
 src/ops/read.c               |  53 ++++----
 src/ops/read.h               |   4 +-
 src/repl.c                   |  58 ++++++---
 20 files changed, 695 insertions(+), 506 deletions(-)
 create mode 100644 src/memory/dump.c
 create mode 100644 src/memory/dump.h

diff --git a/Makefile b/Makefile
index 98a6bd3..3fc8148 100644
--- a/Makefile
+++ b/Makefile
@@ -38,7 +38,7 @@ test: $(OBJS) $(TESTS) Makefile
 
 .PHONY: clean
 clean:
-	$(RM) $(TARGET) $(OBJS) $(DEPS) $(SRC_DIRS)/*~ *~
+	$(RM) $(TARGET) $(OBJS) $(DEPS) $(SRC_DIRS)/*~ $(SRC_DIRS)/*/*~ *~
 
 repl:
 	$(TARGET) -p 2> psse.log
diff --git a/src/arith/peano.c b/src/arith/peano.c
index 423bd51..63783f5 100644
--- a/src/arith/peano.c
+++ b/src/arith/peano.c
@@ -8,11 +8,11 @@
  */
 
 #include <ctype.h>
+#include <math.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <math.h>
 
 #include "consspaceobject.h"
 #include "conspage.h"
@@ -28,7 +28,7 @@
 
 long double to_long_double( struct cons_pointer arg );
 int64_t to_long_int( struct cons_pointer arg );
-struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
+struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer arg1,
                            struct cons_pointer arg2 );
 
 
@@ -119,7 +119,7 @@ int64_t to_long_int( struct cons_pointer arg ) {
 * return a cons_pointer indicating a number which is the sum of
 * the numbers indicated by `arg1` and `arg2`.
 */
-struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
+struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer arg1,
                            struct cons_pointer arg2 ) {
     struct cons_pointer result;
     struct cons_space_object cell1 = pointer2cell( arg1 );
@@ -153,7 +153,7 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
                                                cell2.payload.integer.value );
                         break;
                     case RATIOTV:
-                        result = add_integer_ratio( frame, arg1, arg2 );
+                        result = add_integer_ratio( frame_pointer, arg1, arg2 );
                         break;
                     case REALTV:
                         result =
@@ -161,9 +161,9 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
                                        to_long_double( arg2 ) );
                         break;
                     default:
-                        result = lisp_throw( c_string_to_lisp_string
+                        result = throw_exception( c_string_to_lisp_string
                                              ( "Cannot add: not a number" ),
-                                             frame );
+                                             frame_pointer );
                         break;
                 }
                 break;
@@ -173,10 +173,10 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
                         result = arg2;
                         break;
                     case INTEGERTV:
-                        result = add_integer_ratio( frame, arg2, arg1 );
+                        result = add_integer_ratio( frame_pointer, arg2, arg1 );
                         break;
                     case RATIOTV:
-                        result = add_ratio_ratio( frame, arg1, arg2 );
+                        result = add_ratio_ratio( frame_pointer, arg1, arg2 );
                         break;
                     case REALTV:
                         result =
@@ -184,9 +184,9 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
                                        to_long_double( arg2 ) );
                         break;
                     default:
-                        result = lisp_throw( c_string_to_lisp_string
+                        result = throw_exception( c_string_to_lisp_string
                                              ( "Cannot add: not a number" ),
-                                             frame );
+                                             frame_pointer );
                         break;
                 }
                 break;
@@ -197,8 +197,8 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
                 break;
             default:
                 result = exceptionp( arg2 ) ? arg2 :
-                    lisp_throw( c_string_to_lisp_string
-                                ( "Cannot add: not a number" ), frame );
+                    throw_exception( c_string_to_lisp_string
+                                ( "Cannot add: not a number" ), frame_pointer );
         }
     }
 
@@ -218,7 +218,7 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer arg1,
  * @return a pointer to an integer or real.
  */
 struct cons_pointer lisp_add( struct stack_frame
-                              *frame, struct
+                              *frame, struct cons_pointer frame_pointer, struct
                               cons_pointer env ) {
     struct cons_pointer result = make_integer( 0 );
     struct cons_pointer tmp;
@@ -227,7 +227,7 @@ struct cons_pointer lisp_add( struct stack_frame
           i < args_in_frame &&
           !nilp( frame->arg[i] ) && !exceptionp( result ); i++ ) {
         tmp = result;
-        result = add_2( frame, result, frame->arg[i] );
+        result = add_2( frame, frame_pointer, result, frame->arg[i] );
         if ( !eq( tmp, result ) ) {
             dec_ref( tmp );
         }
@@ -236,7 +236,7 @@ struct cons_pointer lisp_add( struct stack_frame
     struct cons_pointer more = frame->more;
     while ( consp( more ) && !exceptionp( result ) ) {
         tmp = result;
-        result = add_2( frame, result, c_car( more ) );
+        result = add_2( frame, frame_pointer, result, c_car( more ) );
         if ( !eq( tmp, result ) ) {
             dec_ref( tmp );
         }
@@ -252,7 +252,7 @@ struct cons_pointer lisp_add( struct stack_frame
 * return a cons_pointer indicating a number which is the product of
 * the numbers indicated by `arg1` and `arg2`.
 */
-struct cons_pointer multiply_2( struct stack_frame *frame,
+struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer arg1,
                                 struct cons_pointer arg2 ) {
     struct cons_pointer result;
@@ -286,7 +286,7 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                                                cell2.payload.integer.value );
                         break;
                     case RATIOTV:
-                        result = multiply_integer_ratio( frame, arg1, arg2 );
+                        result = multiply_integer_ratio( frame_pointer, arg1, arg2 );
                         break;
                     case REALTV:
                         result =
@@ -294,9 +294,9 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                                        to_long_double( arg2 ) );
                         break;
                     default:
-                        result = lisp_throw( c_string_to_lisp_string
+                        result = throw_exception( c_string_to_lisp_string
                                              ( "Cannot multiply: not a number" ),
-                                             frame );
+                                             frame_pointer );
                         break;
                 }
                 break;
@@ -306,10 +306,10 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                         result = arg2;
                         break;
                     case INTEGERTV:
-                        result = multiply_integer_ratio( frame, arg2, arg1 );
+                        result = multiply_integer_ratio( frame_pointer, arg2, arg1 );
                         break;
                     case RATIOTV:
-                        result = multiply_ratio_ratio( frame, arg1, arg2 );
+                        result = multiply_ratio_ratio( frame_pointer, arg1, arg2 );
                         break;
                     case REALTV:
                         result =
@@ -317,9 +317,9 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                                        to_long_double( arg2 ) );
                         break;
                     default:
-                        result = lisp_throw( c_string_to_lisp_string
+                        result = throw_exception( c_string_to_lisp_string
                                              ( "Cannot multiply: not a number" ),
-                                             frame );
+                                             frame_pointer );
                 }
                 break;
             case REALTV:
@@ -328,9 +328,9 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                                to_long_double( arg2 ) );
                 break;
             default:
-                result = lisp_throw( c_string_to_lisp_string
+                result = throw_exception( c_string_to_lisp_string
                                      ( "Cannot multiply: not a number" ),
-                                     frame );
+                                     frame_pointer );
                 break;
         }
     }
@@ -353,7 +353,7 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
  */
 struct cons_pointer lisp_multiply( struct
                                    stack_frame
-                                   *frame, struct
+                                   *frame, struct cons_pointer frame_pointer, struct
                                    cons_pointer env ) {
     struct cons_pointer result = make_integer( 1 );
     struct cons_pointer tmp;
@@ -361,7 +361,7 @@ struct cons_pointer lisp_multiply( struct
     for ( int i = 0; i < args_in_frame && !nilp( frame->arg[i] )
           && !exceptionp( result ); i++ ) {
         tmp = result;
-        result = multiply_2( frame, result, frame->arg[i] );
+        result = multiply_2( frame, frame_pointer, result, frame->arg[i] );
 
         if ( !eq( tmp, result ) ) {
             dec_ref( tmp );
@@ -372,7 +372,7 @@ struct cons_pointer lisp_multiply( struct
     while ( consp( more )
             && !exceptionp( result ) ) {
         tmp = result;
-        result = multiply_2( frame, result, c_car( more ) );
+        result = multiply_2( frame, frame_pointer, result, c_car( more ) );
 
         if ( !eq( tmp, result ) ) {
             dec_ref( tmp );
@@ -388,7 +388,7 @@ struct cons_pointer lisp_multiply( struct
  * return a cons_pointer indicating a number which is the
  * inverse of the number indicated by `arg`.
  */
-struct cons_pointer inverse( struct stack_frame *frame,
+struct cons_pointer inverse( struct cons_pointer frame,
                              struct cons_pointer arg ) {
     struct cons_pointer result = NIL;
     struct cons_space_object cell = pointer2cell( arg );
@@ -430,7 +430,7 @@ struct cons_pointer inverse( struct stack_frame *frame,
  */
 struct cons_pointer lisp_subtract( struct
                                    stack_frame
-                                   *frame, struct
+                                   *frame, struct cons_pointer frame_pointer, struct
                                    cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_space_object cell0 = pointer2cell( frame->arg[0] );
@@ -451,10 +451,11 @@ struct cons_pointer lisp_subtract( struct
                     break;
                 case RATIOTV:{
                         struct cons_pointer tmp =
-                            make_ratio( frame, frame->arg[0],
+                            make_ratio( frame_pointer, frame->arg[0],
                                         make_integer( 1 ) );
+                        inc_ref(tmp);
                         result =
-                            subtract_ratio_ratio( frame, tmp, frame->arg[1] );
+                            subtract_ratio_ratio( frame_pointer, tmp, frame->arg[1] );
                         dec_ref( tmp );
                     }
                     break;
@@ -464,9 +465,9 @@ struct cons_pointer lisp_subtract( struct
                                    to_long_double( frame->arg[1] ) );
                     break;
                 default:
-                    result = lisp_throw( c_string_to_lisp_string
-                                         ( "Cannot multiply: not a number" ),
-                                         frame );
+                    result = throw_exception( c_string_to_lisp_string
+                                         ( "Cannot subtract: not a number" ),
+                                         frame_pointer );
                     break;
             }
             break;
@@ -477,16 +478,17 @@ struct cons_pointer lisp_subtract( struct
                     break;
                 case INTEGERTV:{
                         struct cons_pointer tmp =
-                            make_ratio( frame, frame->arg[1],
+                            make_ratio( frame_pointer, frame->arg[1],
                                         make_integer( 1 ) );
+                        inc_ref(tmp);
                         result =
-                            subtract_ratio_ratio( frame, frame->arg[0], tmp );
+                            subtract_ratio_ratio( frame_pointer, frame->arg[0], tmp );
                         dec_ref( tmp );
                     }
                     break;
                 case RATIOTV:
                     result =
-                        subtract_ratio_ratio( frame, frame->arg[0],
+                        subtract_ratio_ratio( frame_pointer, frame->arg[0],
                                               frame->arg[1] );
                     break;
                 case REALTV:
@@ -495,9 +497,9 @@ struct cons_pointer lisp_subtract( struct
                                    to_long_double( frame->arg[1] ) );
                     break;
                 default:
-                    result = lisp_throw( c_string_to_lisp_string
-                                         ( "Cannot multiply: not a number" ),
-                                         frame );
+                    result = throw_exception( c_string_to_lisp_string
+                                         ( "Cannot subtract: not a number" ),
+                                         frame_pointer );
                     break;
             }
             break;
@@ -507,8 +509,8 @@ struct cons_pointer lisp_subtract( struct
                            to_long_double( frame->arg[1] ) );
             break;
         default:
-            result = lisp_throw( c_string_to_lisp_string
-                                 ( "Cannot multiply: not a number" ), frame );
+            result = throw_exception( c_string_to_lisp_string
+                                 ( "Cannot subtract: not a number" ), frame_pointer );
             break;
     }
 
@@ -525,7 +527,7 @@ struct cons_pointer lisp_subtract( struct
  */
 struct cons_pointer lisp_divide( struct
                                  stack_frame
-                                 *frame, struct
+                                 *frame,  struct cons_pointer frame_pointer, struct
                                  cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_space_object arg0 = pointer2cell( frame->arg[0] );
@@ -542,8 +544,10 @@ struct cons_pointer lisp_divide( struct
                     break;
                 case INTEGERTV:{
                         struct cons_pointer unsimplified =
-                            make_ratio( frame, frame->arg[0], frame->arg[1] );
-                        result = simplify_ratio( frame, unsimplified );
+                            make_ratio( frame_pointer, frame->arg[0], frame->arg[1] );
+                        /* OK, if result may be unsimplified, we should not inc_ref it
+                         * - but if not, we should dec_ref it. */
+                        result = simplify_ratio( frame_pointer, unsimplified );
                         if ( !eq( unsimplified, result ) ) {
                             dec_ref( unsimplified );
                         }
@@ -552,9 +556,9 @@ struct cons_pointer lisp_divide( struct
                 case RATIOTV:{
                         struct cons_pointer one = make_integer( 1 );
                         struct cons_pointer ratio =
-                            make_ratio( frame, frame->arg[0], one );
+                            make_ratio( frame_pointer, frame->arg[0], one );
                         result =
-                            divide_ratio_ratio( frame, ratio, frame->arg[1] );
+                            divide_ratio_ratio( frame_pointer, ratio, frame->arg[1] );
                         dec_ref( ratio );
                     }
                     break;
@@ -564,9 +568,9 @@ struct cons_pointer lisp_divide( struct
                                    to_long_double( frame->arg[1] ) );
                     break;
                 default:
-                    result = lisp_throw( c_string_to_lisp_string
+                    result = throw_exception( c_string_to_lisp_string
                                          ( "Cannot divide: not a number" ),
-                                         frame );
+                                         frame_pointer );
                     break;
             }
             break;
@@ -577,16 +581,19 @@ struct cons_pointer lisp_divide( struct
                     break;
                 case INTEGERTV:{
                         struct cons_pointer one = make_integer( 1 );
+                  inc_ref( one);
                         struct cons_pointer ratio =
-                            make_ratio( frame, frame->arg[1], one );
+                            make_ratio( frame_pointer, frame->arg[1], one );
+                        inc_ref(ratio);
                         result =
-                            divide_ratio_ratio( frame, frame->arg[0], ratio );
+                            divide_ratio_ratio( frame_pointer, frame->arg[0], ratio );
                         dec_ref( ratio );
+                  dec_ref(one);
                     }
                     break;
                 case RATIOTV:
                     result =
-                        divide_ratio_ratio( frame, frame->arg[0],
+                        divide_ratio_ratio( frame_pointer, frame->arg[0],
                                             frame->arg[1] );
                     break;
                 case REALTV:
@@ -595,9 +602,9 @@ struct cons_pointer lisp_divide( struct
                                    to_long_double( frame->arg[1] ) );
                     break;
                 default:
-                    result = lisp_throw( c_string_to_lisp_string
+                    result = throw_exception( c_string_to_lisp_string
                                          ( "Cannot divide: not a number" ),
-                                         frame );
+                                         frame_pointer );
                     break;
             }
             break;
@@ -607,8 +614,8 @@ struct cons_pointer lisp_divide( struct
                            to_long_double( frame->arg[1] ) );
             break;
         default:
-            result = lisp_throw( c_string_to_lisp_string
-                                 ( "Cannot divide: not a number" ), frame );
+            result = throw_exception( c_string_to_lisp_string
+                                 ( "Cannot divide: not a number" ), frame_pointer );
             break;
     }
 
diff --git a/src/arith/peano.h b/src/arith/peano.h
index 79735c0..46008c2 100644
--- a/src/arith/peano.h
+++ b/src/arith/peano.h
@@ -23,7 +23,7 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_add( struct stack_frame *frame, struct cons_pointer env );
+     lisp_add( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 /**
  * Multiply an indefinite number of numbers together
@@ -32,7 +32,7 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_multiply( struct stack_frame *frame, struct cons_pointer env );
+     lisp_multiply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 /**
  * Subtract one number from another.
@@ -41,7 +41,7 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_subtract( struct stack_frame *frame, struct cons_pointer env );
+     lisp_subtract( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 /**
  * Divide one number by another.
@@ -50,7 +50,7 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_divide( struct stack_frame *frame, struct cons_pointer env );
+     lisp_divide( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 #ifdef __cplusplus
 }
diff --git a/src/arith/ratio.c b/src/arith/ratio.c
index 8a5eec7..042aea1 100644
--- a/src/arith/ratio.c
+++ b/src/arith/ratio.c
@@ -13,6 +13,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "dump.h"
 #include "equal.h"
 #include "integer.h"
 #include "lispops.h"
@@ -24,7 +25,7 @@
  * declared in peano.c, can't include piano.h here because
  * circularity. TODO: refactor.
  */
-struct cons_pointer inverse( struct stack_frame *frame,
+struct cons_pointer inverse( struct cons_pointer frame_pointer,
                              struct cons_pointer arg );
 
 /**
@@ -54,7 +55,7 @@ int64_t least_common_multiple( int64_t m, int64_t n ) {
  * be in a simplified representation. If `arg` isn't a ratio,
  * will throw exception.
  */
-struct cons_pointer simplify_ratio( struct stack_frame *frame,
+struct cons_pointer simplify_ratio( struct cons_pointer frame_pointer,
                                     struct cons_pointer arg ) {
     struct cons_pointer result = arg;
 
@@ -70,15 +71,15 @@ struct cons_pointer simplify_ratio( struct stack_frame *frame,
                 result = make_integer( ddrv / gcd );
             } else {
                 result =
-                    make_ratio( frame, make_integer( ddrv / gcd ),
+                    make_ratio( frame_pointer, make_integer( ddrv / gcd ),
                                 make_integer( drrv / gcd ) );
             }
         }
     } else {
         result =
-            lisp_throw( make_cons( c_string_to_lisp_string
+            throw_exception( make_cons( c_string_to_lisp_string
                                    ( "Shouldn't happen: bad arg to simplify_ratio" ),
-                                   arg ), frame );
+                                   arg ),  frame_pointer );
     }
 
     return result;
@@ -91,7 +92,7 @@ struct cons_pointer simplify_ratio( struct stack_frame *frame,
  * the ratios indicated by `arg1` and `arg2`. If you pass non-ratios,
  * this is going to break horribly.
  */
-struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
+struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
                                      struct cons_pointer arg1,
                                      struct cons_pointer arg2 ) {
     struct cons_pointer r, result;
@@ -123,7 +124,7 @@ struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
 #endif
 
         if ( dr1v == dr2v ) {
-            r = make_ratio( frame,
+            r = make_ratio(  frame_pointer,
                             make_integer( dd1v + dd2v ),
                             cell1.payload.ratio.divisor );
         } else {
@@ -131,10 +132,10 @@ struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
                 dr1vm = make_integer( dr1v * m1 ),
                 dd2vm = make_integer( dd2v * m2 ),
                 dr2vm = make_integer( dr2v * m2 ),
-                r1 = make_ratio( frame, dd1vm, dr1vm ),
-                r2 = make_ratio( frame, dd2vm, dr2vm );
+                r1 = make_ratio(  frame_pointer, dd1vm, dr1vm ),
+                r2 = make_ratio(  frame_pointer, dd2vm, dr2vm );
 
-            r = add_ratio_ratio( frame, r1, r2 );
+            r = add_ratio_ratio( frame_pointer, r1, r2 );
 
             /* because the references on dd1vm, dr1vm, dd2vm and dr2vm were
              * never incremented except when making r1 and r2, decrementing
@@ -143,17 +144,17 @@ struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
             dec_ref( r2 );
         }
 
-        result = simplify_ratio( frame, r );
+        result = simplify_ratio(  frame_pointer, r );
         if ( !eq( r, result ) ) {
             dec_ref( r );
         }
     } else {
         result =
-            lisp_throw( make_cons( c_string_to_lisp_string
+            throw_exception( make_cons( c_string_to_lisp_string
                                    ( "Shouldn't happen: bad arg to add_ratio_ratio" ),
                                    make_cons( arg1,
                                               make_cons( arg2, NIL ) ) ),
-                        frame );
+                         frame_pointer );
     }
 
 #ifdef DEBUG
@@ -171,26 +172,26 @@ struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
  * the intger indicated by `intarg` and the ratio indicated by
  * `ratarg`. If you pass other types, this is going to break horribly.
  */
-struct cons_pointer add_integer_ratio( struct stack_frame *frame,
+struct cons_pointer add_integer_ratio( struct cons_pointer frame_pointer,
                                        struct cons_pointer intarg,
                                        struct cons_pointer ratarg ) {
     struct cons_pointer result;
 
     if ( integerp( intarg ) && ratiop( ratarg ) ) {
         struct cons_pointer one = make_integer( 1 ),
-            ratio = make_ratio( frame, intarg, one );
+            ratio = make_ratio( frame_pointer, intarg, one );
 
-        result = add_ratio_ratio( frame, ratio, ratarg );
+        result = add_ratio_ratio(  frame_pointer, ratio, ratarg );
 
         dec_ref( one );
         dec_ref( ratio );
     } else {
         result =
-            lisp_throw( make_cons( c_string_to_lisp_string
+            throw_exception( make_cons( c_string_to_lisp_string
                                    ( "Shouldn't happen: bad arg to add_integer_ratio" ),
                                    make_cons( intarg,
                                               make_cons( ratarg, NIL ) ) ),
-                        frame );
+                        frame_pointer );
     }
 
     return result;
@@ -201,15 +202,15 @@ struct cons_pointer add_integer_ratio( struct stack_frame *frame,
  * indicated by `arg1` divided by the ratio indicated by `arg2`. If either
  * of these aren't RTIO cells, something horrid will happen and it is YOUR FAULT.
  */
-struct cons_pointer divide_ratio_ratio( struct stack_frame *frame,
+struct cons_pointer divide_ratio_ratio( struct cons_pointer frame_pointer,
                                         struct cons_pointer arg1,
                                         struct cons_pointer arg2 ) {
-    struct cons_pointer i = make_ratio( frame,
+    struct cons_pointer i = make_ratio(  frame_pointer,
                                         pointer2cell( arg2 ).payload.ratio.
                                         divisor,
                                         pointer2cell( arg2 ).payload.ratio.
                                         dividend ), result =
-        multiply_ratio_ratio( frame, arg1, i );
+        multiply_ratio_ratio(  frame_pointer, arg1, i );
 
     dec_ref( i );
 
@@ -221,9 +222,7 @@ struct cons_pointer divide_ratio_ratio( struct stack_frame *frame,
  * the ratios indicated by `arg1` and `arg2`. If you pass non-ratios,
  * this is going to break horribly.
  */
-struct cons_pointer multiply_ratio_ratio( struct
-                                          stack_frame
-                                          *frame, struct
+struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, struct
                                           cons_pointer arg1, struct
                                           cons_pointer arg2 ) {
     struct cons_pointer result;
@@ -249,18 +248,18 @@ struct cons_pointer multiply_ratio_ratio( struct
             ddrv = dd1v * dd2v, drrv = dr1v * dr2v;
 
         struct cons_pointer unsimplified =
-            make_ratio( frame, make_integer( ddrv ),
+            make_ratio(  frame_pointer, make_integer( ddrv ),
                         make_integer( drrv ) );
-        result = simplify_ratio( frame, unsimplified );
+        result = simplify_ratio( frame_pointer, unsimplified );
 
         if ( !eq( unsimplified, result ) ) {
             dec_ref( unsimplified );
         }
     } else {
         result =
-            lisp_throw( c_string_to_lisp_string
+            throw_exception( c_string_to_lisp_string
                         ( "Shouldn't happen: bad arg to multiply_ratio_ratio" ),
-                        frame );
+                         frame_pointer );
     }
 
     return result;
@@ -271,23 +270,23 @@ struct cons_pointer multiply_ratio_ratio( struct
  * the intger indicated by `intarg` and the ratio indicated by
  * `ratarg`. If you pass other types, this is going to break horribly.
  */
-struct cons_pointer multiply_integer_ratio( struct stack_frame *frame,
+struct cons_pointer multiply_integer_ratio( struct cons_pointer frame_pointer,
                                             struct cons_pointer intarg,
                                             struct cons_pointer ratarg ) {
     struct cons_pointer result;
 
     if ( integerp( intarg ) && ratiop( ratarg ) ) {
         struct cons_pointer one = make_integer( 1 ),
-            ratio = make_ratio( frame, intarg, one );
-        result = multiply_ratio_ratio( frame, ratio, ratarg );
+            ratio = make_ratio( frame_pointer, intarg, one );
+        result = multiply_ratio_ratio(  frame_pointer, ratio, ratarg );
 
         dec_ref( one );
         dec_ref( ratio );
     } else {
         result =
-            lisp_throw( c_string_to_lisp_string
+            throw_exception( c_string_to_lisp_string
                         ( "Shouldn't happen: bad arg to multiply_integer_ratio" ),
-                        frame );
+                         frame_pointer );
     }
 
     return result;
@@ -299,11 +298,11 @@ struct cons_pointer multiply_integer_ratio( struct stack_frame *frame,
  * the ratios indicated by `arg1` and `arg2`. If you pass non-ratios,
  * this is going to break horribly.
  */
-struct cons_pointer subtract_ratio_ratio( struct stack_frame *frame,
+struct cons_pointer subtract_ratio_ratio( struct cons_pointer frame_pointer,
                                           struct cons_pointer arg1,
                                           struct cons_pointer arg2 ) {
-    struct cons_pointer i = inverse( frame, arg2 ),
-        result = add_ratio_ratio( frame, arg1, i );
+    struct cons_pointer i = inverse( frame_pointer, arg2 ),
+        result = add_ratio_ratio(  frame_pointer, arg1, i );
 
     dec_ref( i );
 
@@ -315,7 +314,7 @@ struct cons_pointer subtract_ratio_ratio( struct stack_frame *frame,
  * Construct a ratio frame from these two pointers, expected to be integers
  * or (later) bignums, in the context of this stack_frame.
  */
-struct cons_pointer make_ratio( struct stack_frame *frame,
+struct cons_pointer make_ratio( struct cons_pointer frame_pointer,
                                 struct cons_pointer dividend,
                                 struct cons_pointer divisor ) {
     struct cons_pointer result;
@@ -328,9 +327,9 @@ struct cons_pointer make_ratio( struct stack_frame *frame,
         cell->payload.ratio.divisor = divisor;
     } else {
         result =
-            lisp_throw( c_string_to_lisp_string
+            throw_exception( c_string_to_lisp_string
                         ( "Dividend and divisor of a ratio must be integers" ),
-                        frame );
+                         frame_pointer );
     }
 #ifdef DEBUG
     dump_object( stderr, result );
diff --git a/src/arith/ratio.h b/src/arith/ratio.h
index c4e5548..feb8925 100644
--- a/src/arith/ratio.h
+++ b/src/arith/ratio.h
@@ -11,36 +11,34 @@
 #ifndef __ratio_h
 #define __ratio_h
 
-struct cons_pointer simplify_ratio( struct stack_frame *frame,
+struct cons_pointer simplify_ratio( struct cons_pointer frame_pointer,
                                     struct cons_pointer arg );
 
-struct cons_pointer add_ratio_ratio( struct stack_frame *frame,
+struct cons_pointer add_ratio_ratio(  struct cons_pointer frame_pointer,
                                      struct cons_pointer arg1,
                                      struct cons_pointer arg2 );
 
-struct cons_pointer add_integer_ratio( struct stack_frame *frame,
+struct cons_pointer add_integer_ratio(  struct cons_pointer frame_pointer,
                                        struct cons_pointer intarg,
                                        struct cons_pointer ratarg );
 
-struct cons_pointer divide_ratio_ratio( struct stack_frame *frame,
+struct cons_pointer divide_ratio_ratio(  struct cons_pointer frame_pointer,
                                         struct cons_pointer arg1,
                                         struct cons_pointer arg2 );
 
-struct cons_pointer multiply_ratio_ratio( struct
-                                          stack_frame
-                                          *frame, struct
+struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, struct
                                           cons_pointer arg1, struct
                                           cons_pointer arg2 );
 
-struct cons_pointer multiply_integer_ratio( struct stack_frame *frame,
+struct cons_pointer multiply_integer_ratio(  struct cons_pointer frame_pointer,
                                             struct cons_pointer intarg,
                                             struct cons_pointer ratarg );
 
-struct cons_pointer subtract_ratio_ratio( struct stack_frame *frame,
+struct cons_pointer subtract_ratio_ratio(  struct cons_pointer frame_pointer,
                                           struct cons_pointer arg1,
                                           struct cons_pointer arg2 );
 
-struct cons_pointer make_ratio( struct stack_frame *frame,
+struct cons_pointer make_ratio( struct cons_pointer frame_pointer,
                                 struct cons_pointer dividend,
                                 struct cons_pointer divisor );
 
diff --git a/src/init.c b/src/init.c
index 9716365..48516f6 100644
--- a/src/init.c
+++ b/src/init.c
@@ -90,6 +90,7 @@ int main( int argc, char *argv[] ) {
     bind_function( "eq", &lisp_eq );
     bind_function( "equal", &lisp_equal );
     bind_function( "eval", &lisp_eval );
+    bind_function( "exception", &lisp_exception );
     bind_function( "multiply", &lisp_multiply );
     bind_function( "read", &lisp_read );
     bind_function( "oblist", &lisp_oblist );
@@ -98,6 +99,7 @@ int main( int argc, char *argv[] ) {
     bind_function( "reverse", &lisp_reverse );
     bind_function( "set", &lisp_set );
     bind_function( "subtract", &lisp_subtract );
+    bind_function( "throw", &lisp_exception );
     bind_function( "type", &lisp_type );
 
     bind_function( "+", &lisp_add );
diff --git a/src/memory/consspaceobject.c b/src/memory/consspaceobject.c
index 39f464a..75a5257 100644
--- a/src/memory/consspaceobject.c
+++ b/src/memory/consspaceobject.c
@@ -63,98 +63,6 @@ void dec_ref( struct cons_pointer pointer ) {
     }
 }
 
-void dump_string_cell( FILE * output, wchar_t *prefix,
-                       struct cons_pointer pointer ) {
-    struct cons_space_object cell = pointer2cell( pointer );
-    if ( cell.payload.string.character == 0 ) {
-        fwprintf( output,
-                  L"\t\t%ls cell: termination; next at page %d offset %d, count %u\n",
-                  prefix,
-                  cell.payload.string.cdr.page, cell.payload.string.cdr.offset,
-                  cell.count );
-    } else {
-        fwprintf( output,
-                  L"\t\t%ls cell: character '%lc' (%d) next at page %d offset %d, count %u\n",
-                  prefix,
-                  ( wint_t ) cell.payload.string.character,
-                  cell.payload.string.character,
-                  cell.payload.string.cdr.page,
-                  cell.payload.string.cdr.offset, cell.count );
-        fwprintf( output, L"\t\t value: " );
-        print( output, pointer );
-        fwprintf( output, L"\n" );
-    }
-}
-
-/**
- * dump the object at this cons_pointer to this output stream.
- */
-void dump_object( FILE * output, struct cons_pointer pointer ) {
-    struct cons_space_object cell = pointer2cell( pointer );
-    fwprintf( output,
-              L"\t%c%c%c%c (%d) at page %d, offset %d count %u\n",
-              cell.tag.bytes[0],
-              cell.tag.bytes[1],
-              cell.tag.bytes[2],
-              cell.tag.bytes[3],
-              cell.tag.value, pointer.page, pointer.offset, cell.count );
-
-    switch ( cell.tag.value ) {
-        case CONSTV:
-            fwprintf( output,
-                      L"\t\tCons cell: car at page %d offset %d, cdr at page %d offset %d, count %u\n",
-                      cell.payload.cons.car.page,
-                      cell.payload.cons.car.offset,
-                      cell.payload.cons.cdr.page,
-                      cell.payload.cons.cdr.offset, cell.count );
-            break;
-        case EXCEPTIONTV:
-            fwprintf( output, L"\t\tException cell: " );
-            print( output, cell.payload.exception.message );
-            fwprintf( output, L"\n" );
-            for ( struct stack_frame * frame = cell.payload.exception.frame;
-                  frame != NULL; frame = frame->previous ) {
-                dump_frame( output, frame );
-            }
-            break;
-        case FREETV:
-            fwprintf( output, L"\t\tFree cell: next at page %d offset %d\n",
-                      cell.payload.cons.cdr.page,
-                      cell.payload.cons.cdr.offset );
-            break;
-        case INTEGERTV:
-            fwprintf( output,
-                      L"\t\tInteger cell: value %ld, count %u\n",
-                      cell.payload.integer.value, cell.count );
-            break;
-        case LAMBDATV:
-            fwprintf( output, L"\t\tLambda cell; args: " );
-            print( output, cell.payload.lambda.args );
-            fwprintf( output, L";\n\t\t\tbody: " );
-            print( output, cell.payload.lambda.body );
-            break;
-        case RATIOTV:
-            fwprintf( output,
-                      L"\t\tRational cell: value %ld/%ld, count %u\n",
-                      pointer2cell( cell.payload.ratio.dividend ).payload.
-                      integer.value,
-                      pointer2cell( cell.payload.ratio.divisor ).payload.
-                      integer.value, cell.count );
-            break;
-        case READTV:
-            fwprintf( output, L"\t\tInput stream\n" );
-        case REALTV:
-            fwprintf( output, L"\t\tReal cell: value %Lf, count %u\n",
-                      cell.payload.real.value, cell.count );
-            break;
-        case STRINGTV:
-            dump_string_cell( output, L"String", pointer );
-            break;
-        case SYMBOLTV:
-            dump_string_cell( output, L"Symbol", pointer );
-            break;
-    }
-}
 
 /**
  * Construct a cons cell from this pair of pointers.
@@ -178,20 +86,24 @@ struct cons_pointer make_cons( struct cons_pointer car,
 /**
  * Construct an exception cell.
  * @param message should be a lisp string describing the problem, but actually any cons pointer will do;
- * @param frame should be the frame in which the exception occurred.
+ * @param frame_pointer should be the pointer to the frame in which the exception occurred.
  */
 struct cons_pointer make_exception( struct cons_pointer message,
-                                    struct stack_frame *frame ) {
-    struct cons_pointer pointer = allocate_cell( EXCEPTIONTAG );
-    struct cons_space_object *cell = &pointer2cell( pointer );
+                                   struct cons_pointer frame_pointer ) {
+  struct cons_pointer result = NIL;
+  struct cons_pointer pointer = allocate_cell( EXCEPTIONTAG );
+  struct cons_space_object *cell = &pointer2cell( pointer );
 
-    inc_ref( pointer );         /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
+  inc_ref( pointer );         /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
 
-    inc_ref( message );
-    cell->payload.exception.message = message;
-    cell->payload.exception.frame = frame;
+  inc_ref( message );
+  inc_ref( frame_pointer);
+  cell->payload.exception.message = message;
+  cell->payload.exception.frame = frame_pointer;
 
-    return pointer;
+  result = pointer;
+
+  return result;
 }
 
 
@@ -200,7 +112,8 @@ struct cons_pointer make_exception( struct cons_pointer message,
  */
 struct cons_pointer
 make_function( struct cons_pointer src, struct cons_pointer ( *executable )
-                ( struct stack_frame *, struct cons_pointer ) ) {
+                ( struct stack_frame *,
+                                     struct cons_pointer, struct cons_pointer ) ) {
     struct cons_pointer pointer = allocate_cell( FUNCTIONTAG );
     struct cons_space_object *cell = &pointer2cell( pointer );
 
@@ -298,7 +211,8 @@ struct cons_pointer make_symbol( wint_t c, struct cons_pointer tail ) {
  */
 struct cons_pointer
 make_special( struct cons_pointer src, struct cons_pointer ( *executable )
-               ( struct stack_frame * frame, struct cons_pointer env ) ) {
+               ( struct stack_frame * frame,
+                                     struct cons_pointer, struct cons_pointer env ) ) {
     struct cons_pointer pointer = allocate_cell( SPECIALTAG );
     struct cons_space_object *cell = &pointer2cell( pointer );
 
diff --git a/src/memory/consspaceobject.h b/src/memory/consspaceobject.h
index 43bdfe0..b31a0bf 100644
--- a/src/memory/consspaceobject.h
+++ b/src/memory/consspaceobject.h
@@ -278,13 +278,14 @@ struct cons_pointer {
  * here to avoid circularity. TODO: refactor.
  */
 struct stack_frame {
-    struct stack_frame *previous; /* the previous frame */
+    struct cons_pointer previous; /* the previous frame */
     struct cons_pointer arg[args_in_frame];
     /*
      * first 8 arument bindings
      */
     struct cons_pointer more;   /* list of any further argument bindings */
     struct cons_pointer function; /* the function to be called */
+    int args;
 };
 
 /**
@@ -311,7 +312,7 @@ struct cons_payload {
  */
 struct exception_payload {
     struct cons_pointer message;
-    struct stack_frame *frame;
+    struct cons_pointer frame;
 };
 
 /**
@@ -326,6 +327,7 @@ struct exception_payload {
 struct function_payload {
     struct cons_pointer source;
     struct cons_pointer ( *executable ) ( struct stack_frame *,
+                                          struct cons_pointer,
                                           struct cons_pointer );
 };
 
@@ -379,13 +381,11 @@ struct real_payload {
  * its argument list) and a cons pointer (representing its environment) and a
  * stack frame (representing the previous stack frame) as arguments and returns
  * a cons pointer (representing its result).
- *
- * NOTE that this means that special forms do not appear on the lisp stack,
- * which may be confusing. TODO: think about this.
  */
 struct special_payload {
     struct cons_pointer source;
     struct cons_pointer ( *executable ) ( struct stack_frame *,
+                                          struct cons_pointer,
                                           struct cons_pointer );
 };
 
@@ -421,7 +421,8 @@ struct vectorp_payload {
                                  * tag. */
         uint32_t value;         /* the tag considered as a number */
     } tag;
-    uint64_t address;           /* the address of the actual vector space
+    struct vector_space_object * address;
+                                /* the address of the actual vector space
                                  * object (TODO: will change when I actually
                                  * implement vector space) */
 };
@@ -514,20 +515,11 @@ void inc_ref( struct cons_pointer pointer );
  */
 void dec_ref( struct cons_pointer pointer );
 
-/**
- * dump the object at this cons_pointer to this output stream.
- */
-void dump_object( FILE * output, struct cons_pointer pointer );
-
 struct cons_pointer make_cons( struct cons_pointer car,
                                struct cons_pointer cdr );
-/**
- * Construct an exception cell.
- * @param message should be a lisp string describing the problem, but actually any cons pointer will do;
- * @param frame should be the frame in which the exception occurred.
- */
+
 struct cons_pointer make_exception( struct cons_pointer message,
-                                    struct stack_frame *frame );
+                                    struct cons_pointer frame_pointer );
 
 /**
  * Construct a cell which points to an executable Lisp special form.
@@ -535,6 +527,7 @@ struct cons_pointer make_exception( struct cons_pointer message,
 struct cons_pointer make_function( struct cons_pointer src,
                                    struct cons_pointer ( *executable )
                                     ( struct stack_frame *,
+                                      struct cons_pointer,
                                       struct cons_pointer ) );
 
 /**
@@ -550,20 +543,13 @@ struct cons_pointer make_lambda( struct cons_pointer args,
 struct cons_pointer make_nlambda( struct cons_pointer args,
                                   struct cons_pointer body );
 
-/**
- * Construct a ratio frame from these two pointers, expected to be integers
- * or (later) bignums, in the context of this stack_frame.
- */
-struct cons_pointer make_ratio( struct stack_frame *frame,
-                                struct cons_pointer dividend,
-                                struct cons_pointer divisor );
-
 /**
  * Construct a cell which points to an executable Lisp special form.
  */
 struct cons_pointer make_special( struct cons_pointer src,
                                   struct cons_pointer ( *executable )
                                    ( struct stack_frame *,
+                                     struct cons_pointer,
                                      struct cons_pointer ) );
 
 /**
diff --git a/src/memory/dump.c b/src/memory/dump.c
new file mode 100644
index 0000000..5306801
--- /dev/null
+++ b/src/memory/dump.c
@@ -0,0 +1,120 @@
+/*
+ *  dump.c
+ *
+ *  Dump representations of both cons space and vector space objects.
+ *
+ *
+ *  (c) 2018 Simon Brooke <simon@journeyman.cc>
+ *  Licensed under GPL version 2.0, or, at your option, any later version.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+/*
+ * wide characters
+ */
+#include <wchar.h>
+#include <wctype.h>
+
+#include "conspage.h"
+#include "consspaceobject.h"
+#include "print.h"
+#include "stack.h"
+#include "vectorspace.h"
+
+
+void dump_string_cell( FILE * output, wchar_t *prefix,
+                       struct cons_pointer pointer ) {
+    struct cons_space_object cell = pointer2cell( pointer );
+    if ( cell.payload.string.character == 0 ) {
+        fwprintf( output,
+                  L"\t\t%ls cell: termination; next at page %d offset %d, count %u\n",
+                  prefix,
+                  cell.payload.string.cdr.page, cell.payload.string.cdr.offset,
+                  cell.count );
+    } else {
+        fwprintf( output,
+                  L"\t\t%ls cell: character '%lc' (%d) next at page %d offset %d, count %u\n",
+                  prefix,
+                  ( wint_t ) cell.payload.string.character,
+                  cell.payload.string.character,
+                  cell.payload.string.cdr.page,
+                  cell.payload.string.cdr.offset, cell.count );
+        fwprintf( output, L"\t\t value: " );
+        print( output, pointer );
+        fwprintf( output, L"\n" );
+    }
+}
+
+/**
+ * dump the object at this cons_pointer to this output stream.
+ */
+void dump_object( FILE * output, struct cons_pointer pointer ) {
+    struct cons_space_object cell = pointer2cell( pointer );
+    fwprintf( output,
+              L"\t%c%c%c%c (%d) at page %d, offset %d count %u\n",
+              cell.tag.bytes[0],
+              cell.tag.bytes[1],
+              cell.tag.bytes[2],
+              cell.tag.bytes[3],
+              cell.tag.value, pointer.page, pointer.offset, cell.count );
+
+    switch ( cell.tag.value ) {
+        case CONSTV:
+            fwprintf( output,
+                      L"\t\tCons cell: car at page %d offset %d, cdr at page %d offset %d, count %u\n",
+                      cell.payload.cons.car.page,
+                      cell.payload.cons.car.offset,
+                      cell.payload.cons.cdr.page,
+                      cell.payload.cons.cdr.offset, cell.count );
+            break;
+        case EXCEPTIONTV:
+            fwprintf( output, L"\t\tException cell: " );
+            dump_stack_trace( output, pointer);
+            break;
+        case FREETV:
+            fwprintf( output, L"\t\tFree cell: next at page %d offset %d\n",
+                      cell.payload.cons.cdr.page,
+                      cell.payload.cons.cdr.offset );
+            break;
+        case INTEGERTV:
+            fwprintf( output,
+                      L"\t\tInteger cell: value %ld, count %u\n",
+                      cell.payload.integer.value, cell.count );
+            break;
+        case LAMBDATV:
+            fwprintf( output, L"\t\tLambda cell; args: " );
+            print( output, cell.payload.lambda.args );
+            fwprintf( output, L";\n\t\t\tbody: " );
+            print( output, cell.payload.lambda.body );
+            break;
+        case RATIOTV:
+            fwprintf( output,
+                      L"\t\tRational cell: value %ld/%ld, count %u\n",
+                      pointer2cell( cell.payload.ratio.dividend ).payload.
+                      integer.value,
+                      pointer2cell( cell.payload.ratio.divisor ).payload.
+                      integer.value, cell.count );
+            break;
+        case READTV:
+            fwprintf( output, L"\t\tInput stream\n" );
+        case REALTV:
+            fwprintf( output, L"\t\tReal cell: value %Lf, count %u\n",
+                      cell.payload.real.value, cell.count );
+            break;
+        case STRINGTV:
+            dump_string_cell( output, L"String", pointer );
+            break;
+        case SYMBOLTV:
+            dump_string_cell( output, L"Symbol", pointer );
+            break;
+      case VECTORPOINTTV: {
+        struct vector_space_object * vso = cell.payload.vectorp.address;
+      fwprintf( output, L"\t\tVector space object of type %4.4s, payload size %d bytes\n",
+                vso->header.tag, vso->header.size);
+      }
+      break;
+    }
+}
diff --git a/src/memory/dump.h b/src/memory/dump.h
new file mode 100644
index 0000000..e49f453
--- /dev/null
+++ b/src/memory/dump.h
@@ -0,0 +1,29 @@
+/**
+ *  dump.h
+ *
+ *  Dump representations of both cons space and vector space objects.
+ *
+ *  (c) 2018 Simon Brooke <simon@journeyman.cc>
+ *  Licensed under GPL version 2.0, or, at your option, any later version.
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+/*
+ * wide characters
+ */
+#include <wchar.h>
+#include <wctype.h>
+
+#ifndef __dump_h
+#define __dump_h
+
+
+/**
+ * dump the object at this cons_pointer to this output stream.
+ */
+void dump_object( FILE * output, struct cons_pointer pointer );
+
+
+#endif
diff --git a/src/memory/stack.c b/src/memory/stack.c
index 1bb8b1b..8fe268e 100644
--- a/src/memory/stack.c
+++ b/src/memory/stack.c
@@ -11,9 +11,6 @@
  * with freelists to a more general 'equal sized object pages', so that
  * allocating/freeing stack frames can be more efficient.
  *
- * Stack frames are not yet a first class object; they have no VECP pointer
- * in cons space.
- *
  * (c) 2017 Simon Brooke <simon@journeyman.cc>
  * Licensed under GPL version 2.0, or, at your option, any later version.
  */
@@ -25,87 +22,128 @@
 #include "lispops.h"
 #include "print.h"
 #include "stack.h"
+#include "vectorspace.h"
+
+/**
+ * get the actual stackframe object from this `pointer`, or NULL if
+ * `pointer` is not a stackframe pointer.
+ */
+struct stack_frame * get_stack_frame(struct cons_pointer pointer) {
+  struct stack_frame * result = NULL;
+  struct vector_space_object * vso =
+    pointer2cell(pointer).payload.vectorp.address;
+
+  if (vectorpointp(pointer) && stackframep(vso))
+  {
+    result = (struct stack_frame *) &(vso->payload);
+  }
+
+  return result;
+}
 
 /**
  * Make an empty stack frame, and return it.
  * @param previous the current top-of-stack;
  * @param env the environment in which evaluation happens.
- * @return the new frame.
+ * @return the new frame, or NULL if memory is exhausted.
  */
-struct stack_frame *make_empty_frame( struct stack_frame *previous,
-                                      struct cons_pointer env ) {
-    struct stack_frame *result = malloc( sizeof( struct stack_frame ) );
+struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
+  struct cons_pointer result = make_vso(STACKFRAMETAG, sizeof(struct stack_frame));
+  if (!nilp(result)) {
+    struct stack_frame *frame = get_stack_frame(result);
     /*
      * TODO: later, pop a frame off a free-list of stack frames
      */
 
-    result->previous = previous;
+    frame->previous = previous;
+    inc_ref(previous);
 
     /*
      * clearing the frame with memset would probably be slightly quicker, but
      * this is clear.
      */
-    result->more = NIL;
-    result->function = NIL;
+    frame->more = NIL;
+    frame->function = NIL;
+    frame->args = 0;
 
     for ( int i = 0; i < args_in_frame; i++ ) {
-        set_reg( result, i, NIL );
+        set_reg( frame, i, NIL );
     }
+  }
 
     return result;
 }
 
-
 /**
  * Allocate a new stack frame with its previous pointer set to this value,
  * its arguments set up from these args, evaluated in this env.
  * @param previous the current top-of-stack;
  * @args the arguments to load into this frame;
  * @param env the environment in which evaluation happens.
- * @return the new frame.
+ * @return the new frame, or an exception if one occurred while building it.
  */
-struct stack_frame *make_stack_frame( struct stack_frame *previous,
-                                      struct cons_pointer args,
-                                      struct cons_pointer env,
-                                      struct cons_pointer *exception ) {
-    struct stack_frame *result = make_empty_frame( previous, env );
+struct cons_pointer make_stack_frame( struct cons_pointer previous,
+                                     struct cons_pointer args,
+                                     struct cons_pointer env ) {
+  struct cons_pointer result = make_empty_frame( previous );
 
-    for ( int i = 0; i < args_in_frame && consp( args ); i++ ) {
-        /* iterate down the arg list filling in the arg slots in the
+  if (nilp(result))
+  {
+    /* i.e. out of memory */
+    result = make_exception(c_string_to_lisp_string( "Memory exhausted."), previous);
+  } else {
+    struct stack_frame * frame = get_stack_frame(result);
+
+    for ( frame->args = 0; frame->args < args_in_frame && consp( args ); frame->args++ ) {
+      /* iterate down the arg list filling in the arg slots in the
          * frame. When there are no more slots, if there are still args,
          * stash them on more */
-        struct cons_space_object cell = pointer2cell( args );
+      struct cons_space_object cell = pointer2cell( args );
 
-        /*
+      /*
          * TODO: if we were running on real massively parallel hardware,
          * each arg except the first should be handed off to another
          * processor to be evaled in parallel; but see notes here:
          * https://github.com/simon-brooke/post-scarcity/wiki/parallelism
          */
-        struct stack_frame *arg_frame = make_empty_frame( result, env );
+      struct cons_pointer arg_frame_pointer = make_empty_frame( result);
+      inc_ref(arg_frame_pointer);
+
+      if(nilp(arg_frame_pointer)) {
+        result = make_exception(c_string_to_lisp_string( "Memory exhausted."), previous);
+        break;
+      } else {
+        struct stack_frame *arg_frame = get_stack_frame( arg_frame_pointer );
         set_reg( arg_frame, 0, cell.payload.cons.car );
 
-        struct cons_pointer val = lisp_eval( arg_frame, env );
+        struct cons_pointer val = lisp_eval( arg_frame, arg_frame_pointer, env );
         if ( exceptionp( val ) ) {
-            exception = &val;
-            break;
+          result = val;
+          break;
         } else {
-            set_reg( result, i, val );
+          set_reg( frame, frame->args, val );
         }
 
-        free_stack_frame( arg_frame );
+        dec_ref(arg_frame_pointer);
 
         args = cell.payload.cons.cdr;
+      }
     }
-    if ( consp( args ) ) {
+    if (!exceptionp(result)) {
+      if ( consp( args ) ) {
         /* if we still have args, eval them and stick the values on `more` */
-        struct cons_pointer more = eval_forms( previous, args, env );
-        result->more = more;
+        struct cons_pointer more = eval_forms( get_stack_frame(previous), previous, args, env );
+        frame->more = more;
         inc_ref( more );
-    }
+      }
 
-    dump_frame( stderr, result );
-    return result;
+#ifdef DEBUG
+      dump_frame( stderr, result );
+#endif
+    }
+  }
+
+  return result;
 }
 
 /**
@@ -116,25 +154,39 @@ struct stack_frame *make_stack_frame( struct stack_frame *previous,
  * @param env the execution environment;
  * @return a new special frame.
  */
-struct stack_frame *make_special_frame( struct stack_frame *previous,
+struct cons_pointer make_special_frame( struct cons_pointer previous,
                                         struct cons_pointer args,
                                         struct cons_pointer env ) {
-    struct stack_frame *result = make_empty_frame( previous, env );
+  struct cons_pointer result = make_empty_frame( previous );
 
-    for ( int i = 0; i < args_in_frame && !nilp( args ); i++ ) {
+  if (nilp(result))
+  {
+    /* i.e. out of memory */
+    result = make_exception(c_string_to_lisp_string( "Memory exhausted."), previous);
+  } else {
+    struct stack_frame * frame = get_stack_frame(result);
+
+    for ( frame->args = 0; frame->args < args_in_frame && !nilp( args ); frame->args++ ) {
         /* iterate down the arg list filling in the arg slots in the
          * frame. When there are no more slots, if there are still args,
          * stash them on more */
         struct cons_space_object cell = pointer2cell( args );
 
-        set_reg( result, i, cell.payload.cons.car );
+        set_reg( frame, frame->args, cell.payload.cons.car );
 
         args = cell.payload.cons.cdr;
     }
-    if ( consp( args ) ) {
-        result->more = args;
+    if (!exceptionp(result)) {
+      if ( consp( args ) ) {
+        frame->more = args;
         inc_ref( args );
+      }
+
+#ifdef DEBUG
+      dump_frame( stderr, result );
+#endif
     }
+  }
 
     return result;
 }
@@ -160,26 +212,41 @@ void free_stack_frame( struct stack_frame *frame ) {
 /**
  * Dump a stackframe to this stream for debugging
  * @param output the stream
- * @param frame the frame
+ * @param frame_pointer the pointer to the frame
  */
-void dump_frame( FILE * output, struct stack_frame *frame ) {
-    fputws( L"Dumping stack frame\n", output );
-    for ( int arg = 0; arg < args_in_frame; arg++ ) {
-        struct cons_space_object cell = pointer2cell( frame->arg[arg] );
+void dump_frame( FILE * output, struct cons_pointer frame_pointer ) {
+  struct stack_frame *frame = get_stack_frame(frame_pointer);
 
-        fwprintf( output, L"Arg %d:\t%c%c%c%c\tcount: %10u\tvalue: ", arg,
-                  cell.tag.bytes[0],
-                  cell.tag.bytes[1], cell.tag.bytes[2], cell.tag.bytes[3],
-                  cell.count );
+  if (frame != NULL) {
+    for ( int arg = 0; arg < frame->args; arg++ ) {
+      struct cons_space_object cell = pointer2cell( frame->arg[arg] );
 
-        print( output, frame->arg[arg] );
-        fputws( L"\n", output );
+      fwprintf( output, L"Arg %d:\t%c%c%c%c\tcount: %10u\tvalue: ", arg,
+               cell.tag.bytes[0],
+               cell.tag.bytes[1], cell.tag.bytes[2], cell.tag.bytes[3],
+               cell.count );
+
+      print( output, frame->arg[arg] );
+      fputws( L"\n", output );
     }
     fputws( L"More: \t", output );
     print( output, frame->more );
     fputws( L"\n", output );
+  }
 }
 
+void dump_stack_trace(FILE * output, struct cons_pointer pointer) {
+  if (exceptionp(pointer)) {
+    print( output, pointer2cell(pointer).payload.exception.message );
+    fwprintf( output, L"\n" );
+    dump_stack_trace(output, pointer2cell(pointer).payload.exception.frame);
+  } else {
+    while (vectorpointp(pointer) && stackframep(pointer_to_vso(pointer))) {
+      dump_frame( output, pointer);
+      pointer = get_stack_frame(pointer)->previous;
+    }
+  }
+}
 
 /**
  * Fetch a pointer to the value of the local variable at this index.
diff --git a/src/memory/stack.h b/src/memory/stack.h
index d708b39..df76849 100644
--- a/src/memory/stack.h
+++ b/src/memory/stack.h
@@ -24,46 +24,40 @@
 #ifndef __stack_h
 #define __stack_h
 
+/**
+ * macros for the tag of a stack frame.
+ */
+#define STACKFRAMETAG "STAK"
+#define STACKFRAMETV 1262572627
+
+/**
+ * is this vector-space object a stack frame?
+ */
+#define stackframep(vso)(vso->header.tag.value == STACKFRAMETV)
+
 /**
  * set a register in a stack frame. Alwaye use this macro to do so,
  • because that way we can be sure the inc_ref happens!
  */
 #define set_reg(frame,register,value)frame->arg[register]=value; inc_ref(value)
 
+struct stack_frame * get_stack_frame(struct cons_pointer pointer);
 
-/**
- * Make an empty stack frame, and return it.
- * @param previous the current top-of-stack;
- * @param env the environment in which evaluation happens.
- * @return the new frame.
- */
-struct stack_frame *make_empty_frame( struct stack_frame *previous,
-                                      struct cons_pointer env );
+struct cons_pointer make_empty_frame( struct cons_pointer previous );
+
+struct cons_pointer make_stack_frame( struct cons_pointer previous,
+                                     struct cons_pointer args,
+                                     struct cons_pointer env );
 
-struct stack_frame *make_stack_frame( struct stack_frame *previous,
-                                      struct cons_pointer args,
-                                      struct cons_pointer env,
-                                      struct cons_pointer *exception );
 void free_stack_frame( struct stack_frame *frame );
 
-/**
- * Dump a stackframe to this stream for debugging
- * @param output the stream
- * @param frame the frame
- */
-void dump_frame( FILE * output, struct stack_frame *frame );
+void dump_frame( FILE * output, struct cons_pointer pointer );
+
+void dump_stack_trace(FILE * output, struct cons_pointer frame_pointer);
 
 struct cons_pointer fetch_arg( struct stack_frame *frame, unsigned int n );
 
-/**
- * A 'special' frame is exactly like a normal stack frame except that the
- * arguments are unevaluated.
- * @param previous the previous stack frame;
- * @param args a list of the arguments to be stored in this stack frame;
- * @param env the execution environment;
- * @return a new special frame.
- */
-struct stack_frame *make_special_frame( struct stack_frame *previous,
+struct cons_pointer make_special_frame( struct cons_pointer previous,
                                         struct cons_pointer args,
                                         struct cons_pointer env );
 
diff --git a/src/memory/vectorspace.c b/src/memory/vectorspace.c
index 4b18b96..c0b6f8d 100644
--- a/src/memory/vectorspace.c
+++ b/src/memory/vectorspace.c
@@ -8,6 +8,7 @@
  *  Licensed under GPL version 2.0, or, at your option, any later version.
  */
 
+#include <math.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <string.h>
@@ -29,7 +30,7 @@
  * NOTE that `tag` should be the vector-space tag of the particular type of
  * vector-space object, NOT `VECTORPOINTTAG`.
  */
-struct cons_pointer make_vec_pointer( char *tag, uint64_t address ) {
+struct cons_pointer make_vec_pointer( char * tag, struct vector_space_object * address ) {
     struct cons_pointer pointer = allocate_cell( VECTORPOINTTAG );
     struct cons_space_object cell = pointer2cell( pointer );
 
@@ -44,26 +45,33 @@ struct cons_pointer make_vec_pointer( char *tag, uint64_t address ) {
  * and return a `cons_pointer` which points to an object whigh points to it.
  * NOTE that `tag` should be the vector-space tag of the particular type of
  * vector-space object, NOT `VECTORPOINTTAG`.
+ * Returns NIL if the vector could not be allocated due to memory exhaustion.
  */
-struct cons_pointer make_vso( char *tag, int64_t payload_size ) {
+struct cons_pointer make_vso( char *tag, uint64_t payload_size ) {
     struct cons_pointer result = NIL;
     int64_t total_size = sizeof( struct vector_space_header ) + payload_size;
 
-    struct vector_space_header *vso = malloc( total_size );
+    /* Pad size to 64 bit words. This is intended to promote access efficiancy
+     * on 64 bit machines but may just be voodoo coding */
+    uint64_t padded = ceil((total_size * 8.0) / 8.0);
+    struct vector_space_object *vso = malloc( padded );
 
     if ( vso != NULL ) {
-        strncpy( &vso->tag.bytes[0], tag, TAGLENGTH );
-        vso->vecp = make_vec_pointer( tag, ( uint64_t ) vso );
-        vso->size = payload_size;
+        strncpy( &vso->header.tag.bytes[0], tag, TAGLENGTH );
+        vso->header.vecp = make_vec_pointer( tag, vso );
+        vso->header.size = payload_size;
 
 #ifdef DEBUG
         fwprintf( stderr,
-                  L"Allocated vector-space object of type %s, total size %ld, payload size %ld\n",
+                  L"Allocated vector-space object of type %4.4s, total size %ld, payload size %ld\n",
                   tag, total_size, payload_size );
+  if (padded != total_size){
+    fwprintf(stderr, L"\t\tPadded from %d to %d\n",
+            total_size, padded);
+  }
 #endif
 
-        result = vso->vecp;
+        result = vso->header.vecp;
     }
-
     return result;
 }
diff --git a/src/memory/vectorspace.h b/src/memory/vectorspace.h
index 07a0b91..83fa74c 100644
--- a/src/memory/vectorspace.h
+++ b/src/memory/vectorspace.h
@@ -34,20 +34,16 @@
 #define NAMESPACETAG "NMSP"
 #define NAMESPACETV 0
 
-/*
- * a stack frame.
- */
-#define STACKFRAMETAG "STAK"
-#define STACKFRAMETV
 /*
  * a vector of cons pointers.
  */
 #define VECTORTAG "VECT"
 #define VECTORTV 0
 
-#define pointer_to_vso(pointer)(vectorpointp(pointer)? pointer2cell(pointer).payload.vectorp.address : 0)
+#define pointer_to_vso(pointer)((vectorpointp(pointer)? pointer2cell(pointer).payload.vectorp.address : NULL))
+#define vso_get_vecp(vso)((vso->header.vecp))
 
-struct cons_pointer make_vso( char *tag, int64_t payload_size );
+struct cons_pointer make_vso( char *tag, uint64_t payload_size );
 
 struct vector_space_header {
     union {
@@ -62,8 +58,10 @@ struct vector_space_header {
     struct cons_pointer vecp;   /* back pointer to the vector pointer
                                  * which uniquely points to this vso */
     uint64_t size;              /* the size of my payload, in bytes */
-    char mark;                  /* mark bit for marking/sweeping the
-                                 * heap (not in this version) */
+};
+
+struct vector_space_object {
+  struct vector_space_header header;
     char payload;               /* we'll malloc `size` bytes for payload,
                                  * `payload` is just the first of these.
                                  * TODO: this is almost certainly not
diff --git a/src/ops/lispops.c b/src/ops/lispops.c
index 9b12faa..825222f 100644
--- a/src/ops/lispops.c
+++ b/src/ops/lispops.c
@@ -80,6 +80,7 @@ struct cons_pointer c_cdr( struct cons_pointer arg ) {
  * @return the result of evaluating the form.
  */
 struct cons_pointer eval_form( struct stack_frame *parent,
+                               struct cons_pointer parent_pointer,
                                struct cons_pointer form,
                                struct cons_pointer env ) {
     fputws( L"eval_form: ", stderr );
@@ -87,15 +88,19 @@ struct cons_pointer eval_form( struct stack_frame *parent,
     fputws( L"\n", stderr );
 
     struct cons_pointer result = NIL;
-    struct stack_frame *next = make_empty_frame( parent, env );
+    struct cons_pointer next_pointer = make_empty_frame( parent_pointer );
+    inc_ref( next_pointer);
+
+    struct stack_frame * next = get_stack_frame(next_pointer);
     set_reg( next, 0, form );
-    result = lisp_eval( next, env );
+
+    result = lisp_eval( next, next_pointer, env );
 
     if ( !exceptionp( result ) ) {
         /* if we're returning an exception, we should NOT free the
          * stack frame. Corollary is, when we free an exception, we
          * should free all the frames it's holding on to. */
-        free_stack_frame( next );
+        dec_ref(next_pointer);
     }
 
     return result;
@@ -106,12 +111,13 @@ struct cons_pointer eval_form( struct stack_frame *parent,
  * and this `env`, and return a list of their values. If the arg passed as
  * `list` is not in fact a list, return nil.
  */
-struct cons_pointer eval_forms( struct stack_frame *frame,
+struct cons_pointer eval_forms( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer list,
                                 struct cons_pointer env ) {
+  /* TODO: refactor. This runs up the C stack. */
     return consp( list ) ?
-        make_cons( eval_form( frame, c_car( list ), env ),
-                   eval_forms( frame, c_cdr( list ), env ) ) : NIL;
+        make_cons( eval_form( frame, frame_pointer, c_car( list ), env ),
+                   eval_forms( frame, frame_pointer, c_cdr( list ), env ) ) : NIL;
 }
 
 /**
@@ -120,7 +126,7 @@ struct cons_pointer eval_forms( struct stack_frame *frame,
  * (oblist)
  */
 struct cons_pointer
-lisp_oblist( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_oblist( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return oblist;
 }
 
@@ -153,7 +159,7 @@ struct cons_pointer compose_body( struct stack_frame *frame ) {
  * @param env the environment in which it is to be intepreted.
  */
 struct cons_pointer
-lisp_lambda( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_lambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return make_lambda( frame->arg[0], compose_body( frame ) );
 }
 
@@ -164,7 +170,7 @@ lisp_lambda( struct stack_frame *frame, struct cons_pointer env ) {
  * @param env the environment in which it is to be intepreted.
  */
 struct cons_pointer
-lisp_nlambda( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return make_nlambda( frame->arg[0], compose_body( frame ) );
 }
 
@@ -182,7 +188,7 @@ void log_binding( struct cons_pointer name, struct cons_pointer val ) {
  * Evaluate a lambda or nlambda expression.
  */
 struct cons_pointer
-eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
+eval_lambda( struct cons_space_object cell, struct stack_frame *frame, struct cons_pointer frame_pointer,
              struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     fwprintf( stderr, L"eval_lambda called\n" );
@@ -206,10 +212,11 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
     } else if ( symbolp( names ) ) {
         /* if `names` is a symbol, rather than a list of symbols,
          * then bind a list of the values of args to that symbol. */
+        /* TODO: eval all the things in frame->more */
         struct cons_pointer vals = frame->more;
 
         for ( int i = args_in_frame - 1; i >= 0; i-- ) {
-            struct cons_pointer val = eval_form( frame, frame->arg[i], env );
+            struct cons_pointer val = eval_form( frame, frame_pointer, frame->arg[i], env );
 
             if ( nilp( val ) && nilp( vals ) ) {  /* nothing */
             } else {
@@ -223,8 +230,10 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
     while ( !nilp( body ) ) {
         struct cons_pointer sexpr = c_car( body );
         body = c_cdr( body );
+#ifdef DEBUG
         fputws( L"In lambda: ", stderr );
-        result = eval_form( frame, sexpr, new_env );
+#endif
+        result = eval_form( frame, frame_pointer, sexpr, new_env );
     }
 
     return result;
@@ -239,17 +248,23 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
  * @return the result of evaluating the function with its arguments.
  */
 struct cons_pointer
-c_apply( struct stack_frame *frame, struct cons_pointer env ) {
+c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
-    struct stack_frame *fn_frame = make_empty_frame( frame, env );
+
+  /* construct a child frame and within it evaluate the first argument - the
+   * argument in the function position. */
+    struct cons_pointer fn_frame_pointer = make_empty_frame( frame_pointer );
+    inc_ref( fn_frame_pointer);
+    struct stack_frame *fn_frame = get_stack_frame(fn_frame_pointer);
+
     set_reg( fn_frame, 0, c_car( frame->arg[0] ) );
-    struct cons_pointer fn_pointer = lisp_eval( fn_frame, env );
+    struct cons_pointer fn_pointer = lisp_eval( fn_frame, fn_frame_pointer, env );
 
     if ( !exceptionp( result ) ) {
         /* if we're returning an exception, we should NOT free the
          * stack frame. Corollary is, when we free an exception, we
          * should free all the frames it's holding on to. */
-        free_stack_frame( fn_frame );
+        dec_ref(fn_frame_pointer);
     }
 
     struct cons_space_object fn_cell = pointer2cell( fn_pointer );
@@ -263,67 +278,66 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
         case FUNCTIONTV:
             {
                 struct cons_pointer exep = NIL;
-                struct stack_frame *next =
-                    make_stack_frame( frame, args, env, &exep );
-                result = ( *fn_cell.payload.special.executable ) ( next, env );
-                if ( exceptionp( exep ) ) {
-                    /* if we're returning an exception, we should NOT free the
-                     * stack frame. Corollary is, when we free an exception, we
-                     * should free all the frames it's holding on to. */
-                    result = exep;
+                struct cons_pointer next_pointer =
+                    make_stack_frame( frame_pointer, args, env );
+              inc_ref(next_pointer);
+                if ( exceptionp( next_pointer ) ) {
+                    result = next_pointer;
                 } else {
-                    free_stack_frame( next );
+                struct stack_frame *next = get_stack_frame(next_pointer);
+
+                result = ( *fn_cell.payload.function.executable ) ( next, next_pointer, env );
+                  dec_ref(next_pointer);
                 }
             }
             break;
         case LAMBDATV:
             {
                 struct cons_pointer exep = NIL;
-                struct stack_frame *next =
-                    make_stack_frame( frame, args, env, &exep );
-#ifdef DEBUG
-                fputws( L"Stack frame for lambda\n", stderr );
-                dump_frame( stderr, next );
-#endif
-                result = eval_lambda( fn_cell, next, env );
-                if ( exceptionp( result ) ) {
-                    /* if we're returning an exception, we should NOT free the
-                     * stack frame. Corollary is, when we free an exception, we
-                     * should free all the frames it's holding on to. */
-                    result = exep;
+                struct cons_pointer next_pointer =
+                    make_stack_frame( frame_pointer, args, env );
+                inc_ref(next_pointer);
+              if ( exceptionp( next_pointer ) ) {
+                    result = next_pointer;
                 } else {
-                    free_stack_frame( next );
+                struct stack_frame *next = get_stack_frame(next_pointer);
+                result = eval_lambda( fn_cell, next, next_pointer, env );
+                if ( !exceptionp( result ) ) {
+                    dec_ref(next_pointer);
                 }
+              }
             }
             break;
         case NLAMBDATV:
             {
-                struct stack_frame *next =
-                    make_special_frame( frame, args, env );
-#ifdef DEBUG
-                fputws( L"Stack frame for nlambda\n", stderr );
-                dump_frame( stderr, next );
-#endif
-                result = eval_lambda( fn_cell, next, env );
+                struct cons_pointer next_pointer =
+                     make_special_frame( frame_pointer, args, env );
+              inc_ref(next_pointer);
+              if ( exceptionp( next_pointer ) ) {
+                    result = next_pointer;
+                } else {
+                struct stack_frame *next = get_stack_frame(frame_pointer);
+              result = eval_lambda( fn_cell, next, next_pointer, env );
                 if ( !exceptionp( result ) ) {
-                    /* if we're returning an exception, we should NOT free the
-                     * stack frame. Corollary is, when we free an exception, we
-                     * should free all the frames it's holding on to. */
-                    free_stack_frame( next );
+                    dec_ref(next_pointer);
                 }
+              }
             }
             break;
         case SPECIALTV:
             {
-                struct stack_frame *next =
-                    make_special_frame( frame, args, env );
-                result = ( *fn_cell.payload.special.executable ) ( next, env );
+                struct cons_pointer next_pointer =
+                     make_special_frame( frame_pointer, args, env );
+              inc_ref(next_pointer);
+              if ( exceptionp( next_pointer ) ) {
+                    result = next_pointer;
+                } else {
+                struct stack_frame *next = get_stack_frame(frame_pointer);
+                result = ( *fn_cell.payload.special.executable ) ( next, next_pointer, env );
                 if ( !exceptionp( result ) ) {
-                    /* if we're returning an exception, we should NOT free the
-                     * stack frame. Corollary is, when we free an exception, we
-                     * should free all the frames it's holding on to. */
-                    free_stack_frame( next );
+                    dec_ref(next_pointer);
                 }
+              }
             }
             break;
         default:
@@ -338,9 +352,10 @@ c_apply( struct stack_frame *frame, struct cons_pointer env ) {
                 struct cons_pointer message =
                     c_string_to_lisp_string( buffer );
                 free( buffer );
-                result = lisp_throw( message, frame );
+                result = throw_exception( message, frame_pointer );
             }
     }
+  dec_ref(fn_frame_pointer);
 
     return result;
 }
@@ -378,19 +393,19 @@ struct cons_pointer c_type( struct cons_pointer pointer ) {
  * If a special form, passes the cdr of s_expr to the special form as argument.
  */
 struct cons_pointer
-lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = frame->arg[0];
     struct cons_space_object cell = pointer2cell( frame->arg[0] );
 
 #ifdef DEBUG
     fputws( L"Eval: ", stderr );
-    dump_frame( stderr, frame );
+    dump_frame( stderr, frame_pointer );
 #endif
 
     switch ( cell.tag.value ) {
         case CONSTV:
             {
-                result = c_apply( frame, env );
+                result = c_apply( frame, frame_pointer, env );
             }
             break;
 
@@ -403,7 +418,7 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
                         make_cons( c_string_to_lisp_string
                                    ( "Attempt to take value of unbound symbol." ),
                                    frame->arg[0] );
-                    result = lisp_throw( message, frame );
+                    result = throw_exception( message, frame_pointer );
                 } else {
                     result = c_assoc( canonical, env );
                     inc_ref( result );
@@ -441,15 +456,15 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer env ) {
  * the second argument
  */
 struct cons_pointer
-lisp_apply( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
 #ifdef DEBUG
     fputws( L"Apply: ", stderr );
-    dump_frame( stderr, frame );
+    dump_frame( stderr, frame_pointer );
 #endif
     set_reg( frame, 0, make_cons( frame->arg[0], frame->arg[1] ) );
     set_reg( frame, 1, NIL );
 
-    struct cons_pointer result = c_apply( frame, env );
+    struct cons_pointer result = c_apply( frame, frame_pointer, env );
 
 #ifdef DEBUG
     fputws( L"Apply returning ", stderr );
@@ -469,7 +484,7 @@ lisp_apply( struct stack_frame *frame, struct cons_pointer env ) {
  * this isn't at this stage checked) unevaluated.
  */
 struct cons_pointer
-lisp_quote( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_quote( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return frame->arg[0];
 }
 
@@ -484,7 +499,7 @@ lisp_quote( struct stack_frame *frame, struct cons_pointer env ) {
  * the namespace in so doing. `namespace` defaults to the value of `oblist`.
  */
 struct cons_pointer
-lisp_set( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_pointer namespace =
         nilp( frame->arg[2] ) ? oblist : frame->arg[2];
@@ -497,7 +512,7 @@ lisp_set( struct stack_frame *frame, struct cons_pointer env ) {
             make_exception( make_cons
                             ( c_string_to_lisp_string
                               ( "The first argument to `set!` is not a symbol: " ),
-                              make_cons( frame->arg[0], NIL ) ), frame );
+                              make_cons( frame->arg[0], NIL ) ), frame_pointer );
     }
 
     return result;
@@ -514,13 +529,13 @@ lisp_set( struct stack_frame *frame, struct cons_pointer env ) {
  * the namespace in so doing. `namespace` defaults to the value of `oblist`.
  */
 struct cons_pointer
-lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_pointer namespace =
         nilp( frame->arg[2] ) ? oblist : frame->arg[2];
 
     if ( symbolp( frame->arg[0] ) ) {
-        struct cons_pointer val = eval_form( frame, frame->arg[1], env );
+        struct cons_pointer val = eval_form( frame, frame_pointer, frame->arg[1], env );
         deep_bind( frame->arg[0], val );
         result = val;
     } else {
@@ -528,7 +543,7 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env ) {
             make_exception( make_cons
                             ( c_string_to_lisp_string
                               ( "The first argument to `set!` is not a symbol: " ),
-                              make_cons( frame->arg[0], NIL ) ), frame );
+                              make_cons( frame->arg[0], NIL ) ), frame_pointer );
     }
 
     return result;
@@ -543,7 +558,7 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env ) {
  * otherwise returns a new cons cell.
  */
 struct cons_pointer
-lisp_cons( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_cons( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer car = frame->arg[0];
     struct cons_pointer cdr = frame->arg[1];
     struct cons_pointer result;
@@ -567,7 +582,7 @@ lisp_cons( struct stack_frame *frame, struct cons_pointer env ) {
  * strings, and TODO read streams and other things which can be considered as sequences.
  */
 struct cons_pointer
-lisp_car( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
 
     if ( consp( frame->arg[0] ) ) {
@@ -579,7 +594,7 @@ lisp_car( struct stack_frame *frame, struct cons_pointer env ) {
     } else {
         struct cons_pointer message =
             c_string_to_lisp_string( "Attempt to take CAR of non sequence" );
-        result = lisp_throw( message, frame );
+        result = throw_exception( message, frame_pointer );
     }
 
     return result;
@@ -591,7 +606,7 @@ lisp_car( struct stack_frame *frame, struct cons_pointer env ) {
  * strings, and TODO read streams and other things which can be considered as sequences.
  */
 struct cons_pointer
-lisp_cdr( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
 
     if ( consp( frame->arg[0] ) ) {
@@ -603,7 +618,7 @@ lisp_cdr( struct stack_frame *frame, struct cons_pointer env ) {
     } else {
         struct cons_pointer message =
             c_string_to_lisp_string( "Attempt to take CDR of non sequence" );
-        result = lisp_throw( message, frame );
+        result = throw_exception( message, frame_pointer );
     }
 
     return result;
@@ -614,7 +629,7 @@ lisp_cdr( struct stack_frame *frame, struct cons_pointer env ) {
  * Returns the value associated with key in store, or NIL if not found.
  */
 struct cons_pointer
-lisp_assoc( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_assoc( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return c_assoc( frame->arg[0], frame->arg[1] );
 }
 
@@ -622,7 +637,7 @@ lisp_assoc( struct stack_frame *frame, struct cons_pointer env ) {
  * (eq a b)
  * Returns T if a and b are pointers to the same object, else NIL
  */
-struct cons_pointer lisp_eq( struct stack_frame *frame,
+struct cons_pointer lisp_eq( struct stack_frame *frame, struct cons_pointer frame_pointer,
                              struct cons_pointer env ) {
     return eq( frame->arg[0], frame->arg[1] ) ? TRUE : NIL;
 }
@@ -632,7 +647,7 @@ struct cons_pointer lisp_eq( struct stack_frame *frame,
  * Returns T if a and b are pointers to structurally identical objects, else NIL
  */
 struct cons_pointer
-lisp_equal( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return equal( frame->arg[0], frame->arg[1] ) ? TRUE : NIL;
 }
 
@@ -643,14 +658,14 @@ lisp_equal( struct stack_frame *frame, struct cons_pointer env ) {
  * is a read stream, then read from that stream, else stdin.
  */
 struct cons_pointer
-lisp_read( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_read( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     FILE *input = stdin;
 
     if ( readp( frame->arg[0] ) ) {
         input = pointer2cell( frame->arg[0] ).payload.stream.stream;
     }
 
-    return read( frame, input );
+    return read( frame, frame_pointer, input );
 }
 
 
@@ -683,7 +698,7 @@ struct cons_pointer c_reverse( struct cons_pointer arg ) {
  * (reverse sequence)
  * Return a sequence like this sequence but with the members in the reverse order.
  */
-struct cons_pointer lisp_reverse( struct stack_frame *frame,
+struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                   struct cons_pointer env ) {
     return c_reverse( frame->arg[0] );
 }
@@ -696,7 +711,10 @@ struct cons_pointer lisp_reverse( struct stack_frame *frame,
  * is a write stream, then print to that stream, else stdout.
  */
 struct cons_pointer
-lisp_print( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+#ifdef DEBUG
+  fputws(L"Entering print\n", stderr);
+#endif
     struct cons_pointer result = NIL;
     FILE *output = stdout;
 
@@ -706,9 +724,11 @@ lisp_print( struct stack_frame *frame, struct cons_pointer env ) {
 
     result = print( output, frame->arg[0] );
 
+#ifdef DEBUG
     fputws( L"Print returning ", stderr );
-    print( stderr, result );
+    // print( stderr, result );
     fputws( L"\n", stderr );
+#endif
 
     return result;
 }
@@ -721,7 +741,7 @@ lisp_print( struct stack_frame *frame, struct cons_pointer env ) {
  * @return As a Lisp string, the tag of the object which is the argument.
  */
 struct cons_pointer
-lisp_type( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     return c_type( frame->arg[0] );
 }
 
@@ -739,16 +759,16 @@ lisp_type( struct stack_frame *frame, struct cons_pointer env ) {
  * argument.
  */
 struct cons_pointer
-lisp_progn( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer remaining = frame->more;
     struct cons_pointer result = NIL;
 
     for ( int i = 0; i < args_in_frame && !nilp( frame->arg[i] ); i++ ) {
-        result = eval_form( frame, frame->arg[i], env );
+        result = eval_form( frame, frame_pointer, frame->arg[i], env );
     }
 
     while ( consp( remaining ) ) {
-        result = eval_form( frame, c_car( remaining ), env );
+        result = eval_form( frame, frame_pointer, c_car( remaining ), env );
 
         remaining = c_cdr( remaining );
     }
@@ -766,7 +786,7 @@ lisp_progn( struct stack_frame *frame, struct cons_pointer env ) {
  * @return the value of the last form of the first successful clause.
  */
 struct cons_pointer
-lisp_cond( struct stack_frame *frame, struct cons_pointer env ) {
+lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     bool done = false;
 
@@ -777,11 +797,11 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer env ) {
 
         if ( consp( clause_pointer ) ) {
             struct cons_space_object cell = pointer2cell( clause_pointer );
-            result = eval_form( frame, c_car( clause_pointer ), env );
+            result = eval_form( frame, frame_pointer, c_car( clause_pointer ), env );
 
             if ( !nilp( result ) ) {
                 struct cons_pointer vals =
-                    eval_forms( frame, c_cdr( clause_pointer ), env );
+                    eval_forms( frame, frame_pointer,c_cdr( clause_pointer ), env );
 
                 while ( consp( vals ) ) {
                     result = c_car( vals );
@@ -793,9 +813,9 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer env ) {
         } else if ( nilp( clause_pointer ) ) {
             done = true;
         } else {
-            result = lisp_throw( c_string_to_lisp_string
+            result = throw_exception( c_string_to_lisp_string
                                  ( "Arguments to `cond` must be lists" ),
-                                 frame );
+                                 frame_pointer);
         }
     }
     /* TODO: if there are more than 8 clauses we need to continue into the
@@ -805,15 +825,17 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer env ) {
 }
 
 /**
- * TODO: make this do something sensible somehow.
- * This requires that a frame be a heap-space object with a cons-space
+ * Throw an exception.
+ * `throw_exception` is a misnomer, because it doesn't obey the calling signature of a
+ * lisp function; but it is nevertheless to be preferred to make_exception. A
+ * real `throw_exception`, which does, will be needed.
  * object pointing to it. Then this should become a normal lisp function
  * which expects a normally bound frame and environment, such that
  * frame->arg[0] is the message, and frame->arg[1] is the cons-space
  * pointer to the frame in which the exception occurred.
  */
 struct cons_pointer
-lisp_throw( struct cons_pointer message, struct stack_frame *frame ) {
+throw_exception( struct cons_pointer message, struct cons_pointer frame_pointer ) {
     fwprintf( stderr, L"\nERROR: " );
     print( stderr, message );
     struct cons_pointer result = NIL;
@@ -823,8 +845,23 @@ lisp_throw( struct cons_pointer message, struct stack_frame *frame ) {
     if ( cell.tag.value == EXCEPTIONTV ) {
         result = message;
     } else {
-        result = make_exception( message, frame );
+        result = make_exception( message, frame_pointer );
     }
 
     return result;
 }
+
+/**
+ * (exception <message>)
+ *
+ * Function. Returns an exception whose message is this `message`, and whose
+ * stack frame is the parent stack frame when the function is invoked.
+ * `message` does not have to be a string but should be something intelligible
+ * which can be read.
+ * If `message` is itself an exception, returns that instead.
+ */
+struct cons_pointer
+lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+  struct cons_pointer message = frame->arg[0];
+  return exceptionp(message) ? message : make_exception(message, frame->previous);
+}
diff --git a/src/ops/lispops.h b/src/ops/lispops.h
index 961cf2e..059255d 100644
--- a/src/ops/lispops.h
+++ b/src/ops/lispops.h
@@ -51,6 +51,7 @@ struct cons_pointer c_reverse( struct cons_pointer arg );
  * @return the result of evaluating the form.
  */
 struct cons_pointer eval_form( struct stack_frame *parent,
+                               struct cons_pointer parent_pointer,
                                struct cons_pointer form,
                                struct cons_pointer env );
 
@@ -59,7 +60,7 @@ struct cons_pointer eval_form( struct stack_frame *parent,
  * and this `env`, and return a list of their values. If the arg passed as
  * `list` is not in fact a list, return nil.
  */
-struct cons_pointer eval_forms( struct stack_frame *frame,
+struct cons_pointer eval_forms( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer list,
                                 struct cons_pointer env );
 
@@ -67,19 +68,19 @@ struct cons_pointer eval_forms( struct stack_frame *frame,
 /*
  * special forms
  */
-struct cons_pointer lisp_eval( struct stack_frame *frame,
+struct cons_pointer lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                struct cons_pointer env );
-struct cons_pointer lisp_apply( struct stack_frame *frame,
+struct cons_pointer lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
 
 struct cons_pointer
-lisp_oblist( struct stack_frame *frame, struct cons_pointer env );
+lisp_oblist( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 struct cons_pointer
-lisp_set( struct stack_frame *frame, struct cons_pointer env );
+lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 struct cons_pointer
-lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env );
+lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 /**
  * Construct an interpretable function.
@@ -88,7 +89,7 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer env );
  * @param lexpr the lambda expression to be interpreted;
  * @param env the environment in which it is to be intepreted.
  */
-struct cons_pointer lisp_lambda( struct stack_frame *frame,
+struct cons_pointer lisp_lambda( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                  struct cons_pointer env );
 
 /**
@@ -98,31 +99,31 @@ struct cons_pointer lisp_lambda( struct stack_frame *frame,
  * @param env the environment in which it is to be intepreted.
  */
 struct cons_pointer
-lisp_nlambda( struct stack_frame *frame, struct cons_pointer env );
+lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
-struct cons_pointer lisp_quote( struct stack_frame *frame,
+struct cons_pointer lisp_quote( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
 
 /*
  * functions
  */
-struct cons_pointer lisp_cons( struct stack_frame *frame,
+struct cons_pointer lisp_cons( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                struct cons_pointer env );
-struct cons_pointer lisp_car( struct stack_frame *frame,
+struct cons_pointer lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer,
                               struct cons_pointer env );
-struct cons_pointer lisp_cdr( struct stack_frame *frame,
+struct cons_pointer lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer,
                               struct cons_pointer env );
-struct cons_pointer lisp_assoc( struct stack_frame *frame,
+struct cons_pointer lisp_assoc( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
-struct cons_pointer lisp_eq( struct stack_frame *frame,
+struct cons_pointer lisp_eq( struct stack_frame *frame, struct cons_pointer frame_pointer,
                              struct cons_pointer env );
-struct cons_pointer lisp_equal( struct stack_frame *frame,
+struct cons_pointer lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
-struct cons_pointer lisp_print( struct stack_frame *frame,
+struct cons_pointer lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
-struct cons_pointer lisp_read( struct stack_frame *frame,
+struct cons_pointer lisp_read( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                struct cons_pointer env );
-struct cons_pointer lisp_reverse( struct stack_frame *frame,
+struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer frame_pointer,
                                   struct cons_pointer env );
 /**
  * Function: Get the Lisp type of the single argument.
@@ -131,7 +132,7 @@ struct cons_pointer lisp_reverse( struct stack_frame *frame,
  * @return As a Lisp string, the tag of the object which is the argument.
  */
 struct cons_pointer
-lisp_type( struct stack_frame *frame, struct cons_pointer env );
+lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 
 /**
@@ -145,7 +146,7 @@ lisp_type( struct stack_frame *frame, struct cons_pointer env );
  * argument.
  */
 struct cons_pointer
-lisp_progn( struct stack_frame *frame, struct cons_pointer env );
+lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
 /**
  * Special form: conditional. Each arg is expected to be a list; if the first
@@ -157,10 +158,16 @@ lisp_progn( struct stack_frame *frame, struct cons_pointer env );
  * @return the value of the last form of the first successful clause.
  */
 struct cons_pointer
-lisp_cond( struct stack_frame *frame, struct cons_pointer env );
+lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
 
-/*
- * neither, at this stage, really
+/**
+ * Throw an exception.
+ * `throw_exception` is a misnomer, because it doesn't obey the calling signature of a
+ * lisp function; but it is nevertheless to be preferred to make_exception. A
+ * real `throw_exception`, which does, will be needed.
  */
-struct cons_pointer lisp_throw( struct cons_pointer message,
-                                struct stack_frame *frame );
+struct cons_pointer throw_exception( struct cons_pointer message,
+                                struct cons_pointer frame_pointer );
+
+struct cons_pointer
+lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
diff --git a/src/ops/print.c b/src/ops/print.c
index 4ec5a15..7efd59f 100644
--- a/src/ops/print.c
+++ b/src/ops/print.c
@@ -20,6 +20,7 @@
 #include "conspage.h"
 #include "consspaceobject.h"
 #include "integer.h"
+#include "stack.h"
 #include "print.h"
 
 /**
@@ -118,12 +119,7 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
         case EXCEPTIONTV:
             fwprintf( output, L"\n%sException: ",
                       print_use_colours ? "\x1B[31m" : "" );
-            if ( stringp( cell.payload.exception.message ) ) {
-                print_string_contents( output,
-                                       cell.payload.exception.message );
-            } else {
-                print( output, cell.payload.exception.message );
-            }
+            dump_stack_trace(output, pointer);
             break;
         case FUNCTIONTV:
             fwprintf( output, L"(Function)" );
diff --git a/src/ops/read.c b/src/ops/read.c
index bd063b2..1a09700 100644
--- a/src/ops/read.c
+++ b/src/ops/read.c
@@ -25,6 +25,7 @@
 #include "ratio.h"
 #include "read.h"
 #include "real.h"
+#include "vectorspace.h"
 
 /*
  * for the time being things which may be read are: strings numbers - either
@@ -32,9 +33,11 @@
  * atoms because I don't yet know what an atom is or how it's stored.
  */
 
-struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
+struct cons_pointer read_number( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer, FILE * input,
                                  wint_t initial, bool seen_period );
-struct cons_pointer read_list( struct stack_frame *frame, FILE * input,
+struct cons_pointer read_list( struct stack_frame *frame,
+                              struct cons_pointer frame_pointer, FILE * input,
                                wint_t initial );
 struct cons_pointer read_string( FILE * input, wint_t initial );
 struct cons_pointer read_symbol( FILE * input, wint_t initial );
@@ -52,7 +55,7 @@ struct cons_pointer c_quote( struct cons_pointer arg ) {
  * treating this initial character as the first character of the object
  * representation.
  */
-struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
+struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_pointer frame_pointer, FILE * input,
                                        wint_t initial ) {
     struct cons_pointer result = NIL;
 
@@ -64,7 +67,7 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
     if ( feof( input ) ) {
         result =
             make_exception( c_string_to_lisp_string
-                            ( "End of file while reading" ), frame );
+                            ( "End of file while reading" ), frame_pointer );
     } else {
         switch ( c ) {
             case ';':
@@ -72,16 +75,16 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
                 /* skip all characters from semi-colon to the end of the line */
                 break;
             case EOF:
-                result = lisp_throw( c_string_to_lisp_string
-                                     ( "End of input while reading" ), frame );
+                result = throw_exception( c_string_to_lisp_string
+                                     ( "End of input while reading" ), frame_pointer );
                 break;
             case '\'':
                 result =
                     c_quote( read_continuation
-                             ( frame, input, fgetwc( input ) ) );
+                             ( frame, frame_pointer, input, fgetwc( input ) ) );
                 break;
             case '(':
-                result = read_list( frame, input, fgetwc( input ) );
+                result = read_list( frame, frame_pointer, input, fgetwc( input ) );
                 break;
             case '"':
                 result = read_string( input, fgetwc( input ) );
@@ -90,7 +93,7 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
                     wint_t next = fgetwc( input );
                     ungetwc( next, input );
                     if ( iswdigit( next ) ) {
-                        result = read_number( frame, input, c, false );
+                        result = read_number( frame, frame_pointer, input, c, false );
                     } else {
                         result = read_symbol( input, c );
                     }
@@ -101,12 +104,12 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
                     wint_t next = fgetwc( input );
                     if ( iswdigit( next ) ) {
                         ungetwc( next, input );
-                        result = read_number( frame, input, c, true );
+                        result = read_number( frame, frame_pointer, input, c, true );
                     } else if ( iswblank( next ) ) {
                         /* dotted pair. TODO: this isn't right, we
                          * really need to backtrack up a level. */
                         result =
-                            read_continuation( frame, input, fgetwc( input ) );
+                            read_continuation( frame, frame_pointer, input, fgetwc( input ) );
                     } else {
                         read_symbol( input, c );
                     }
@@ -114,7 +117,7 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
                 break;
             default:
                 if ( iswdigit( c ) ) {
-                    result = read_number( frame, input, c, false );
+                    result = read_number( frame, frame_pointer, input, c, false );
                 } else if ( iswprint( c ) ) {
                     result = read_symbol( input, c );
                 } else {
@@ -122,7 +125,7 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
                         make_exception( make_cons( c_string_to_lisp_string
                                                    ( "Unrecognised start of input character" ),
                                                    make_string( c, NIL ) ),
-                                        frame );
+                                        frame_pointer );
                 }
                 break;
         }
@@ -136,7 +139,9 @@ struct cons_pointer read_continuation( struct stack_frame *frame, FILE * input,
  * TODO: to be able to read bignums, we need to read the number from the
  * input stream into a Lisp string, and then convert it to a number.
  */
-struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
+struct cons_pointer read_number( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
+                                FILE * input,
                                  wint_t initial, bool seen_period ) {
     struct cons_pointer result = NIL;
     int64_t accumulator = 0;
@@ -157,7 +162,7 @@ struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
             if ( seen_period || dividend != 0 ) {
                 return make_exception( c_string_to_lisp_string
                                        ( "Malformed number: too many periods" ),
-                                       frame );
+                                       frame_pointer );
             } else {
                 seen_period = true;
             }
@@ -165,7 +170,7 @@ struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
             if ( seen_period || dividend > 0 ) {
                 return make_exception( c_string_to_lisp_string
                                        ( "Malformed number: dividend of rational must be integer" ),
-                                       frame );
+                                       frame_pointer );
             } else {
                 dividend = negative ? 0 - accumulator : accumulator;
 
@@ -200,7 +205,7 @@ struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
         result = make_real( rv );
     } else if ( dividend != 0 ) {
         result =
-            make_ratio( frame, make_integer( dividend ),
+            make_ratio( frame_pointer, make_integer( dividend ),
                         make_integer( accumulator ) );
     } else {
         if ( negative ) {
@@ -216,18 +221,18 @@ struct cons_pointer read_number( struct stack_frame *frame, FILE * input,
  * Read a list from this input stream, which no longer contains the opening
  * left parenthesis.
  */
-struct cons_pointer read_list( struct
-                               stack_frame
-                               *frame, FILE * input, wint_t initial ) {
+struct cons_pointer read_list( struct stack_frame *frame,
+                              struct cons_pointer frame_pointer,
+                              FILE * input, wint_t initial ) {
     struct cons_pointer result = NIL;
     if ( initial != ')' ) {
 #ifdef DEBUG
         fwprintf( stderr,
                   L"read_list starting '%C' (%d)\n", initial, initial );
 #endif
-        struct cons_pointer car = read_continuation( frame, input,
+        struct cons_pointer car = read_continuation( frame, frame_pointer, input,
                                                      initial );
-        result = make_cons( car, read_list( frame, input, fgetwc( input ) ) );
+        result = make_cons( car, read_list( frame, frame_pointer, input, fgetwc( input ) ) );
     }
 #ifdef DEBUG
     else {
@@ -318,6 +323,6 @@ struct cons_pointer read_symbol( FILE * input, wint_t initial ) {
  */
 struct cons_pointer read( struct
                           stack_frame
-                          *frame, FILE * input ) {
-    return read_continuation( frame, input, fgetwc( input ) );
+                          *frame, struct cons_pointer frame_pointer, FILE * input ) {
+    return read_continuation( frame, frame_pointer, input, fgetwc( input ) );
 }
diff --git a/src/ops/read.h b/src/ops/read.h
index af7574b..c144699 100644
--- a/src/ops/read.h
+++ b/src/ops/read.h
@@ -14,6 +14,8 @@
 /**
  * read the next object on this input stream and return a cons_pointer to it.
  */
-struct cons_pointer read( struct stack_frame *frame, FILE * input );
+struct cons_pointer read( struct stack_frame *frame,
+                         struct cons_pointer frame_pointer,
+                         FILE * input );
 
 #endif
diff --git a/src/repl.c b/src/repl.c
index f9ca5d5..5dd6567 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -31,44 +31,64 @@
  * Dummy up a Lisp read call with its own stack frame.
  */
 struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
-    struct stack_frame *frame = make_empty_frame( NULL, oblist );
+  struct cons_pointer result = NIL;
+  struct cons_pointer frame_pointer = make_empty_frame( NIL );
+  if (!nilp(frame_pointer)) {
+    inc_ref(frame_pointer);
+    struct stack_frame *frame = get_stack_frame(frame_pointer);
 
-    set_reg( frame, 0, stream_pointer );
-    struct cons_pointer result = lisp_read( frame, oblist );
-    free_stack_frame( frame );
+    if (frame != NULL){
 
-    return result;
+      set_reg( frame, 0, stream_pointer );
+      struct cons_pointer result = lisp_read( frame, frame_pointer, oblist );
+    }
+    dec_ref(frame_pointer);
+  }
+
+  return result;
 }
 
 /**
  * Dummy up a Lisp eval call with its own stack frame.
  */
 struct cons_pointer repl_eval( struct cons_pointer input ) {
-    struct stack_frame *frame = make_empty_frame( NULL, oblist );
+  struct cons_pointer result = NIL;
+  struct cons_pointer frame_pointer = make_empty_frame( NIL );
+  if (!nilp(frame_pointer)) {
+    inc_ref(frame_pointer);
+    struct stack_frame *frame = get_stack_frame(frame_pointer);
 
-    set_reg( frame, 0, input );
-    struct cons_pointer result = lisp_eval( frame, oblist );
-
-    if ( !exceptionp( result ) ) {
-        free_stack_frame( frame );
+    if (frame != NULL){
+      set_reg( frame, 0, input );
+      result = lisp_eval( frame, frame_pointer, oblist );
     }
 
-    return result;
+    dec_ref(frame_pointer);
+  }
+
+  return result;
 }
 
 /**
  * Dummy up a Lisp print call with its own stack frame.
  */
 struct cons_pointer repl_print( struct cons_pointer stream_pointer,
-                                struct cons_pointer value ) {
-    struct stack_frame *frame = make_empty_frame( NULL, oblist );
+                               struct cons_pointer value ) {
+  struct cons_pointer result = NIL;
+  struct cons_pointer frame_pointer = make_empty_frame( NIL );
+  if (!nilp(frame_pointer)) {
+    struct stack_frame *frame = get_stack_frame(frame_pointer);
 
-    set_reg( frame, 0, value );
-    set_reg( frame, 1, stream_pointer );
-    struct cons_pointer result = lisp_print( frame, oblist );
-    free_stack_frame( frame );
+    if (frame != NULL){
+      set_reg( frame, 0, value );
+      set_reg( frame, 1, stream_pointer );
+      result = lisp_print( frame, frame_pointer, oblist );
+      free_stack_frame( frame );
+    }
+    dec_ref(frame_pointer);
+  }
 
-    return result;
+  return result;
 }
 
 /**

From 3d5c27cb10df058363a2f37789fea170a75451ed Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Wed, 26 Dec 2018 21:10:24 +0000
Subject: [PATCH 2/6] Horribly broken, may have to rethink.

---
 src/arith/peano.c            | 104 +++++++------
 src/arith/peano.h            |  14 +-
 src/arith/ratio.c            |  69 ++++-----
 src/arith/ratio.h            |  10 +-
 src/arith/real.c             |   1 +
 src/memory/consspaceobject.c |  26 ++--
 src/memory/consspaceobject.h |   8 +-
 src/memory/dump.c            |  23 +--
 src/memory/stack.c           | 282 ++++++++++++++++++++---------------
 src/memory/stack.h           |   8 +-
 src/memory/vectorspace.c     |  26 +++-
 src/memory/vectorspace.h     |   2 +-
 src/ops/equal.c              |   4 +-
 src/ops/lispops.c            | 194 ++++++++++++++----------
 src/ops/lispops.h            |  68 ++++++---
 src/ops/print.c              |  10 +-
 src/ops/read.c               |  56 ++++---
 src/ops/read.h               |   3 +-
 src/repl.c                   |  73 ++++-----
 19 files changed, 568 insertions(+), 413 deletions(-)

diff --git a/src/arith/peano.c b/src/arith/peano.c
index 63783f5..763414e 100644
--- a/src/arith/peano.c
+++ b/src/arith/peano.c
@@ -28,7 +28,9 @@
 
 long double to_long_double( struct cons_pointer arg );
 int64_t to_long_int( struct cons_pointer arg );
-struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer arg1,
+struct cons_pointer add_2( struct stack_frame *frame,
+                           struct cons_pointer frame_pointer,
+                           struct cons_pointer arg1,
                            struct cons_pointer arg2 );
 
 
@@ -119,7 +121,9 @@ int64_t to_long_int( struct cons_pointer arg ) {
 * return a cons_pointer indicating a number which is the sum of
 * the numbers indicated by `arg1` and `arg2`.
 */
-struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer arg1,
+struct cons_pointer add_2( struct stack_frame *frame,
+                           struct cons_pointer frame_pointer,
+                           struct cons_pointer arg1,
                            struct cons_pointer arg2 ) {
     struct cons_pointer result;
     struct cons_space_object cell1 = pointer2cell( arg1 );
@@ -153,7 +157,8 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_
                                                cell2.payload.integer.value );
                         break;
                     case RATIOTV:
-                        result = add_integer_ratio( frame_pointer, arg1, arg2 );
+                        result =
+                            add_integer_ratio( frame_pointer, arg1, arg2 );
                         break;
                     case REALTV:
                         result =
@@ -162,8 +167,8 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                             ( "Cannot add: not a number" ),
-                                             frame_pointer );
+                                                  ( "Cannot add: not a number" ),
+                                                  frame_pointer );
                         break;
                 }
                 break;
@@ -173,7 +178,8 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_
                         result = arg2;
                         break;
                     case INTEGERTV:
-                        result = add_integer_ratio( frame_pointer, arg2, arg1 );
+                        result =
+                            add_integer_ratio( frame_pointer, arg2, arg1 );
                         break;
                     case RATIOTV:
                         result = add_ratio_ratio( frame_pointer, arg1, arg2 );
@@ -185,8 +191,8 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                             ( "Cannot add: not a number" ),
-                                             frame_pointer );
+                                                  ( "Cannot add: not a number" ),
+                                                  frame_pointer );
                         break;
                 }
                 break;
@@ -198,7 +204,8 @@ struct cons_pointer add_2( struct stack_frame *frame, struct cons_pointer frame_
             default:
                 result = exceptionp( arg2 ) ? arg2 :
                     throw_exception( c_string_to_lisp_string
-                                ( "Cannot add: not a number" ), frame_pointer );
+                                     ( "Cannot add: not a number" ),
+                                     frame_pointer );
         }
     }
 
@@ -252,7 +259,8 @@ struct cons_pointer lisp_add( struct stack_frame
 * return a cons_pointer indicating a number which is the product of
 * the numbers indicated by `arg1` and `arg2`.
 */
-struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer multiply_2( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer arg1,
                                 struct cons_pointer arg2 ) {
     struct cons_pointer result;
@@ -286,7 +294,9 @@ struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer f
                                                cell2.payload.integer.value );
                         break;
                     case RATIOTV:
-                        result = multiply_integer_ratio( frame_pointer, arg1, arg2 );
+                        result =
+                            multiply_integer_ratio( frame_pointer, arg1,
+                                                    arg2 );
                         break;
                     case REALTV:
                         result =
@@ -295,8 +305,8 @@ struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer f
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                             ( "Cannot multiply: not a number" ),
-                                             frame_pointer );
+                                                  ( "Cannot multiply: not a number" ),
+                                                  frame_pointer );
                         break;
                 }
                 break;
@@ -306,10 +316,13 @@ struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer f
                         result = arg2;
                         break;
                     case INTEGERTV:
-                        result = multiply_integer_ratio( frame_pointer, arg2, arg1 );
+                        result =
+                            multiply_integer_ratio( frame_pointer, arg2,
+                                                    arg1 );
                         break;
                     case RATIOTV:
-                        result = multiply_ratio_ratio( frame_pointer, arg1, arg2 );
+                        result =
+                            multiply_ratio_ratio( frame_pointer, arg1, arg2 );
                         break;
                     case REALTV:
                         result =
@@ -318,8 +331,8 @@ struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer f
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                             ( "Cannot multiply: not a number" ),
-                                             frame_pointer );
+                                                  ( "Cannot multiply: not a number" ),
+                                                  frame_pointer );
                 }
                 break;
             case REALTV:
@@ -329,8 +342,8 @@ struct cons_pointer multiply_2( struct stack_frame *frame, struct cons_pointer f
                 break;
             default:
                 result = throw_exception( c_string_to_lisp_string
-                                     ( "Cannot multiply: not a number" ),
-                                     frame_pointer );
+                                          ( "Cannot multiply: not a number" ),
+                                          frame_pointer );
                 break;
         }
     }
@@ -406,8 +419,8 @@ struct cons_pointer inverse( struct cons_pointer frame,
         case RATIOTV:
             result = make_ratio( frame,
                                  make_integer( 0 -
-                                               to_long_int( cell.payload.ratio.
-                                                            dividend ) ),
+                                               to_long_int( cell.payload.
+                                                            ratio.dividend ) ),
                                  cell.payload.ratio.divisor );
             break;
         case REALTV:
@@ -453,9 +466,10 @@ struct cons_pointer lisp_subtract( struct
                         struct cons_pointer tmp =
                             make_ratio( frame_pointer, frame->arg[0],
                                         make_integer( 1 ) );
-                        inc_ref(tmp);
+                        inc_ref( tmp );
                         result =
-                            subtract_ratio_ratio( frame_pointer, tmp, frame->arg[1] );
+                            subtract_ratio_ratio( frame_pointer, tmp,
+                                                  frame->arg[1] );
                         dec_ref( tmp );
                     }
                     break;
@@ -466,8 +480,8 @@ struct cons_pointer lisp_subtract( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                         ( "Cannot subtract: not a number" ),
-                                         frame_pointer );
+                                              ( "Cannot subtract: not a number" ),
+                                              frame_pointer );
                     break;
             }
             break;
@@ -480,9 +494,10 @@ struct cons_pointer lisp_subtract( struct
                         struct cons_pointer tmp =
                             make_ratio( frame_pointer, frame->arg[1],
                                         make_integer( 1 ) );
-                        inc_ref(tmp);
+                        inc_ref( tmp );
                         result =
-                            subtract_ratio_ratio( frame_pointer, frame->arg[0], tmp );
+                            subtract_ratio_ratio( frame_pointer, frame->arg[0],
+                                                  tmp );
                         dec_ref( tmp );
                     }
                     break;
@@ -498,8 +513,8 @@ struct cons_pointer lisp_subtract( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                         ( "Cannot subtract: not a number" ),
-                                         frame_pointer );
+                                              ( "Cannot subtract: not a number" ),
+                                              frame_pointer );
                     break;
             }
             break;
@@ -510,7 +525,8 @@ struct cons_pointer lisp_subtract( struct
             break;
         default:
             result = throw_exception( c_string_to_lisp_string
-                                 ( "Cannot subtract: not a number" ), frame_pointer );
+                                      ( "Cannot subtract: not a number" ),
+                                      frame_pointer );
             break;
     }
 
@@ -527,7 +543,7 @@ struct cons_pointer lisp_subtract( struct
  */
 struct cons_pointer lisp_divide( struct
                                  stack_frame
-                                 *frame,  struct cons_pointer frame_pointer, struct
+                                 *frame, struct cons_pointer frame_pointer, struct
                                  cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_space_object arg0 = pointer2cell( frame->arg[0] );
@@ -544,7 +560,8 @@ struct cons_pointer lisp_divide( struct
                     break;
                 case INTEGERTV:{
                         struct cons_pointer unsimplified =
-                            make_ratio( frame_pointer, frame->arg[0], frame->arg[1] );
+                            make_ratio( frame_pointer, frame->arg[0],
+                                        frame->arg[1] );
                         /* OK, if result may be unsimplified, we should not inc_ref it
                          * - but if not, we should dec_ref it. */
                         result = simplify_ratio( frame_pointer, unsimplified );
@@ -558,7 +575,8 @@ struct cons_pointer lisp_divide( struct
                         struct cons_pointer ratio =
                             make_ratio( frame_pointer, frame->arg[0], one );
                         result =
-                            divide_ratio_ratio( frame_pointer, ratio, frame->arg[1] );
+                            divide_ratio_ratio( frame_pointer, ratio,
+                                                frame->arg[1] );
                         dec_ref( ratio );
                     }
                     break;
@@ -569,8 +587,8 @@ struct cons_pointer lisp_divide( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                         ( "Cannot divide: not a number" ),
-                                         frame_pointer );
+                                              ( "Cannot divide: not a number" ),
+                                              frame_pointer );
                     break;
             }
             break;
@@ -581,14 +599,15 @@ struct cons_pointer lisp_divide( struct
                     break;
                 case INTEGERTV:{
                         struct cons_pointer one = make_integer( 1 );
-                  inc_ref( one);
+                        inc_ref( one );
                         struct cons_pointer ratio =
                             make_ratio( frame_pointer, frame->arg[1], one );
-                        inc_ref(ratio);
+                        inc_ref( ratio );
                         result =
-                            divide_ratio_ratio( frame_pointer, frame->arg[0], ratio );
+                            divide_ratio_ratio( frame_pointer, frame->arg[0],
+                                                ratio );
                         dec_ref( ratio );
-                  dec_ref(one);
+                        dec_ref( one );
                     }
                     break;
                 case RATIOTV:
@@ -603,8 +622,8 @@ struct cons_pointer lisp_divide( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                         ( "Cannot divide: not a number" ),
-                                         frame_pointer );
+                                              ( "Cannot divide: not a number" ),
+                                              frame_pointer );
                     break;
             }
             break;
@@ -615,7 +634,8 @@ struct cons_pointer lisp_divide( struct
             break;
         default:
             result = throw_exception( c_string_to_lisp_string
-                                 ( "Cannot divide: not a number" ), frame_pointer );
+                                      ( "Cannot divide: not a number" ),
+                                      frame_pointer );
             break;
     }
 
diff --git a/src/arith/peano.h b/src/arith/peano.h
index 46008c2..f1c21b4 100644
--- a/src/arith/peano.h
+++ b/src/arith/peano.h
@@ -23,7 +23,8 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_add( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+     lisp_add( struct stack_frame *frame, struct cons_pointer frame_pointer,
+               struct cons_pointer env );
 
 /**
  * Multiply an indefinite number of numbers together
@@ -32,7 +33,9 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_multiply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+     lisp_multiply( struct stack_frame *frame,
+                    struct cons_pointer frame_pointer,
+                    struct cons_pointer env );
 
 /**
  * Subtract one number from another.
@@ -41,7 +44,9 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_subtract( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+     lisp_subtract( struct stack_frame *frame,
+                    struct cons_pointer frame_pointer,
+                    struct cons_pointer env );
 
 /**
  * Divide one number by another.
@@ -50,7 +55,8 @@ extern "C" {
  * @return a pointer to an integer or real.
  */
     struct cons_pointer
-     lisp_divide( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+     lisp_divide( struct stack_frame *frame, struct cons_pointer frame_pointer,
+                  struct cons_pointer env );
 
 #ifdef __cplusplus
 }
diff --git a/src/arith/ratio.c b/src/arith/ratio.c
index 042aea1..afea5b0 100644
--- a/src/arith/ratio.c
+++ b/src/arith/ratio.c
@@ -61,10 +61,10 @@ struct cons_pointer simplify_ratio( struct cons_pointer frame_pointer,
 
     if ( ratiop( arg ) ) {
         int64_t ddrv =
-            pointer2cell( pointer2cell( arg ).payload.ratio.dividend ).payload.
-            integer.value, drrv =
-            pointer2cell( pointer2cell( arg ).payload.ratio.divisor ).payload.
-            integer.value, gcd = greatest_common_divisor( ddrv, drrv );
+            pointer2cell( pointer2cell( arg ).payload.ratio.dividend ).
+            payload.integer.value, drrv =
+            pointer2cell( pointer2cell( arg ).payload.ratio.divisor ).
+            payload.integer.value, gcd = greatest_common_divisor( ddrv, drrv );
 
         if ( gcd > 1 ) {
             if ( drrv / gcd == 1 ) {
@@ -78,8 +78,8 @@ struct cons_pointer simplify_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( make_cons( c_string_to_lisp_string
-                                   ( "Shouldn't happen: bad arg to simplify_ratio" ),
-                                   arg ),  frame_pointer );
+                                        ( "Shouldn't happen: bad arg to simplify_ratio" ),
+                                        arg ), frame_pointer );
     }
 
     return result;
@@ -124,7 +124,7 @@ struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
 #endif
 
         if ( dr1v == dr2v ) {
-            r = make_ratio(  frame_pointer,
+            r = make_ratio( frame_pointer,
                             make_integer( dd1v + dd2v ),
                             cell1.payload.ratio.divisor );
         } else {
@@ -132,8 +132,8 @@ struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
                 dr1vm = make_integer( dr1v * m1 ),
                 dd2vm = make_integer( dd2v * m2 ),
                 dr2vm = make_integer( dr2v * m2 ),
-                r1 = make_ratio(  frame_pointer, dd1vm, dr1vm ),
-                r2 = make_ratio(  frame_pointer, dd2vm, dr2vm );
+                r1 = make_ratio( frame_pointer, dd1vm, dr1vm ),
+                r2 = make_ratio( frame_pointer, dd2vm, dr2vm );
 
             r = add_ratio_ratio( frame_pointer, r1, r2 );
 
@@ -144,17 +144,17 @@ struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
             dec_ref( r2 );
         }
 
-        result = simplify_ratio(  frame_pointer, r );
+        result = simplify_ratio( frame_pointer, r );
         if ( !eq( r, result ) ) {
             dec_ref( r );
         }
     } else {
         result =
             throw_exception( make_cons( c_string_to_lisp_string
-                                   ( "Shouldn't happen: bad arg to add_ratio_ratio" ),
-                                   make_cons( arg1,
-                                              make_cons( arg2, NIL ) ) ),
-                         frame_pointer );
+                                        ( "Shouldn't happen: bad arg to add_ratio_ratio" ),
+                                        make_cons( arg1,
+                                                   make_cons( arg2, NIL ) ) ),
+                             frame_pointer );
     }
 
 #ifdef DEBUG
@@ -181,17 +181,18 @@ struct cons_pointer add_integer_ratio( struct cons_pointer frame_pointer,
         struct cons_pointer one = make_integer( 1 ),
             ratio = make_ratio( frame_pointer, intarg, one );
 
-        result = add_ratio_ratio(  frame_pointer, ratio, ratarg );
+        result = add_ratio_ratio( frame_pointer, ratio, ratarg );
 
         dec_ref( one );
         dec_ref( ratio );
     } else {
         result =
             throw_exception( make_cons( c_string_to_lisp_string
-                                   ( "Shouldn't happen: bad arg to add_integer_ratio" ),
-                                   make_cons( intarg,
-                                              make_cons( ratarg, NIL ) ) ),
-                        frame_pointer );
+                                        ( "Shouldn't happen: bad arg to add_integer_ratio" ),
+                                        make_cons( intarg,
+                                                   make_cons( ratarg,
+                                                              NIL ) ) ),
+                             frame_pointer );
     }
 
     return result;
@@ -205,12 +206,12 @@ struct cons_pointer add_integer_ratio( struct cons_pointer frame_pointer,
 struct cons_pointer divide_ratio_ratio( struct cons_pointer frame_pointer,
                                         struct cons_pointer arg1,
                                         struct cons_pointer arg2 ) {
-    struct cons_pointer i = make_ratio(  frame_pointer,
-                                        pointer2cell( arg2 ).payload.ratio.
-                                        divisor,
-                                        pointer2cell( arg2 ).payload.ratio.
-                                        dividend ), result =
-        multiply_ratio_ratio(  frame_pointer, arg1, i );
+    struct cons_pointer i = make_ratio( frame_pointer,
+                                        pointer2cell( arg2 ).payload.
+                                        ratio.divisor,
+                                        pointer2cell( arg2 ).payload.
+                                        ratio.dividend ), result =
+        multiply_ratio_ratio( frame_pointer, arg1, i );
 
     dec_ref( i );
 
@@ -248,7 +249,7 @@ struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, str
             ddrv = dd1v * dd2v, drrv = dr1v * dr2v;
 
         struct cons_pointer unsimplified =
-            make_ratio(  frame_pointer, make_integer( ddrv ),
+            make_ratio( frame_pointer, make_integer( ddrv ),
                         make_integer( drrv ) );
         result = simplify_ratio( frame_pointer, unsimplified );
 
@@ -258,8 +259,8 @@ struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, str
     } else {
         result =
             throw_exception( c_string_to_lisp_string
-                        ( "Shouldn't happen: bad arg to multiply_ratio_ratio" ),
-                         frame_pointer );
+                             ( "Shouldn't happen: bad arg to multiply_ratio_ratio" ),
+                             frame_pointer );
     }
 
     return result;
@@ -278,15 +279,15 @@ struct cons_pointer multiply_integer_ratio( struct cons_pointer frame_pointer,
     if ( integerp( intarg ) && ratiop( ratarg ) ) {
         struct cons_pointer one = make_integer( 1 ),
             ratio = make_ratio( frame_pointer, intarg, one );
-        result = multiply_ratio_ratio(  frame_pointer, ratio, ratarg );
+        result = multiply_ratio_ratio( frame_pointer, ratio, ratarg );
 
         dec_ref( one );
         dec_ref( ratio );
     } else {
         result =
             throw_exception( c_string_to_lisp_string
-                        ( "Shouldn't happen: bad arg to multiply_integer_ratio" ),
-                         frame_pointer );
+                             ( "Shouldn't happen: bad arg to multiply_integer_ratio" ),
+                             frame_pointer );
     }
 
     return result;
@@ -302,7 +303,7 @@ struct cons_pointer subtract_ratio_ratio( struct cons_pointer frame_pointer,
                                           struct cons_pointer arg1,
                                           struct cons_pointer arg2 ) {
     struct cons_pointer i = inverse( frame_pointer, arg2 ),
-        result = add_ratio_ratio(  frame_pointer, arg1, i );
+        result = add_ratio_ratio( frame_pointer, arg1, i );
 
     dec_ref( i );
 
@@ -328,8 +329,8 @@ struct cons_pointer make_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( c_string_to_lisp_string
-                        ( "Dividend and divisor of a ratio must be integers" ),
-                         frame_pointer );
+                             ( "Dividend and divisor of a ratio must be integers" ),
+                             frame_pointer );
     }
 #ifdef DEBUG
     dump_object( stderr, result );
diff --git a/src/arith/ratio.h b/src/arith/ratio.h
index feb8925..5a3b0d6 100644
--- a/src/arith/ratio.h
+++ b/src/arith/ratio.h
@@ -14,15 +14,15 @@
 struct cons_pointer simplify_ratio( struct cons_pointer frame_pointer,
                                     struct cons_pointer arg );
 
-struct cons_pointer add_ratio_ratio(  struct cons_pointer frame_pointer,
+struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
                                      struct cons_pointer arg1,
                                      struct cons_pointer arg2 );
 
-struct cons_pointer add_integer_ratio(  struct cons_pointer frame_pointer,
+struct cons_pointer add_integer_ratio( struct cons_pointer frame_pointer,
                                        struct cons_pointer intarg,
                                        struct cons_pointer ratarg );
 
-struct cons_pointer divide_ratio_ratio(  struct cons_pointer frame_pointer,
+struct cons_pointer divide_ratio_ratio( struct cons_pointer frame_pointer,
                                         struct cons_pointer arg1,
                                         struct cons_pointer arg2 );
 
@@ -30,11 +30,11 @@ struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, str
                                           cons_pointer arg1, struct
                                           cons_pointer arg2 );
 
-struct cons_pointer multiply_integer_ratio(  struct cons_pointer frame_pointer,
+struct cons_pointer multiply_integer_ratio( struct cons_pointer frame_pointer,
                                             struct cons_pointer intarg,
                                             struct cons_pointer ratarg );
 
-struct cons_pointer subtract_ratio_ratio(  struct cons_pointer frame_pointer,
+struct cons_pointer subtract_ratio_ratio( struct cons_pointer frame_pointer,
                                           struct cons_pointer arg1,
                                           struct cons_pointer arg2 );
 
diff --git a/src/arith/real.c b/src/arith/real.c
index a499b6a..d3786dd 100644
--- a/src/arith/real.c
+++ b/src/arith/real.c
@@ -9,6 +9,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "dump.h"
 #include "read.h"
 
 /**
diff --git a/src/memory/consspaceobject.c b/src/memory/consspaceobject.c
index 75a5257..acca2a8 100644
--- a/src/memory/consspaceobject.c
+++ b/src/memory/consspaceobject.c
@@ -89,21 +89,21 @@ struct cons_pointer make_cons( struct cons_pointer car,
  * @param frame_pointer should be the pointer to the frame in which the exception occurred.
  */
 struct cons_pointer make_exception( struct cons_pointer message,
-                                   struct cons_pointer frame_pointer ) {
-  struct cons_pointer result = NIL;
-  struct cons_pointer pointer = allocate_cell( EXCEPTIONTAG );
-  struct cons_space_object *cell = &pointer2cell( pointer );
+                                    struct cons_pointer frame_pointer ) {
+    struct cons_pointer result = NIL;
+    struct cons_pointer pointer = allocate_cell( EXCEPTIONTAG );
+    struct cons_space_object *cell = &pointer2cell( pointer );
 
-  inc_ref( pointer );         /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
+    inc_ref( pointer );         /* this is a hack; I don't know why it's necessary to do this, but if I don't the cell gets freed */
 
-  inc_ref( message );
-  inc_ref( frame_pointer);
-  cell->payload.exception.message = message;
-  cell->payload.exception.frame = frame_pointer;
+    inc_ref( message );
+    inc_ref( frame_pointer );
+    cell->payload.exception.message = message;
+    cell->payload.exception.frame = frame_pointer;
 
-  result = pointer;
+    result = pointer;
 
-  return result;
+    return result;
 }
 
 
@@ -113,7 +113,7 @@ struct cons_pointer make_exception( struct cons_pointer message,
 struct cons_pointer
 make_function( struct cons_pointer src, struct cons_pointer ( *executable )
                 ( struct stack_frame *,
-                                     struct cons_pointer, struct cons_pointer ) ) {
+                  struct cons_pointer, struct cons_pointer ) ) {
     struct cons_pointer pointer = allocate_cell( FUNCTIONTAG );
     struct cons_space_object *cell = &pointer2cell( pointer );
 
@@ -212,7 +212,7 @@ struct cons_pointer make_symbol( wint_t c, struct cons_pointer tail ) {
 struct cons_pointer
 make_special( struct cons_pointer src, struct cons_pointer ( *executable )
                ( struct stack_frame * frame,
-                                     struct cons_pointer, struct cons_pointer env ) ) {
+                 struct cons_pointer, struct cons_pointer env ) ) {
     struct cons_pointer pointer = allocate_cell( SPECIALTAG );
     struct cons_space_object *cell = &pointer2cell( pointer );
 
diff --git a/src/memory/consspaceobject.h b/src/memory/consspaceobject.h
index b31a0bf..44b6a79 100644
--- a/src/memory/consspaceobject.h
+++ b/src/memory/consspaceobject.h
@@ -421,10 +421,10 @@ struct vectorp_payload {
                                  * tag. */
         uint32_t value;         /* the tag considered as a number */
     } tag;
-    struct vector_space_object * address;
-                                /* the address of the actual vector space
-                                 * object (TODO: will change when I actually
-                                 * implement vector space) */
+    struct vector_space_object *address;
+    /* the address of the actual vector space
+     * object (TODO: will change when I actually
+     * implement vector space) */
 };
 
 /**
diff --git a/src/memory/dump.c b/src/memory/dump.c
index 5306801..5aaedfb 100644
--- a/src/memory/dump.c
+++ b/src/memory/dump.c
@@ -72,7 +72,7 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
             break;
         case EXCEPTIONTV:
             fwprintf( output, L"\t\tException cell: " );
-            dump_stack_trace( output, pointer);
+            dump_stack_trace( output, pointer );
             break;
         case FREETV:
             fwprintf( output, L"\t\tFree cell: next at page %d offset %d\n",
@@ -93,10 +93,10 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
         case RATIOTV:
             fwprintf( output,
                       L"\t\tRational cell: value %ld/%ld, count %u\n",
-                      pointer2cell( cell.payload.ratio.dividend ).payload.
-                      integer.value,
-                      pointer2cell( cell.payload.ratio.divisor ).payload.
-                      integer.value, cell.count );
+                      pointer2cell( cell.payload.ratio.dividend ).
+                      payload.integer.value,
+                      pointer2cell( cell.payload.ratio.divisor ).
+                      payload.integer.value, cell.count );
             break;
         case READTV:
             fwprintf( output, L"\t\tInput stream\n" );
@@ -110,11 +110,12 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
         case SYMBOLTV:
             dump_string_cell( output, L"Symbol", pointer );
             break;
-      case VECTORPOINTTV: {
-        struct vector_space_object * vso = cell.payload.vectorp.address;
-      fwprintf( output, L"\t\tVector space object of type %4.4s, payload size %d bytes\n",
-                vso->header.tag, vso->header.size);
-      }
-      break;
+        case VECTORPOINTTV:{
+                struct vector_space_object *vso = cell.payload.vectorp.address;
+                fwprintf( output,
+                          L"\t\tVector space object of type %4.4s, payload size %d bytes\n",
+                          vso->header.tag, vso->header.size );
+            }
+            break;
     }
 }
diff --git a/src/memory/stack.c b/src/memory/stack.c
index 8fe268e..9f0f6f8 100644
--- a/src/memory/stack.c
+++ b/src/memory/stack.c
@@ -28,17 +28,26 @@
  * get the actual stackframe object from this `pointer`, or NULL if
  * `pointer` is not a stackframe pointer.
  */
-struct stack_frame * get_stack_frame(struct cons_pointer pointer) {
-  struct stack_frame * result = NULL;
-  struct vector_space_object * vso =
-    pointer2cell(pointer).payload.vectorp.address;
+struct stack_frame *get_stack_frame( struct cons_pointer pointer ) {
+    struct stack_frame *result = NULL;
+    fputws
+        ( L"get_stack_frame: about to get a pointer to the vector space object\n",
+          stderr );
+    struct vector_space_object *vso =
+        pointer2cell( pointer ).payload.vectorp.address;
+    fputws( L"get_stack_frame: got a pointer, about to test it\n", stderr );
 
-  if (vectorpointp(pointer) && stackframep(vso))
-  {
-    result = (struct stack_frame *) &(vso->payload);
-  }
+    if ( vectorpointp( pointer ) ) {  // && stackframep(vso)){
+        fputws( L"get_stack_frame: pointer is good, about to set the result\n",
+                stderr );
 
-  return result;
+        result = ( struct stack_frame * ) &( vso->payload );
+        fputws( L"get_stack_frame: all good, returning\n", stderr );
+    } else {
+        fputws( L"get_stack_frame: fail, returning NULL\n", stderr );
+    }
+
+    return result;
 }
 
 /**
@@ -48,28 +57,38 @@ struct stack_frame * get_stack_frame(struct cons_pointer pointer) {
  * @return the new frame, or NULL if memory is exhausted.
  */
 struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
-  struct cons_pointer result = make_vso(STACKFRAMETAG, sizeof(struct stack_frame));
-  if (!nilp(result)) {
-    struct stack_frame *frame = get_stack_frame(result);
-    /*
-     * TODO: later, pop a frame off a free-list of stack frames
-     */
+    fputws( L"Entering make_empty_frame\n", stderr );
+    struct cons_pointer result =
+        make_vso( STACKFRAMETAG, sizeof( struct stack_frame ) );
+    if ( !nilp( result ) ) {
+        fputws( L"make_empty_frame: about to call get_stack_frame\n", stderr );
+        struct stack_frame *frame = get_stack_frame( result );
+        /*
+         * TODO: later, pop a frame off a free-list of stack frames
+         */
 
-    frame->previous = previous;
-    inc_ref(previous);
+        fwprintf( stderr,
+                  L"make_empty_frame: about to set previous to %4.4s\n",
+                  pointer2cell( previous ).tag );
+        frame->previous = previous;
+        fputws( L"make_empty_frame: about to call inc_ref\n", stderr );
+        inc_ref( previous );
 
-    /*
-     * clearing the frame with memset would probably be slightly quicker, but
-     * this is clear.
-     */
-    frame->more = NIL;
-    frame->function = NIL;
-    frame->args = 0;
+        /*
+         * clearing the frame with memset would probably be slightly quicker, but
+         * this is clear.
+         */
+        frame->more = NIL;
+        frame->function = NIL;
+        frame->args = 0;
 
-    for ( int i = 0; i < args_in_frame; i++ ) {
-        set_reg( frame, i, NIL );
+        fputws( L"make_empty_frame: about to initialise arg registers\n",
+                stderr );
+        for ( int i = 0; i < args_in_frame; i++ ) {
+            set_reg( frame, i, NIL );
+        }
     }
-  }
+    fputws( L"Leaving make_empty_frame\n", stderr );
 
     return result;
 }
@@ -83,67 +102,76 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
  * @return the new frame, or an exception if one occurred while building it.
  */
 struct cons_pointer make_stack_frame( struct cons_pointer previous,
-                                     struct cons_pointer args,
-                                     struct cons_pointer env ) {
-  struct cons_pointer result = make_empty_frame( previous );
+                                      struct cons_pointer args,
+                                      struct cons_pointer env ) {
+    fputws( L"Entering make_stack_frame\n", stderr );
+    struct cons_pointer result = make_empty_frame( previous );
 
-  if (nilp(result))
-  {
-    /* i.e. out of memory */
-    result = make_exception(c_string_to_lisp_string( "Memory exhausted."), previous);
-  } else {
-    struct stack_frame * frame = get_stack_frame(result);
+    if ( nilp( result ) ) {
+        /* i.e. out of memory */
+        result =
+            make_exception( c_string_to_lisp_string( "Memory exhausted." ),
+                            previous );
+    } else {
+        struct stack_frame *frame = get_stack_frame( result );
 
-    for ( frame->args = 0; frame->args < args_in_frame && consp( args ); frame->args++ ) {
-      /* iterate down the arg list filling in the arg slots in the
-         * frame. When there are no more slots, if there are still args,
-         * stash them on more */
-      struct cons_space_object cell = pointer2cell( args );
+        for ( frame->args = 0; frame->args < args_in_frame && consp( args );
+              frame->args++ ) {
+            /* iterate down the arg list filling in the arg slots in the
+             * frame. When there are no more slots, if there are still args,
+             * stash them on more */
+            struct cons_space_object cell = pointer2cell( args );
 
-      /*
-         * TODO: if we were running on real massively parallel hardware,
-         * each arg except the first should be handed off to another
-         * processor to be evaled in parallel; but see notes here:
-         * https://github.com/simon-brooke/post-scarcity/wiki/parallelism
-         */
-      struct cons_pointer arg_frame_pointer = make_empty_frame( result);
-      inc_ref(arg_frame_pointer);
+            /*
+             * TODO: if we were running on real massively parallel hardware,
+             * each arg except the first should be handed off to another
+             * processor to be evaled in parallel; but see notes here:
+             * https://github.com/simon-brooke/post-scarcity/wiki/parallelism
+             */
+            struct cons_pointer arg_frame_pointer = make_empty_frame( result );
+            inc_ref( arg_frame_pointer );
 
-      if(nilp(arg_frame_pointer)) {
-        result = make_exception(c_string_to_lisp_string( "Memory exhausted."), previous);
-        break;
-      } else {
-        struct stack_frame *arg_frame = get_stack_frame( arg_frame_pointer );
-        set_reg( arg_frame, 0, cell.payload.cons.car );
+            if ( nilp( arg_frame_pointer ) ) {
+                result =
+                    make_exception( c_string_to_lisp_string
+                                    ( "Memory exhausted." ), previous );
+                break;
+            } else {
+                struct stack_frame *arg_frame =
+                    get_stack_frame( arg_frame_pointer );
+                set_reg( arg_frame, 0, cell.payload.cons.car );
 
-        struct cons_pointer val = lisp_eval( arg_frame, arg_frame_pointer, env );
-        if ( exceptionp( val ) ) {
-          result = val;
-          break;
-        } else {
-          set_reg( frame, frame->args, val );
+                struct cons_pointer val =
+                    lisp_eval( arg_frame, arg_frame_pointer, env );
+                if ( exceptionp( val ) ) {
+                    result = val;
+                    break;
+                } else {
+                    set_reg( frame, frame->args, val );
+                }
+
+                dec_ref( arg_frame_pointer );
+
+                args = cell.payload.cons.cdr;
+            }
         }
-
-        dec_ref(arg_frame_pointer);
-
-        args = cell.payload.cons.cdr;
-      }
-    }
-    if (!exceptionp(result)) {
-      if ( consp( args ) ) {
-        /* if we still have args, eval them and stick the values on `more` */
-        struct cons_pointer more = eval_forms( get_stack_frame(previous), previous, args, env );
-        frame->more = more;
-        inc_ref( more );
-      }
-
+        if ( !exceptionp( result ) ) {
+            if ( consp( args ) ) {
+                /* if we still have args, eval them and stick the values on `more` */
+                struct cons_pointer more =
+                    eval_forms( get_stack_frame( previous ), previous, args,
+                                env );
+                frame->more = more;
+                inc_ref( more );
+            }
 #ifdef DEBUG
-      dump_frame( stderr, result );
+            dump_frame( stderr, result );
 #endif
+        }
     }
-  }
+    fputws( L"Leaving make_stack_frame\n", stderr );
 
-  return result;
+    return result;
 }
 
 /**
@@ -157,36 +185,40 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
 struct cons_pointer make_special_frame( struct cons_pointer previous,
                                         struct cons_pointer args,
                                         struct cons_pointer env ) {
-  struct cons_pointer result = make_empty_frame( previous );
+    fputws( L"Entering make_special_frame\n", stderr );
 
-  if (nilp(result))
-  {
-    /* i.e. out of memory */
-    result = make_exception(c_string_to_lisp_string( "Memory exhausted."), previous);
-  } else {
-    struct stack_frame * frame = get_stack_frame(result);
+    struct cons_pointer result = make_empty_frame( previous );
 
-    for ( frame->args = 0; frame->args < args_in_frame && !nilp( args ); frame->args++ ) {
-        /* iterate down the arg list filling in the arg slots in the
-         * frame. When there are no more slots, if there are still args,
-         * stash them on more */
-        struct cons_space_object cell = pointer2cell( args );
+    if ( nilp( result ) ) {
+        /* i.e. out of memory */
+        result =
+            make_exception( c_string_to_lisp_string( "Memory exhausted." ),
+                            previous );
+    } else {
+        struct stack_frame *frame = get_stack_frame( result );
 
-        set_reg( frame, frame->args, cell.payload.cons.car );
+        for ( frame->args = 0; frame->args < args_in_frame && !nilp( args );
+              frame->args++ ) {
+            /* iterate down the arg list filling in the arg slots in the
+             * frame. When there are no more slots, if there are still args,
+             * stash them on more */
+            struct cons_space_object cell = pointer2cell( args );
 
-        args = cell.payload.cons.cdr;
-    }
-    if (!exceptionp(result)) {
-      if ( consp( args ) ) {
-        frame->more = args;
-        inc_ref( args );
-      }
+            set_reg( frame, frame->args, cell.payload.cons.car );
 
+            args = cell.payload.cons.cdr;
+        }
+        if ( !exceptionp( result ) ) {
+            if ( consp( args ) ) {
+                frame->more = args;
+                inc_ref( args );
+            }
 #ifdef DEBUG
-      dump_frame( stderr, result );
+            dump_frame( stderr, result );
 #endif
+        }
     }
-  }
+    fputws( L"Leaving make_special_frame\n", stderr );
 
     return result;
 }
@@ -215,37 +247,39 @@ void free_stack_frame( struct stack_frame *frame ) {
  * @param frame_pointer the pointer to the frame
  */
 void dump_frame( FILE * output, struct cons_pointer frame_pointer ) {
-  struct stack_frame *frame = get_stack_frame(frame_pointer);
+    struct stack_frame *frame = get_stack_frame( frame_pointer );
 
-  if (frame != NULL) {
-    for ( int arg = 0; arg < frame->args; arg++ ) {
-      struct cons_space_object cell = pointer2cell( frame->arg[arg] );
+    if ( frame != NULL ) {
+        for ( int arg = 0; arg < frame->args; arg++ ) {
+            struct cons_space_object cell = pointer2cell( frame->arg[arg] );
 
-      fwprintf( output, L"Arg %d:\t%c%c%c%c\tcount: %10u\tvalue: ", arg,
-               cell.tag.bytes[0],
-               cell.tag.bytes[1], cell.tag.bytes[2], cell.tag.bytes[3],
-               cell.count );
+            fwprintf( output, L"Arg %d:\t%c%c%c%c\tcount: %10u\tvalue: ", arg,
+                      cell.tag.bytes[0],
+                      cell.tag.bytes[1], cell.tag.bytes[2], cell.tag.bytes[3],
+                      cell.count );
 
-      print( output, frame->arg[arg] );
-      fputws( L"\n", output );
+            print( output, frame->arg[arg] );
+            fputws( L"\n", output );
+        }
+        fputws( L"More: \t", output );
+        print( output, frame->more );
+        fputws( L"\n", output );
     }
-    fputws( L"More: \t", output );
-    print( output, frame->more );
-    fputws( L"\n", output );
-  }
 }
 
-void dump_stack_trace(FILE * output, struct cons_pointer pointer) {
-  if (exceptionp(pointer)) {
-    print( output, pointer2cell(pointer).payload.exception.message );
-    fwprintf( output, L"\n" );
-    dump_stack_trace(output, pointer2cell(pointer).payload.exception.frame);
-  } else {
-    while (vectorpointp(pointer) && stackframep(pointer_to_vso(pointer))) {
-      dump_frame( output, pointer);
-      pointer = get_stack_frame(pointer)->previous;
+void dump_stack_trace( FILE * output, struct cons_pointer pointer ) {
+    if ( exceptionp( pointer ) ) {
+        print( output, pointer2cell( pointer ).payload.exception.message );
+        fwprintf( output, L"\n" );
+        dump_stack_trace( output,
+                          pointer2cell( pointer ).payload.exception.frame );
+    } else {
+        while ( vectorpointp( pointer )
+                && stackframep( pointer_to_vso( pointer ) ) ) {
+            dump_frame( output, pointer );
+            pointer = get_stack_frame( pointer )->previous;
+        }
     }
-  }
 }
 
 /**
diff --git a/src/memory/stack.h b/src/memory/stack.h
index df76849..20acd73 100644
--- a/src/memory/stack.h
+++ b/src/memory/stack.h
@@ -41,19 +41,19 @@
  */
 #define set_reg(frame,register,value)frame->arg[register]=value; inc_ref(value)
 
-struct stack_frame * get_stack_frame(struct cons_pointer pointer);
+struct stack_frame *get_stack_frame( struct cons_pointer pointer );
 
 struct cons_pointer make_empty_frame( struct cons_pointer previous );
 
 struct cons_pointer make_stack_frame( struct cons_pointer previous,
-                                     struct cons_pointer args,
-                                     struct cons_pointer env );
+                                      struct cons_pointer args,
+                                      struct cons_pointer env );
 
 void free_stack_frame( struct stack_frame *frame );
 
 void dump_frame( FILE * output, struct cons_pointer pointer );
 
-void dump_stack_trace(FILE * output, struct cons_pointer frame_pointer);
+void dump_stack_trace( FILE * output, struct cons_pointer frame_pointer );
 
 struct cons_pointer fetch_arg( struct stack_frame *frame, unsigned int n );
 
diff --git a/src/memory/vectorspace.c b/src/memory/vectorspace.c
index c0b6f8d..db39b48 100644
--- a/src/memory/vectorspace.c
+++ b/src/memory/vectorspace.c
@@ -30,12 +30,19 @@
  * NOTE that `tag` should be the vector-space tag of the particular type of
  * vector-space object, NOT `VECTORPOINTTAG`.
  */
-struct cons_pointer make_vec_pointer( char * tag, struct vector_space_object * address ) {
+struct cons_pointer make_vec_pointer( char *tag,
+                                      struct vector_space_object *address ) {
+    fputws( L"Entered make_vec_pointer\n", stderr );
     struct cons_pointer pointer = allocate_cell( VECTORPOINTTAG );
     struct cons_space_object cell = pointer2cell( pointer );
-
+    fwprintf( stderr,
+              L"make_vec_pointer: allocated cell, about to write tag '%s'\n",
+              tag );
     strncpy( &cell.payload.vectorp.tag.bytes[0], tag, 4 );
+    fputws( L"make_vec_pointer: tag written, about to set pointer address\n",
+            stderr );
     cell.payload.vectorp.address = address;
+    fputws( L"make_vec_pointer: all good, returning\n", stderr );
 
     return pointer;
 }
@@ -48,15 +55,18 @@ struct cons_pointer make_vec_pointer( char * tag, struct vector_space_object * a
  * Returns NIL if the vector could not be allocated due to memory exhaustion.
  */
 struct cons_pointer make_vso( char *tag, uint64_t payload_size ) {
+    fputws( L"Entered make_vso\n", stderr );
     struct cons_pointer result = NIL;
     int64_t total_size = sizeof( struct vector_space_header ) + payload_size;
 
     /* Pad size to 64 bit words. This is intended to promote access efficiancy
      * on 64 bit machines but may just be voodoo coding */
-    uint64_t padded = ceil((total_size * 8.0) / 8.0);
+    uint64_t padded = ceil( ( total_size * 8.0 ) / 8.0 );
+    fputws( L"make_vso: about to malloc\n", stderr );
     struct vector_space_object *vso = malloc( padded );
 
     if ( vso != NULL ) {
+        fwprintf( stderr, L"make_vso: about to write tag '%s'\n", tag );
         strncpy( &vso->header.tag.bytes[0], tag, TAGLENGTH );
         vso->header.vecp = make_vec_pointer( tag, vso );
         vso->header.size = payload_size;
@@ -65,13 +75,15 @@ struct cons_pointer make_vso( char *tag, uint64_t payload_size ) {
         fwprintf( stderr,
                   L"Allocated vector-space object of type %4.4s, total size %ld, payload size %ld\n",
                   tag, total_size, payload_size );
-  if (padded != total_size){
-    fwprintf(stderr, L"\t\tPadded from %d to %d\n",
-            total_size, padded);
-  }
+        if ( padded != total_size ) {
+            fwprintf( stderr, L"\t\tPadded from %d to %d\n",
+                      total_size, padded );
+        }
 #endif
 
         result = vso->header.vecp;
     }
+    fputws( L"make_vso: all good, returning\n", stderr );
+
     return result;
 }
diff --git a/src/memory/vectorspace.h b/src/memory/vectorspace.h
index 83fa74c..caec968 100644
--- a/src/memory/vectorspace.h
+++ b/src/memory/vectorspace.h
@@ -61,7 +61,7 @@ struct vector_space_header {
 };
 
 struct vector_space_object {
-  struct vector_space_header header;
+    struct vector_space_header header;
     char payload;               /* we'll malloc `size` bytes for payload,
                                  * `payload` is just the first of these.
                                  * TODO: this is almost certainly not
diff --git a/src/ops/equal.c b/src/ops/equal.c
index ebb085e..0f0597c 100644
--- a/src/ops/equal.c
+++ b/src/ops/equal.c
@@ -80,8 +80,8 @@ bool equal( struct cons_pointer a, struct cons_pointer b ) {
                     && ( equal( cell_a->payload.string.cdr,
                                 cell_b->payload.string.cdr )
                          || ( end_of_string( cell_a->payload.string.cdr )
-                              && end_of_string( cell_b->payload.string.
-                                                cdr ) ) );
+                              && end_of_string( cell_b->payload.
+                                                string.cdr ) ) );
                 break;
             case INTEGERTV:
                 result =
diff --git a/src/ops/lispops.c b/src/ops/lispops.c
index 825222f..1e6712d 100644
--- a/src/ops/lispops.c
+++ b/src/ops/lispops.c
@@ -89,9 +89,9 @@ struct cons_pointer eval_form( struct stack_frame *parent,
 
     struct cons_pointer result = NIL;
     struct cons_pointer next_pointer = make_empty_frame( parent_pointer );
-    inc_ref( next_pointer);
+    inc_ref( next_pointer );
 
-    struct stack_frame * next = get_stack_frame(next_pointer);
+    struct stack_frame *next = get_stack_frame( next_pointer );
     set_reg( next, 0, form );
 
     result = lisp_eval( next, next_pointer, env );
@@ -100,7 +100,7 @@ struct cons_pointer eval_form( struct stack_frame *parent,
         /* if we're returning an exception, we should NOT free the
          * stack frame. Corollary is, when we free an exception, we
          * should free all the frames it's holding on to. */
-        dec_ref(next_pointer);
+        dec_ref( next_pointer );
     }
 
     return result;
@@ -111,13 +111,15 @@ struct cons_pointer eval_form( struct stack_frame *parent,
  * and this `env`, and return a list of their values. If the arg passed as
  * `list` is not in fact a list, return nil.
  */
-struct cons_pointer eval_forms( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer eval_forms( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer list,
                                 struct cons_pointer env ) {
-  /* TODO: refactor. This runs up the C stack. */
+    /* TODO: refactor. This runs up the C stack. */
     return consp( list ) ?
         make_cons( eval_form( frame, frame_pointer, c_car( list ), env ),
-                   eval_forms( frame, frame_pointer, c_cdr( list ), env ) ) : NIL;
+                   eval_forms( frame, frame_pointer, c_cdr( list ),
+                               env ) ) : NIL;
 }
 
 /**
@@ -126,7 +128,8 @@ struct cons_pointer eval_forms( struct stack_frame *frame, struct cons_pointer f
  * (oblist)
  */
 struct cons_pointer
-lisp_oblist( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_oblist( struct stack_frame *frame, struct cons_pointer frame_pointer,
+             struct cons_pointer env ) {
     return oblist;
 }
 
@@ -159,7 +162,8 @@ struct cons_pointer compose_body( struct stack_frame *frame ) {
  * @param env the environment in which it is to be intepreted.
  */
 struct cons_pointer
-lisp_lambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_lambda( struct stack_frame *frame, struct cons_pointer frame_pointer,
+             struct cons_pointer env ) {
     return make_lambda( frame->arg[0], compose_body( frame ) );
 }
 
@@ -170,7 +174,8 @@ lisp_lambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struc
  * @param env the environment in which it is to be intepreted.
  */
 struct cons_pointer
-lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer,
+              struct cons_pointer env ) {
     return make_nlambda( frame->arg[0], compose_body( frame ) );
 }
 
@@ -188,8 +193,8 @@ void log_binding( struct cons_pointer name, struct cons_pointer val ) {
  * Evaluate a lambda or nlambda expression.
  */
 struct cons_pointer
-eval_lambda( struct cons_space_object cell, struct stack_frame *frame, struct cons_pointer frame_pointer,
-             struct cons_pointer env ) {
+eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
+             struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     fwprintf( stderr, L"eval_lambda called\n" );
 
@@ -216,7 +221,8 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame, struct co
         struct cons_pointer vals = frame->more;
 
         for ( int i = args_in_frame - 1; i >= 0; i-- ) {
-            struct cons_pointer val = eval_form( frame, frame_pointer, frame->arg[i], env );
+            struct cons_pointer val =
+                eval_form( frame, frame_pointer, frame->arg[i], env );
 
             if ( nilp( val ) && nilp( vals ) ) {  /* nothing */
             } else {
@@ -248,23 +254,25 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame, struct co
  * @return the result of evaluating the function with its arguments.
  */
 struct cons_pointer
-c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
+         struct cons_pointer env ) {
     struct cons_pointer result = NIL;
 
-  /* construct a child frame and within it evaluate the first argument - the
-   * argument in the function position. */
+    /* construct a child frame and within it evaluate the first argument - the
+     * argument in the function position. */
     struct cons_pointer fn_frame_pointer = make_empty_frame( frame_pointer );
-    inc_ref( fn_frame_pointer);
-    struct stack_frame *fn_frame = get_stack_frame(fn_frame_pointer);
+    inc_ref( fn_frame_pointer );
+    struct stack_frame *fn_frame = get_stack_frame( fn_frame_pointer );
 
     set_reg( fn_frame, 0, c_car( frame->arg[0] ) );
-    struct cons_pointer fn_pointer = lisp_eval( fn_frame, fn_frame_pointer, env );
+    struct cons_pointer fn_pointer =
+        lisp_eval( fn_frame, fn_frame_pointer, env );
 
     if ( !exceptionp( result ) ) {
         /* if we're returning an exception, we should NOT free the
          * stack frame. Corollary is, when we free an exception, we
          * should free all the frames it's holding on to. */
-        dec_ref(fn_frame_pointer);
+        dec_ref( fn_frame_pointer );
     }
 
     struct cons_space_object fn_cell = pointer2cell( fn_pointer );
@@ -280,14 +288,17 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct co
                 struct cons_pointer exep = NIL;
                 struct cons_pointer next_pointer =
                     make_stack_frame( frame_pointer, args, env );
-              inc_ref(next_pointer);
+                inc_ref( next_pointer );
                 if ( exceptionp( next_pointer ) ) {
                     result = next_pointer;
                 } else {
-                struct stack_frame *next = get_stack_frame(next_pointer);
+                    struct stack_frame *next = get_stack_frame( next_pointer );
 
-                result = ( *fn_cell.payload.function.executable ) ( next, next_pointer, env );
-                  dec_ref(next_pointer);
+                    result =
+                        ( *fn_cell.payload.function.executable ) ( next,
+                                                                   next_pointer,
+                                                                   env );
+                    dec_ref( next_pointer );
                 }
             }
             break;
@@ -296,48 +307,53 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct co
                 struct cons_pointer exep = NIL;
                 struct cons_pointer next_pointer =
                     make_stack_frame( frame_pointer, args, env );
-                inc_ref(next_pointer);
-              if ( exceptionp( next_pointer ) ) {
+                inc_ref( next_pointer );
+                if ( exceptionp( next_pointer ) ) {
                     result = next_pointer;
                 } else {
-                struct stack_frame *next = get_stack_frame(next_pointer);
-                result = eval_lambda( fn_cell, next, next_pointer, env );
-                if ( !exceptionp( result ) ) {
-                    dec_ref(next_pointer);
+                    struct stack_frame *next = get_stack_frame( next_pointer );
+                    result = eval_lambda( fn_cell, next, next_pointer, env );
+                    if ( !exceptionp( result ) ) {
+                        dec_ref( next_pointer );
+                    }
                 }
-              }
             }
             break;
         case NLAMBDATV:
             {
                 struct cons_pointer next_pointer =
-                     make_special_frame( frame_pointer, args, env );
-              inc_ref(next_pointer);
-              if ( exceptionp( next_pointer ) ) {
+                    make_special_frame( frame_pointer, args, env );
+                inc_ref( next_pointer );
+                if ( exceptionp( next_pointer ) ) {
                     result = next_pointer;
                 } else {
-                struct stack_frame *next = get_stack_frame(frame_pointer);
-              result = eval_lambda( fn_cell, next, next_pointer, env );
-                if ( !exceptionp( result ) ) {
-                    dec_ref(next_pointer);
+                    struct stack_frame *next =
+                        get_stack_frame( frame_pointer );
+                    result = eval_lambda( fn_cell, next, next_pointer, env );
+                    if ( !exceptionp( result ) ) {
+                        dec_ref( next_pointer );
+                    }
                 }
-              }
             }
             break;
         case SPECIALTV:
             {
                 struct cons_pointer next_pointer =
-                     make_special_frame( frame_pointer, args, env );
-              inc_ref(next_pointer);
-              if ( exceptionp( next_pointer ) ) {
+                    make_special_frame( frame_pointer, args, env );
+                inc_ref( next_pointer );
+                if ( exceptionp( next_pointer ) ) {
                     result = next_pointer;
                 } else {
-                struct stack_frame *next = get_stack_frame(frame_pointer);
-                result = ( *fn_cell.payload.special.executable ) ( next, next_pointer, env );
-                if ( !exceptionp( result ) ) {
-                    dec_ref(next_pointer);
+                    struct stack_frame *next =
+                        get_stack_frame( frame_pointer );
+                    result =
+                        ( *fn_cell.payload.special.executable ) ( next,
+                                                                  next_pointer,
+                                                                  env );
+                    if ( !exceptionp( result ) ) {
+                        dec_ref( next_pointer );
+                    }
                 }
-              }
             }
             break;
         default:
@@ -355,7 +371,7 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct co
                 result = throw_exception( message, frame_pointer );
             }
     }
-  dec_ref(fn_frame_pointer);
+    dec_ref( fn_frame_pointer );
 
     return result;
 }
@@ -393,7 +409,8 @@ struct cons_pointer c_type( struct cons_pointer pointer ) {
  * If a special form, passes the cdr of s_expr to the special form as argument.
  */
 struct cons_pointer
-lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env ) {
     struct cons_pointer result = frame->arg[0];
     struct cons_space_object cell = pointer2cell( frame->arg[0] );
 
@@ -456,7 +473,8 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * the second argument
  */
 struct cons_pointer
-lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env ) {
 #ifdef DEBUG
     fputws( L"Apply: ", stderr );
     dump_frame( stderr, frame_pointer );
@@ -484,7 +502,8 @@ lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * this isn't at this stage checked) unevaluated.
  */
 struct cons_pointer
-lisp_quote( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_quote( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env ) {
     return frame->arg[0];
 }
 
@@ -499,7 +518,8 @@ lisp_quote( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * the namespace in so doing. `namespace` defaults to the value of `oblist`.
  */
 struct cons_pointer
-lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer,
+          struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_pointer namespace =
         nilp( frame->arg[2] ) ? oblist : frame->arg[2];
@@ -512,7 +532,8 @@ lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer, struct c
             make_exception( make_cons
                             ( c_string_to_lisp_string
                               ( "The first argument to `set!` is not a symbol: " ),
-                              make_cons( frame->arg[0], NIL ) ), frame_pointer );
+                              make_cons( frame->arg[0], NIL ) ),
+                            frame_pointer );
     }
 
     return result;
@@ -529,13 +550,15 @@ lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer, struct c
  * the namespace in so doing. `namespace` defaults to the value of `oblist`.
  */
 struct cons_pointer
-lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer,
+                 struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     struct cons_pointer namespace =
         nilp( frame->arg[2] ) ? oblist : frame->arg[2];
 
     if ( symbolp( frame->arg[0] ) ) {
-        struct cons_pointer val = eval_form( frame, frame_pointer, frame->arg[1], env );
+        struct cons_pointer val =
+            eval_form( frame, frame_pointer, frame->arg[1], env );
         deep_bind( frame->arg[0], val );
         result = val;
     } else {
@@ -543,7 +566,8 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, s
             make_exception( make_cons
                             ( c_string_to_lisp_string
                               ( "The first argument to `set!` is not a symbol: " ),
-                              make_cons( frame->arg[0], NIL ) ), frame_pointer );
+                              make_cons( frame->arg[0], NIL ) ),
+                            frame_pointer );
     }
 
     return result;
@@ -558,7 +582,8 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, s
  * otherwise returns a new cons cell.
  */
 struct cons_pointer
-lisp_cons( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_cons( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env ) {
     struct cons_pointer car = frame->arg[0];
     struct cons_pointer cdr = frame->arg[1];
     struct cons_pointer result;
@@ -582,7 +607,8 @@ lisp_cons( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * strings, and TODO read streams and other things which can be considered as sequences.
  */
 struct cons_pointer
-lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer,
+          struct cons_pointer env ) {
     struct cons_pointer result = NIL;
 
     if ( consp( frame->arg[0] ) ) {
@@ -606,7 +632,8 @@ lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer, struct c
  * strings, and TODO read streams and other things which can be considered as sequences.
  */
 struct cons_pointer
-lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer,
+          struct cons_pointer env ) {
     struct cons_pointer result = NIL;
 
     if ( consp( frame->arg[0] ) ) {
@@ -629,7 +656,8 @@ lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer, struct c
  * Returns the value associated with key in store, or NIL if not found.
  */
 struct cons_pointer
-lisp_assoc( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_assoc( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env ) {
     return c_assoc( frame->arg[0], frame->arg[1] );
 }
 
@@ -637,7 +665,8 @@ lisp_assoc( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * (eq a b)
  * Returns T if a and b are pointers to the same object, else NIL
  */
-struct cons_pointer lisp_eq( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_eq( struct stack_frame *frame,
+                             struct cons_pointer frame_pointer,
                              struct cons_pointer env ) {
     return eq( frame->arg[0], frame->arg[1] ) ? TRUE : NIL;
 }
@@ -647,7 +676,8 @@ struct cons_pointer lisp_eq( struct stack_frame *frame, struct cons_pointer fram
  * Returns T if a and b are pointers to structurally identical objects, else NIL
  */
 struct cons_pointer
-lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env ) {
     return equal( frame->arg[0], frame->arg[1] ) ? TRUE : NIL;
 }
 
@@ -658,7 +688,8 @@ lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * is a read stream, then read from that stream, else stdin.
  */
 struct cons_pointer
-lisp_read( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_read( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env ) {
     FILE *input = stdin;
 
     if ( readp( frame->arg[0] ) ) {
@@ -698,7 +729,8 @@ struct cons_pointer c_reverse( struct cons_pointer arg ) {
  * (reverse sequence)
  * Return a sequence like this sequence but with the members in the reverse order.
  */
-struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_reverse( struct stack_frame *frame,
+                                  struct cons_pointer frame_pointer,
                                   struct cons_pointer env ) {
     return c_reverse( frame->arg[0] );
 }
@@ -711,9 +743,10 @@ struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer
  * is a write stream, then print to that stream, else stdout.
  */
 struct cons_pointer
-lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env ) {
 #ifdef DEBUG
-  fputws(L"Entering print\n", stderr);
+    fputws( L"Entering print\n", stderr );
 #endif
     struct cons_pointer result = NIL;
     FILE *output = stdout;
@@ -741,7 +774,8 @@ lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * @return As a Lisp string, the tag of the object which is the argument.
  */
 struct cons_pointer
-lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env ) {
     return c_type( frame->arg[0] );
 }
 
@@ -759,7 +793,8 @@ lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * argument.
  */
 struct cons_pointer
-lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env ) {
     struct cons_pointer remaining = frame->more;
     struct cons_pointer result = NIL;
 
@@ -786,7 +821,8 @@ lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * @return the value of the last form of the first successful clause.
  */
 struct cons_pointer
-lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
+lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env ) {
     struct cons_pointer result = NIL;
     bool done = false;
 
@@ -797,11 +833,14 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
 
         if ( consp( clause_pointer ) ) {
             struct cons_space_object cell = pointer2cell( clause_pointer );
-            result = eval_form( frame, frame_pointer, c_car( clause_pointer ), env );
+            result =
+                eval_form( frame, frame_pointer, c_car( clause_pointer ),
+                           env );
 
             if ( !nilp( result ) ) {
                 struct cons_pointer vals =
-                    eval_forms( frame, frame_pointer,c_cdr( clause_pointer ), env );
+                    eval_forms( frame, frame_pointer, c_cdr( clause_pointer ),
+                                env );
 
                 while ( consp( vals ) ) {
                     result = c_car( vals );
@@ -814,8 +853,8 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
             done = true;
         } else {
             result = throw_exception( c_string_to_lisp_string
-                                 ( "Arguments to `cond` must be lists" ),
-                                 frame_pointer);
+                                      ( "Arguments to `cond` must be lists" ),
+                                      frame_pointer );
         }
     }
     /* TODO: if there are more than 8 clauses we need to continue into the
@@ -835,7 +874,8 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * pointer to the frame in which the exception occurred.
  */
 struct cons_pointer
-throw_exception( struct cons_pointer message, struct cons_pointer frame_pointer ) {
+throw_exception( struct cons_pointer message,
+                 struct cons_pointer frame_pointer ) {
     fwprintf( stderr, L"\nERROR: " );
     print( stderr, message );
     struct cons_pointer result = NIL;
@@ -861,7 +901,9 @@ throw_exception( struct cons_pointer message, struct cons_pointer frame_pointer
  * If `message` is itself an exception, returns that instead.
  */
 struct cons_pointer
-lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env ) {
-  struct cons_pointer message = frame->arg[0];
-  return exceptionp(message) ? message : make_exception(message, frame->previous);
+lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer,
+                struct cons_pointer env ) {
+    struct cons_pointer message = frame->arg[0];
+    return exceptionp( message ) ? message : make_exception( message,
+                                                             frame->previous );
 }
diff --git a/src/ops/lispops.h b/src/ops/lispops.h
index 059255d..a1dee81 100644
--- a/src/ops/lispops.h
+++ b/src/ops/lispops.h
@@ -60,7 +60,8 @@ struct cons_pointer eval_form( struct stack_frame *parent,
  * and this `env`, and return a list of their values. If the arg passed as
  * `list` is not in fact a list, return nil.
  */
-struct cons_pointer eval_forms( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer eval_forms( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer list,
                                 struct cons_pointer env );
 
@@ -68,19 +69,24 @@ struct cons_pointer eval_forms( struct stack_frame *frame, struct cons_pointer f
 /*
  * special forms
  */
-struct cons_pointer lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_eval( struct stack_frame *frame,
+                               struct cons_pointer frame_pointer,
                                struct cons_pointer env );
-struct cons_pointer lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_apply( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
 
 struct cons_pointer
-lisp_oblist( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_oblist( struct stack_frame *frame, struct cons_pointer frame_pointer,
+             struct cons_pointer env );
 
 struct cons_pointer
-lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer,
+          struct cons_pointer env );
 
 struct cons_pointer
-lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer,
+                 struct cons_pointer env );
 
 /**
  * Construct an interpretable function.
@@ -89,7 +95,8 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer, s
  * @param lexpr the lambda expression to be interpreted;
  * @param env the environment in which it is to be intepreted.
  */
-struct cons_pointer lisp_lambda( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_lambda( struct stack_frame *frame,
+                                 struct cons_pointer frame_pointer,
                                  struct cons_pointer env );
 
 /**
@@ -99,31 +106,42 @@ struct cons_pointer lisp_lambda( struct stack_frame *frame, struct cons_pointer
  * @param env the environment in which it is to be intepreted.
  */
 struct cons_pointer
-lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer,
+              struct cons_pointer env );
 
-struct cons_pointer lisp_quote( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_quote( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
 
 /*
  * functions
  */
-struct cons_pointer lisp_cons( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_cons( struct stack_frame *frame,
+                               struct cons_pointer frame_pointer,
                                struct cons_pointer env );
-struct cons_pointer lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_car( struct stack_frame *frame,
+                              struct cons_pointer frame_pointer,
                               struct cons_pointer env );
-struct cons_pointer lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_cdr( struct stack_frame *frame,
+                              struct cons_pointer frame_pointer,
                               struct cons_pointer env );
-struct cons_pointer lisp_assoc( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_assoc( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
-struct cons_pointer lisp_eq( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_eq( struct stack_frame *frame,
+                             struct cons_pointer frame_pointer,
                              struct cons_pointer env );
-struct cons_pointer lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_equal( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
-struct cons_pointer lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_print( struct stack_frame *frame,
+                                struct cons_pointer frame_pointer,
                                 struct cons_pointer env );
-struct cons_pointer lisp_read( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_read( struct stack_frame *frame,
+                               struct cons_pointer frame_pointer,
                                struct cons_pointer env );
-struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer frame_pointer,
+struct cons_pointer lisp_reverse( struct stack_frame *frame,
+                                  struct cons_pointer frame_pointer,
                                   struct cons_pointer env );
 /**
  * Function: Get the Lisp type of the single argument.
@@ -132,7 +150,8 @@ struct cons_pointer lisp_reverse( struct stack_frame *frame, struct cons_pointer
  * @return As a Lisp string, the tag of the object which is the argument.
  */
 struct cons_pointer
-lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env );
 
 
 /**
@@ -146,7 +165,8 @@ lisp_type( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * argument.
  */
 struct cons_pointer
-lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer,
+            struct cons_pointer env );
 
 /**
  * Special form: conditional. Each arg is expected to be a list; if the first
@@ -158,7 +178,8 @@ lisp_progn( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * @return the value of the last form of the first successful clause.
  */
 struct cons_pointer
-lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer,
+           struct cons_pointer env );
 
 /**
  * Throw an exception.
@@ -167,7 +188,8 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer, struct
  * real `throw_exception`, which does, will be needed.
  */
 struct cons_pointer throw_exception( struct cons_pointer message,
-                                struct cons_pointer frame_pointer );
+                                     struct cons_pointer frame_pointer );
 
 struct cons_pointer
-lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer, struct cons_pointer env );
+lisp_exception( struct stack_frame *frame, struct cons_pointer frame_pointer,
+                struct cons_pointer env );
diff --git a/src/ops/print.c b/src/ops/print.c
index 7efd59f..99cd7f3 100644
--- a/src/ops/print.c
+++ b/src/ops/print.c
@@ -119,7 +119,7 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
         case EXCEPTIONTV:
             fwprintf( output, L"\n%sException: ",
                       print_use_colours ? "\x1B[31m" : "" );
-            dump_stack_trace(output, pointer);
+            dump_stack_trace( output, pointer );
             break;
         case FUNCTIONTV:
             fwprintf( output, L"(Function)" );
@@ -133,8 +133,8 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
         case LAMBDATV:
             print( output, make_cons( c_string_to_lisp_symbol( "lambda" ),
                                       make_cons( cell.payload.lambda.args,
-                                                 cell.payload.
-                                                 lambda.body ) ) );
+                                                 cell.payload.lambda.
+                                                 body ) ) );
             break;
         case NILTV:
             fwprintf( output, L"nil" );
@@ -142,8 +142,8 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
         case NLAMBDATV:
             print( output, make_cons( c_string_to_lisp_symbol( "nlambda" ),
                                       make_cons( cell.payload.lambda.args,
-                                                 cell.payload.
-                                                 lambda.body ) ) );
+                                                 cell.payload.lambda.
+                                                 body ) ) );
             break;
         case RATIOTV:
             print( output, cell.payload.ratio.dividend );
diff --git a/src/ops/read.c b/src/ops/read.c
index 1a09700..7d21dbe 100644
--- a/src/ops/read.c
+++ b/src/ops/read.c
@@ -34,10 +34,11 @@
  */
 
 struct cons_pointer read_number( struct stack_frame *frame,
-                                struct cons_pointer frame_pointer, FILE * input,
-                                 wint_t initial, bool seen_period );
+                                 struct cons_pointer frame_pointer,
+                                 FILE * input, wint_t initial,
+                                 bool seen_period );
 struct cons_pointer read_list( struct stack_frame *frame,
-                              struct cons_pointer frame_pointer, FILE * input,
+                               struct cons_pointer frame_pointer, FILE * input,
                                wint_t initial );
 struct cons_pointer read_string( FILE * input, wint_t initial );
 struct cons_pointer read_symbol( FILE * input, wint_t initial );
@@ -55,8 +56,9 @@ struct cons_pointer c_quote( struct cons_pointer arg ) {
  * treating this initial character as the first character of the object
  * representation.
  */
-struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_pointer frame_pointer, FILE * input,
-                                       wint_t initial ) {
+struct cons_pointer read_continuation( struct stack_frame *frame,
+                                       struct cons_pointer frame_pointer,
+                                       FILE * input, wint_t initial ) {
     struct cons_pointer result = NIL;
 
     wint_t c;
@@ -76,15 +78,18 @@ struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_po
                 break;
             case EOF:
                 result = throw_exception( c_string_to_lisp_string
-                                     ( "End of input while reading" ), frame_pointer );
+                                          ( "End of input while reading" ),
+                                          frame_pointer );
                 break;
             case '\'':
                 result =
                     c_quote( read_continuation
-                             ( frame, frame_pointer, input, fgetwc( input ) ) );
+                             ( frame, frame_pointer, input,
+                               fgetwc( input ) ) );
                 break;
             case '(':
-                result = read_list( frame, frame_pointer, input, fgetwc( input ) );
+                result =
+                    read_list( frame, frame_pointer, input, fgetwc( input ) );
                 break;
             case '"':
                 result = read_string( input, fgetwc( input ) );
@@ -93,7 +98,9 @@ struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_po
                     wint_t next = fgetwc( input );
                     ungetwc( next, input );
                     if ( iswdigit( next ) ) {
-                        result = read_number( frame, frame_pointer, input, c, false );
+                        result =
+                            read_number( frame, frame_pointer, input, c,
+                                         false );
                     } else {
                         result = read_symbol( input, c );
                     }
@@ -104,12 +111,15 @@ struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_po
                     wint_t next = fgetwc( input );
                     if ( iswdigit( next ) ) {
                         ungetwc( next, input );
-                        result = read_number( frame, frame_pointer, input, c, true );
+                        result =
+                            read_number( frame, frame_pointer, input, c,
+                                         true );
                     } else if ( iswblank( next ) ) {
                         /* dotted pair. TODO: this isn't right, we
                          * really need to backtrack up a level. */
                         result =
-                            read_continuation( frame, frame_pointer, input, fgetwc( input ) );
+                            read_continuation( frame, frame_pointer, input,
+                                               fgetwc( input ) );
                     } else {
                         read_symbol( input, c );
                     }
@@ -117,7 +127,8 @@ struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_po
                 break;
             default:
                 if ( iswdigit( c ) ) {
-                    result = read_number( frame, frame_pointer, input, c, false );
+                    result =
+                        read_number( frame, frame_pointer, input, c, false );
                 } else if ( iswprint( c ) ) {
                     result = read_symbol( input, c );
                 } else {
@@ -140,8 +151,8 @@ struct cons_pointer read_continuation( struct stack_frame *frame, struct cons_po
  * input stream into a Lisp string, and then convert it to a number.
  */
 struct cons_pointer read_number( struct stack_frame *frame,
-                                struct cons_pointer frame_pointer,
-                                FILE * input,
+                                 struct cons_pointer frame_pointer,
+                                 FILE * input,
                                  wint_t initial, bool seen_period ) {
     struct cons_pointer result = NIL;
     int64_t accumulator = 0;
@@ -222,17 +233,21 @@ struct cons_pointer read_number( struct stack_frame *frame,
  * left parenthesis.
  */
 struct cons_pointer read_list( struct stack_frame *frame,
-                              struct cons_pointer frame_pointer,
-                              FILE * input, wint_t initial ) {
+                               struct cons_pointer frame_pointer,
+                               FILE * input, wint_t initial ) {
     struct cons_pointer result = NIL;
     if ( initial != ')' ) {
 #ifdef DEBUG
         fwprintf( stderr,
                   L"read_list starting '%C' (%d)\n", initial, initial );
 #endif
-        struct cons_pointer car = read_continuation( frame, frame_pointer, input,
-                                                     initial );
-        result = make_cons( car, read_list( frame, frame_pointer, input, fgetwc( input ) ) );
+        struct cons_pointer car =
+            read_continuation( frame, frame_pointer, input,
+                               initial );
+        result =
+            make_cons( car,
+                       read_list( frame, frame_pointer, input,
+                                  fgetwc( input ) ) );
     }
 #ifdef DEBUG
     else {
@@ -323,6 +338,7 @@ struct cons_pointer read_symbol( FILE * input, wint_t initial ) {
  */
 struct cons_pointer read( struct
                           stack_frame
-                          *frame, struct cons_pointer frame_pointer, FILE * input ) {
+                          *frame, struct cons_pointer frame_pointer,
+                          FILE * input ) {
     return read_continuation( frame, frame_pointer, input, fgetwc( input ) );
 }
diff --git a/src/ops/read.h b/src/ops/read.h
index c144699..c6dbba3 100644
--- a/src/ops/read.h
+++ b/src/ops/read.h
@@ -15,7 +15,6 @@
  * read the next object on this input stream and return a cons_pointer to it.
  */
 struct cons_pointer read( struct stack_frame *frame,
-                         struct cons_pointer frame_pointer,
-                         FILE * input );
+                          struct cons_pointer frame_pointer, FILE * input );
 
 #endif
diff --git a/src/repl.c b/src/repl.c
index 5dd6567..d077ba8 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -31,64 +31,65 @@
  * Dummy up a Lisp read call with its own stack frame.
  */
 struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
-  struct cons_pointer result = NIL;
-  struct cons_pointer frame_pointer = make_empty_frame( NIL );
-  if (!nilp(frame_pointer)) {
-    inc_ref(frame_pointer);
-    struct stack_frame *frame = get_stack_frame(frame_pointer);
+    struct cons_pointer result = NIL;
+    struct cons_pointer frame_pointer = make_empty_frame( NIL );
+    if ( !nilp( frame_pointer ) ) {
+        inc_ref( frame_pointer );
+        struct stack_frame *frame = get_stack_frame( frame_pointer );
 
-    if (frame != NULL){
+        if ( frame != NULL ) {
 
-      set_reg( frame, 0, stream_pointer );
-      struct cons_pointer result = lisp_read( frame, frame_pointer, oblist );
+            set_reg( frame, 0, stream_pointer );
+            struct cons_pointer result =
+                lisp_read( frame, frame_pointer, oblist );
+        }
+        dec_ref( frame_pointer );
     }
-    dec_ref(frame_pointer);
-  }
 
-  return result;
+    return result;
 }
 
 /**
  * Dummy up a Lisp eval call with its own stack frame.
  */
 struct cons_pointer repl_eval( struct cons_pointer input ) {
-  struct cons_pointer result = NIL;
-  struct cons_pointer frame_pointer = make_empty_frame( NIL );
-  if (!nilp(frame_pointer)) {
-    inc_ref(frame_pointer);
-    struct stack_frame *frame = get_stack_frame(frame_pointer);
+    struct cons_pointer result = NIL;
+    struct cons_pointer frame_pointer = make_empty_frame( NIL );
+    if ( !nilp( frame_pointer ) ) {
+        inc_ref( frame_pointer );
+        struct stack_frame *frame = get_stack_frame( frame_pointer );
 
-    if (frame != NULL){
-      set_reg( frame, 0, input );
-      result = lisp_eval( frame, frame_pointer, oblist );
+        if ( frame != NULL ) {
+            set_reg( frame, 0, input );
+            result = lisp_eval( frame, frame_pointer, oblist );
+        }
+
+        dec_ref( frame_pointer );
     }
 
-    dec_ref(frame_pointer);
-  }
-
-  return result;
+    return result;
 }
 
 /**
  * Dummy up a Lisp print call with its own stack frame.
  */
 struct cons_pointer repl_print( struct cons_pointer stream_pointer,
-                               struct cons_pointer value ) {
-  struct cons_pointer result = NIL;
-  struct cons_pointer frame_pointer = make_empty_frame( NIL );
-  if (!nilp(frame_pointer)) {
-    struct stack_frame *frame = get_stack_frame(frame_pointer);
+                                struct cons_pointer value ) {
+    struct cons_pointer result = NIL;
+    struct cons_pointer frame_pointer = make_empty_frame( NIL );
+    if ( !nilp( frame_pointer ) ) {
+        struct stack_frame *frame = get_stack_frame( frame_pointer );
 
-    if (frame != NULL){
-      set_reg( frame, 0, value );
-      set_reg( frame, 1, stream_pointer );
-      result = lisp_print( frame, frame_pointer, oblist );
-      free_stack_frame( frame );
+        if ( frame != NULL ) {
+            set_reg( frame, 0, value );
+            set_reg( frame, 1, stream_pointer );
+            result = lisp_print( frame, frame_pointer, oblist );
+            free_stack_frame( frame );
+        }
+        dec_ref( frame_pointer );
     }
-    dec_ref(frame_pointer);
-  }
 
-  return result;
+    return result;
 }
 
 /**

From 75abfb4050f7c6c74f7d913cc44a6b2f72d79758 Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Thu, 27 Dec 2018 21:37:38 +0000
Subject: [PATCH 3/6] Much better debugging, but it still doesn't work

---
 Doxyfile                     | 138 +++++++++++++++++------------------
 Makefile                     |   2 +-
 src/arith/integer.c          |   5 +-
 src/arith/peano.c            |  45 +++++-------
 src/arith/ratio.c            |   7 +-
 src/arith/real.c             |   6 +-
 src/debug.c                  |  65 +++++++++++++++++
 src/debug.h                  |  28 +++++++
 src/init.c                   |  22 +++++-
 src/memory/conspage.c        |   3 +-
 src/memory/conspage.h        |   4 +-
 src/memory/consspaceobject.h |  11 +--
 src/memory/cursor.c          |   9 +++
 src/memory/cursor.h          | Bin 0 -> 614 bytes
 src/memory/dump.c            |  17 ++++-
 src/memory/stack.c           |  63 +++++++++-------
 src/memory/stack.h           |   4 +-
 src/memory/vectorspace.c     |  42 ++++++-----
 src/memory/vectorspace.h     |   2 +-
 src/ops/intern.c             |  31 +++++---
 src/ops/lispops.c            |  79 ++++++++++----------
 src/ops/read.c               |  26 +++----
 src/repl.c                   |  19 ++++-
 23 files changed, 395 insertions(+), 233 deletions(-)
 create mode 100644 src/debug.c
 create mode 100644 src/debug.h
 create mode 100644 src/memory/cursor.c
 create mode 100644 src/memory/cursor.h

diff --git a/Doxyfile b/Doxyfile
index b94ec20..955cb32 100644
--- a/Doxyfile
+++ b/Doxyfile
@@ -32,13 +32,13 @@ DOXYFILE_ENCODING      = UTF-8
 # title of most generated pages and in a few other places.
 # The default value is: My Project.
 
-PROJECT_NAME           = "\"Post Scarcity\""
+PROJECT_NAME           = "Post Scarcity"
 
 # The PROJECT_NUMBER tag can be used to enter a project or revision number. This
 # could be handy for archiving the generated documentation or if some version
 # control system is used.
 
-PROJECT_NUMBER         = 
+PROJECT_NUMBER         =
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description
 # for a project that appears at the top of each page and should give viewer a
@@ -51,14 +51,14 @@ PROJECT_BRIEF          = "A prototype for a post scarcity programming environmen
 # pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
 # the logo to the output directory.
 
-PROJECT_LOGO           = 
+PROJECT_LOGO           =
 
 # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
 # into which the generated documentation will be written. If a relative path is
 # entered, it will be relative to the location where doxygen was started. If
 # left blank the current directory will be used.
 
-OUTPUT_DIRECTORY       = /home/simon/workspace/post-scarcity/doc
+OUTPUT_DIRECTORY       = doc
 
 # If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
 # directories (in 2 levels) under the output directory of each output format and
@@ -162,7 +162,7 @@ FULL_PATH_NAMES        = YES
 # will be relative from the directory where doxygen is started.
 # This tag requires that the tag FULL_PATH_NAMES is set to YES.
 
-STRIP_FROM_PATH        = 
+STRIP_FROM_PATH        =
 
 # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
 # path mentioned in the documentation of a class, which tells the reader which
@@ -171,7 +171,7 @@ STRIP_FROM_PATH        =
 # specify the list of include paths that are normally passed to the compiler
 # using the -I flag.
 
-STRIP_FROM_INC_PATH    = 
+STRIP_FROM_INC_PATH    =
 
 # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
 # less readable) file names. This can be useful is your file systems doesn't
@@ -238,13 +238,13 @@ TAB_SIZE               = 4
 # "Side Effects:". You can put \n's in the value part of an alias to insert
 # newlines.
 
-ALIASES                = 
+ALIASES                =
 
 # This tag can be used to specify a number of word-keyword mappings (TCL only).
 # A mapping has the form "name=value". For example adding "class=itcl::class"
 # will allow you to use the command class in the itcl::class meaning.
 
-TCL_SUBST              = 
+TCL_SUBST              =
 
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
 # only. Doxygen will then generate output that is more tailored for C. For
@@ -291,7 +291,7 @@ OPTIMIZE_OUTPUT_VHDL   = NO
 # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
 # the files are not read by doxygen.
 
-EXTENSION_MAPPING      = 
+EXTENSION_MAPPING      =
 
 # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
 # according to the Markdown format, which allows for more readable
@@ -648,7 +648,7 @@ GENERATE_DEPRECATEDLIST= YES
 # sections, marked by \if <section_label> ... \endif and \cond <section_label>
 # ... \endcond blocks.
 
-ENABLED_SECTIONS       = 
+ENABLED_SECTIONS       =
 
 # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
 # initial value of a variable or macro / define can have for it to appear in the
@@ -690,7 +690,7 @@ SHOW_NAMESPACES        = YES
 # by doxygen. Whatever the program writes to standard output is used as the file
 # version. For an example see the documentation.
 
-FILE_VERSION_FILTER    = 
+FILE_VERSION_FILTER    =
 
 # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
 # by doxygen. The layout file controls the global structure of the generated
@@ -703,7 +703,7 @@ FILE_VERSION_FILTER    =
 # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
 # tag is left empty.
 
-LAYOUT_FILE            = 
+LAYOUT_FILE            =
 
 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
 # the reference definitions. This must be a list of .bib files. The .bib
@@ -713,7 +713,7 @@ LAYOUT_FILE            =
 # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
 # search path. See also \cite for info how to create references.
 
-CITE_BIB_FILES         = 
+CITE_BIB_FILES         =
 
 #---------------------------------------------------------------------------
 # Configuration options related to warning and progress messages
@@ -778,7 +778,7 @@ WARN_FORMAT            = "$file:$line: $text"
 # messages should be written. If left blank the output is written to standard
 # error (stderr).
 
-WARN_LOGFILE           = 
+WARN_LOGFILE           = doxy.log
 
 #---------------------------------------------------------------------------
 # Configuration options related to the input files
@@ -790,7 +790,7 @@ WARN_LOGFILE           =
 # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
 # Note: If this tag is empty the current directory is searched.
 
-INPUT                  = /home/simon/workspace/post-scarcity/src
+INPUT                  = src src/arith src/memory src/ops
 
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -873,7 +873,7 @@ RECURSIVE              = NO
 # Note that relative paths are relative to the directory from which doxygen is
 # run.
 
-EXCLUDE                = 
+EXCLUDE                =
 
 # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
 # directories that are symbolic links (a Unix file system feature) are excluded
@@ -889,7 +889,7 @@ EXCLUDE_SYMLINKS       = NO
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       = 
+EXCLUDE_PATTERNS       =
 
 # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
 # (namespaces, classes, functions, etc.) that should be excluded from the
@@ -900,13 +900,13 @@ EXCLUDE_PATTERNS       =
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories use the pattern */test/*
 
-EXCLUDE_SYMBOLS        = 
+EXCLUDE_SYMBOLS        =
 
 # The EXAMPLE_PATH tag can be used to specify one or more files or directories
 # that contain example code fragments that are included (see the \include
 # command).
 
-EXAMPLE_PATH           = 
+EXAMPLE_PATH           =
 
 # If the value of the EXAMPLE_PATH tag contains directories, you can use the
 # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
@@ -926,7 +926,7 @@ EXAMPLE_RECURSIVE      = NO
 # that contain images that are to be included in the documentation (see the
 # \image command).
 
-IMAGE_PATH             = 
+IMAGE_PATH             =
 
 # The INPUT_FILTER tag can be used to specify a program that doxygen should
 # invoke to filter for each input file. Doxygen will invoke the filter program
@@ -947,7 +947,7 @@ IMAGE_PATH             =
 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
 # properly processed by doxygen.
 
-INPUT_FILTER           = 
+INPUT_FILTER           =
 
 # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
 # basis. Doxygen will compare the file name with each pattern and apply the
@@ -960,7 +960,7 @@ INPUT_FILTER           =
 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
 # properly processed by doxygen.
 
-FILTER_PATTERNS        = 
+FILTER_PATTERNS        =
 
 # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
 # INPUT_FILTER) will also be used to filter the input files that are used for
@@ -975,14 +975,14 @@ FILTER_SOURCE_FILES    = NO
 # *.ext= (so without naming a filter).
 # This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
 
-FILTER_SOURCE_PATTERNS = 
+FILTER_SOURCE_PATTERNS =
 
 # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
 # is part of the input, its contents will be placed on the main page
 # (index.html). This can be useful if you have a project on for instance GitHub
 # and want to reuse the introduction page also for the doxygen output.
 
-USE_MDFILE_AS_MAINPAGE = 
+USE_MDFILE_AS_MAINPAGE =
 
 #---------------------------------------------------------------------------
 # Configuration options related to source browsing
@@ -1087,7 +1087,7 @@ CLANG_ASSISTED_PARSING = NO
 # specified with INPUT and INCLUDE_PATH.
 # This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES.
 
-CLANG_OPTIONS          = 
+CLANG_OPTIONS          =
 
 #---------------------------------------------------------------------------
 # Configuration options related to the alphabetical class index
@@ -1113,7 +1113,7 @@ COLS_IN_ALPHA_INDEX    = 5
 # while generating the index headers.
 # This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
-IGNORE_PREFIX          = 
+IGNORE_PREFIX          =
 
 #---------------------------------------------------------------------------
 # Configuration options related to the HTML output
@@ -1157,7 +1157,7 @@ HTML_FILE_EXTENSION    = .html
 # of the possible markers and block names see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_HEADER            = 
+HTML_HEADER            =
 
 # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
 # generated HTML page. If the tag is left blank doxygen will generate a standard
@@ -1167,7 +1167,7 @@ HTML_HEADER            =
 # that doxygen normally uses.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_FOOTER            = 
+HTML_FOOTER            =
 
 # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
 # sheet that is used by each HTML page. It can be used to fine-tune the look of
@@ -1179,7 +1179,7 @@ HTML_FOOTER            =
 # obsolete.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_STYLESHEET        = 
+HTML_STYLESHEET        =
 
 # The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
 # cascading style sheets that are included after the standard style sheets
@@ -1192,7 +1192,7 @@ HTML_STYLESHEET        =
 # list). For an example see the documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_EXTRA_STYLESHEET  = 
+HTML_EXTRA_STYLESHEET  =
 
 # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the HTML output directory. Note
@@ -1202,7 +1202,7 @@ HTML_EXTRA_STYLESHEET  =
 # files will be copied as-is; there are no commands or markers available.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
-HTML_EXTRA_FILES       = 
+HTML_EXTRA_FILES       =
 
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
 # will adjust the colors in the style sheet and background images according to
@@ -1331,7 +1331,7 @@ GENERATE_HTMLHELP      = NO
 # written to the html output directory.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
-CHM_FILE               = 
+CHM_FILE               =
 
 # The HHC_LOCATION tag can be used to specify the location (absolute path
 # including file name) of the HTML help compiler (hhc.exe). If non-empty,
@@ -1339,7 +1339,7 @@ CHM_FILE               =
 # The file has to be specified with full path.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
-HHC_LOCATION           = 
+HHC_LOCATION           =
 
 # The GENERATE_CHI flag controls if a separate .chi index file is generated
 # (YES) or that it should be included in the master .chm file (NO).
@@ -1352,7 +1352,7 @@ GENERATE_CHI           = NO
 # and project file content.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
-CHM_INDEX_ENCODING     = 
+CHM_INDEX_ENCODING     =
 
 # The BINARY_TOC flag controls whether a binary table of contents is generated
 # (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
@@ -1383,7 +1383,7 @@ GENERATE_QHP           = NO
 # the HTML output folder.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
-QCH_FILE               = 
+QCH_FILE               =
 
 # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
 # Project output. For more information please see Qt Help Project / Namespace
@@ -1408,7 +1408,7 @@ QHP_VIRTUAL_FOLDER     = doc
 # filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
-QHP_CUST_FILTER_NAME   = 
+QHP_CUST_FILTER_NAME   =
 
 # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
 # custom filter to add. For more information please see Qt Help Project / Custom
@@ -1416,21 +1416,21 @@ QHP_CUST_FILTER_NAME   =
 # filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
-QHP_CUST_FILTER_ATTRS  = 
+QHP_CUST_FILTER_ATTRS  =
 
 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
 # project's filter section matches. Qt Help Project / Filter Attributes (see:
 # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
-QHP_SECT_FILTER_ATTRS  = 
+QHP_SECT_FILTER_ATTRS  =
 
 # The QHG_LOCATION tag can be used to specify the location of Qt's
 # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
 # generated .qhp file.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
-QHG_LOCATION           = 
+QHG_LOCATION           =
 
 # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
 # generated, together with the HTML files, they form an Eclipse help plugin. To
@@ -1563,7 +1563,7 @@ MATHJAX_RELPATH        = http://cdn.mathjax.org/mathjax/latest
 # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
-MATHJAX_EXTENSIONS     = 
+MATHJAX_EXTENSIONS     =
 
 # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
 # of code that will be used on startup of the MathJax code. See the MathJax site
@@ -1571,7 +1571,7 @@ MATHJAX_EXTENSIONS     =
 # example see the documentation.
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
-MATHJAX_CODEFILE       = 
+MATHJAX_CODEFILE       =
 
 # When the SEARCHENGINE tag is enabled doxygen will generate a search box for
 # the HTML output. The underlying search engine uses javascript and DHTML and
@@ -1631,7 +1631,7 @@ EXTERNAL_SEARCH        = NO
 # Searching" for details.
 # This tag requires that the tag SEARCHENGINE is set to YES.
 
-SEARCHENGINE_URL       = 
+SEARCHENGINE_URL       =
 
 # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
 # search data is written to a file for indexing by an external tool. With the
@@ -1647,7 +1647,7 @@ SEARCHDATA_FILE        = searchdata.xml
 # projects and redirect the results back to the right project.
 # This tag requires that the tag SEARCHENGINE is set to YES.
 
-EXTERNAL_SEARCH_ID     = 
+EXTERNAL_SEARCH_ID     =
 
 # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
 # projects other than the one defined by this configuration file, but that are
@@ -1657,7 +1657,7 @@ EXTERNAL_SEARCH_ID     =
 # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
 # This tag requires that the tag SEARCHENGINE is set to YES.
 
-EXTRA_SEARCH_MAPPINGS  = 
+EXTRA_SEARCH_MAPPINGS  =
 
 #---------------------------------------------------------------------------
 # Configuration options related to the LaTeX output
@@ -1721,7 +1721,7 @@ PAPER_TYPE             = a4
 # If left blank no extra packages will be included.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-EXTRA_PACKAGES         = 
+EXTRA_PACKAGES         =
 
 # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
 # generated LaTeX document. The header should contain everything until the first
@@ -1737,7 +1737,7 @@ EXTRA_PACKAGES         =
 # to HTML_HEADER.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-LATEX_HEADER           = 
+LATEX_HEADER           =
 
 # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
 # generated LaTeX document. The footer should contain everything after the last
@@ -1748,7 +1748,7 @@ LATEX_HEADER           =
 # Note: Only use a user-defined footer if you know what you are doing!
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-LATEX_FOOTER           = 
+LATEX_FOOTER           =
 
 # The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
 # LaTeX style sheets that are included after the standard style sheets created
@@ -1759,7 +1759,7 @@ LATEX_FOOTER           =
 # list).
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-LATEX_EXTRA_STYLESHEET = 
+LATEX_EXTRA_STYLESHEET =
 
 # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
 # other source files which should be copied to the LATEX_OUTPUT output
@@ -1767,7 +1767,7 @@ LATEX_EXTRA_STYLESHEET =
 # markers available.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-LATEX_EXTRA_FILES      = 
+LATEX_EXTRA_FILES      =
 
 # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
 # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
@@ -1875,14 +1875,14 @@ RTF_HYPERLINKS         = NO
 # default style sheet that doxygen normally uses.
 # This tag requires that the tag GENERATE_RTF is set to YES.
 
-RTF_STYLESHEET_FILE    = 
+RTF_STYLESHEET_FILE    =
 
 # Set optional variables used in the generation of an RTF document. Syntax is
 # similar to doxygen's config file. A template extensions file can be generated
 # using doxygen -e rtf extensionFile.
 # This tag requires that the tag GENERATE_RTF is set to YES.
 
-RTF_EXTENSIONS_FILE    = 
+RTF_EXTENSIONS_FILE    =
 
 # If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
 # with syntax highlighting in the RTF output.
@@ -1927,7 +1927,7 @@ MAN_EXTENSION          = .3
 # MAN_EXTENSION with the initial . removed.
 # This tag requires that the tag GENERATE_MAN is set to YES.
 
-MAN_SUBDIR             = 
+MAN_SUBDIR             =
 
 # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
 # will generate one additional man file for each entity documented in the real
@@ -2040,7 +2040,7 @@ PERLMOD_PRETTY         = YES
 # overwrite each other's variables.
 # This tag requires that the tag GENERATE_PERLMOD is set to YES.
 
-PERLMOD_MAKEVAR_PREFIX = 
+PERLMOD_MAKEVAR_PREFIX =
 
 #---------------------------------------------------------------------------
 # Configuration options related to the preprocessor
@@ -2081,7 +2081,7 @@ SEARCH_INCLUDES        = YES
 # preprocessor.
 # This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
-INCLUDE_PATH           = 
+INCLUDE_PATH           =
 
 # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
 # patterns (like *.h and *.hpp) to filter out the header-files in the
@@ -2089,7 +2089,7 @@ INCLUDE_PATH           =
 # used.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-INCLUDE_FILE_PATTERNS  = 
+INCLUDE_FILE_PATTERNS  =
 
 # The PREDEFINED tag can be used to specify one or more macro names that are
 # defined before the preprocessor is started (similar to the -D option of e.g.
@@ -2099,7 +2099,7 @@ INCLUDE_FILE_PATTERNS  =
 # recursively expanded use the := operator instead of the = operator.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-PREDEFINED             = 
+PREDEFINED             =
 
 # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
 # tag can be used to specify a list of macro names that should be expanded. The
@@ -2108,7 +2108,7 @@ PREDEFINED             =
 # definition found in the source code.
 # This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
 
-EXPAND_AS_DEFINED      = 
+EXPAND_AS_DEFINED      =
 
 # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
 # remove all references to function-like macros that are alone on a line, have
@@ -2137,13 +2137,13 @@ SKIP_FUNCTION_MACROS   = YES
 # the path). If a tag file is not located in the directory in which doxygen is
 # run, you must also specify the path to the tagfile here.
 
-TAGFILES               = 
+TAGFILES               =
 
 # When a file name is specified after GENERATE_TAGFILE, doxygen will create a
 # tag file that is based on the input files it reads. See section "Linking to
 # external documentation" for more information about the usage of tag files.
 
-GENERATE_TAGFILE       = 
+GENERATE_TAGFILE       =
 
 # If the ALLEXTERNALS tag is set to YES, all external class will be listed in
 # the class index. If set to NO, only the inherited external classes will be
@@ -2192,14 +2192,14 @@ CLASS_DIAGRAMS         = YES
 # the mscgen tool resides. If left empty the tool is assumed to be found in the
 # default search path.
 
-MSCGEN_PATH            = 
+MSCGEN_PATH            =
 
 # You can include diagrams made with dia in doxygen documentation. Doxygen will
 # then run dia to produce the diagram and insert it in the documentation. The
 # DIA_PATH tag allows you to specify the directory where the dia binary resides.
 # If left empty dia is assumed to be found in the default search path.
 
-DIA_PATH               = 
+DIA_PATH               =
 
 # If set to YES the inheritance and collaboration graphs will hide inheritance
 # and usage relations if the target is undocumented or is not a class.
@@ -2248,7 +2248,7 @@ DOT_FONTSIZE           = 10
 # the path where dot can find it using this tag.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTPATH           = 
+DOT_FONTPATH           =
 
 # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
 # each documented class showing the direct and indirect inheritance relations.
@@ -2394,26 +2394,26 @@ INTERACTIVE_SVG        = YES
 # found. If left blank, it is assumed the dot tool can be found in the path.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_PATH               = 
+DOT_PATH               =
 
 # The DOTFILE_DIRS tag can be used to specify one or more directories that
 # contain dot files that are included in the documentation (see the \dotfile
 # command).
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOTFILE_DIRS           = 
+DOTFILE_DIRS           =
 
 # The MSCFILE_DIRS tag can be used to specify one or more directories that
 # contain msc files that are included in the documentation (see the \mscfile
 # command).
 
-MSCFILE_DIRS           = 
+MSCFILE_DIRS           =
 
 # The DIAFILE_DIRS tag can be used to specify one or more directories that
 # contain dia files that are included in the documentation (see the \diafile
 # command).
 
-DIAFILE_DIRS           = 
+DIAFILE_DIRS           =
 
 # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
 # path where java can find the plantuml.jar file. If left blank, it is assumed
@@ -2421,17 +2421,17 @@ DIAFILE_DIRS           =
 # generate a warning when it encounters a \startuml command in this case and
 # will not generate output for the diagram.
 
-PLANTUML_JAR_PATH      = 
+PLANTUML_JAR_PATH      =
 
 # When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
 # configuration file for plantuml.
 
-PLANTUML_CFG_FILE      = 
+PLANTUML_CFG_FILE      =
 
 # When using plantuml, the specified paths are searched for files specified by
 # the !include statement in a plantuml block.
 
-PLANTUML_INCLUDE_PATH  = 
+PLANTUML_INCLUDE_PATH  =
 
 # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
 # that will be shown in the graph. If the number of nodes in a graph becomes
diff --git a/Makefile b/Makefile
index 3fc8148..c368d50 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@ LDFLAGS := -lm
 $(TARGET): $(OBJS) Makefile
 	$(CC) $(LDFLAGS) $(OBJS) -DVERSION=$(VERSION) -o $@ $(LDFLAGS) $(LOADLIBES) $(LDLIBS)
 
-doc: $(SRCS) Makefile
+doc: $(SRCS) Makefile Doxyfile
 	doxygen
 
 format: $(SRCS) $(HDRS) Makefile
diff --git a/src/arith/integer.c b/src/arith/integer.c
index 60ce8c3..5239746 100644
--- a/src/arith/integer.c
+++ b/src/arith/integer.c
@@ -13,6 +13,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "debug.h"
 
 /**
  * return the numeric value of this cell, as a C primitive double, not
@@ -40,9 +41,7 @@ struct cons_pointer make_integer( int64_t value ) {
     struct cons_space_object *cell = &pointer2cell( result );
     cell->payload.integer.value = value;
 
-#ifdef DEBUG
-    dump_object( stderr, result );
-#endif
+    debug_dump_object( result, DEBUG_ARITH );
 
     return result;
 }
diff --git a/src/arith/peano.c b/src/arith/peano.c
index 763414e..4cb8abd 100644
--- a/src/arith/peano.c
+++ b/src/arith/peano.c
@@ -16,6 +16,7 @@
 
 #include "consspaceobject.h"
 #include "conspage.h"
+#include "debug.h"
 #include "equal.h"
 #include "integer.h"
 #include "intern.h"
@@ -86,8 +87,8 @@ long double to_long_double( struct cons_pointer arg ) {
             break;
     }
 
-    fputws( L"to_long_double( ", stderr );
-    print( stderr, arg );
+    debug_print( L"to_long_double( ", DEBUG_ARITH );
+    debug_print_object( arg, DEBUG_ARITH );
     fwprintf( stderr, L") => %lf\n", result );
 
     return result;
@@ -129,13 +130,11 @@ struct cons_pointer add_2( struct stack_frame *frame,
     struct cons_space_object cell1 = pointer2cell( arg1 );
     struct cons_space_object cell2 = pointer2cell( arg2 );
 
-#ifdef DEBUG
-    fputws( L"add_2( arg1 = ", stderr );
-    print( stderr, arg1 );
-    fputws( L"; arg2 = ", stderr );
-    print( stderr, arg2 );
-    fputws( L")\n", stderr );
-#endif
+    debug_print( L"add_2( arg1 = ", DEBUG_ARITH );
+    debug_print_object( arg1, DEBUG_ARITH );
+    debug_print( L"; arg2 = ", DEBUG_ARITH );
+    debug_print_object( arg2, DEBUG_ARITH );
+    debug_print( L"\n", DEBUG_ARITH );
 
     if ( zerop( arg1 ) ) {
         result = arg2;
@@ -209,11 +208,9 @@ struct cons_pointer add_2( struct stack_frame *frame,
         }
     }
 
-#ifdef DEBUG
-    fputws( L"}; => ", stderr );
-    print( stderr, arg2 );
-    fputws( L"\n", stderr );
-#endif
+    debug_print( L"}; => ", DEBUG_ARITH );
+    debug_print_object( arg2, DEBUG_ARITH );
+    debug_print( L"\n", DEBUG_ARITH );
 
     return result;
 }
@@ -267,13 +264,11 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
     struct cons_space_object cell1 = pointer2cell( arg1 );
     struct cons_space_object cell2 = pointer2cell( arg2 );
 
-#ifdef DEBUG
-    fputws( L"multiply_2( arg1 = ", stderr );
-    print( stderr, arg1 );
-    fputws( L"; arg2 = ", stderr );
-    print( stderr, arg2 );
-    fputws( L")\n", stderr );
-#endif
+    debug_print( L"multiply_2( arg1 = ", DEBUG_ARITH );
+    debug_print_object( arg1, DEBUG_ARITH );
+    debug_print( L"; arg2 = ", DEBUG_ARITH );
+    debug_print_object( arg2, DEBUG_ARITH );
+    debug_print( L")", DEBUG_ARITH );
 
     if ( zerop( arg1 ) ) {
         result = arg2;
@@ -348,11 +343,9 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
         }
     }
 
-#ifdef DEBUG
-    fputws( L" => ", stderr );
-    print( stderr, arg2 );
-    fputws( L"\n", stderr );
-#endif
+    debug_print( L" => ", DEBUG_ARITH );
+    debug_print_object( arg2, DEBUG_ARITH );
+    debug_print( L"\n", DEBUG_ARITH );
 
     return result;
 }
diff --git a/src/arith/ratio.c b/src/arith/ratio.c
index afea5b0..f12acbb 100644
--- a/src/arith/ratio.c
+++ b/src/arith/ratio.c
@@ -13,7 +13,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
-#include "dump.h"
+#include "debug.h"
 #include "equal.h"
 #include "integer.h"
 #include "lispops.h"
@@ -332,9 +332,8 @@ struct cons_pointer make_ratio( struct cons_pointer frame_pointer,
                              ( "Dividend and divisor of a ratio must be integers" ),
                              frame_pointer );
     }
-#ifdef DEBUG
-    dump_object( stderr, result );
-#endif
+    debug_dump_object( result, DEBUG_ARITH );
+
 
     return result;
 }
diff --git a/src/arith/real.c b/src/arith/real.c
index d3786dd..84ba899 100644
--- a/src/arith/real.c
+++ b/src/arith/real.c
@@ -9,7 +9,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
-#include "dump.h"
+#include "debug.h"
 #include "read.h"
 
 /**
@@ -23,9 +23,7 @@ struct cons_pointer make_real( long double value ) {
     struct cons_space_object *cell = &pointer2cell( result );
     cell->payload.real.value = value;
 
-#ifdef DEBUG
-    dump_object( stderr, result );
-#endif
+    debug_dump_object( result, DEBUG_ARITH );
 
     return result;
 }
diff --git a/src/debug.c b/src/debug.c
new file mode 100644
index 0000000..27f7634
--- /dev/null
+++ b/src/debug.c
@@ -0,0 +1,65 @@
+/**
+ * debug.c
+ *
+ * Better debug log messages.
+ *
+ * (c) 2017 Simon Brooke <simon@journeyman.cc>
+ * Licensed under GPL version 2.0, or, at your option, any later version.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+/*
+ * wide characters
+ */
+#include <wchar.h>
+#include <wctype.h>
+
+#include "consspaceobject.h"
+#include "debug.h"
+#include "dump.h"
+#include "print.h"
+
+/**
+ * the controlling flags for `debug_print`; set in `init.c`, q.v.
+ */
+int verbosity = 0;
+
+/**
+ * print this debug `message` to stderr, if `verbosity` matches `level`.
+ * `verbosity is a set of flags, see debug_print.h; so you can
+ * turn debugging on for only one part of the system.
+ */
+void debug_print( wchar_t *message, int level ) {
+#ifdef DEBUG
+    if ( level & verbosity ) {
+        fputws( message, stderr );
+    }
+#endif
+}
+
+/**
+ * print the object indicated by this `pointer` to stderr, if `verbosity`
+ * matches `level`.`verbosity is a set of flags, see debug_print.h; so you can
+ * turn debugging on for only one part of the system.
+ */
+void debug_print_object( struct cons_pointer pointer, int level ) {
+#ifdef DEBUG
+    if ( level & verbosity ) {
+        print( stderr, pointer );
+    }
+#endif
+}
+
+/**
+ * Like `dump_object`, q.v., but protected by the verbosity mechanism.
+ */
+void debug_dump_object( struct cons_pointer pointer, int level ) {
+#ifdef DEBUG
+    if ( level & verbosity ) {
+        dump_object( stderr, pointer );
+    }
+#endif
+}
diff --git a/src/debug.h b/src/debug.h
new file mode 100644
index 0000000..9c0448b
--- /dev/null
+++ b/src/debug.h
@@ -0,0 +1,28 @@
+/**
+ * debug.h
+ *
+ * Better debug log messages.
+ *
+ * (c) 2017 Simon Brooke <simon@journeyman.cc>
+ * Licensed under GPL version 2.0, or, at your option, any later version.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+
+#ifndef __debug_print_h
+#define __debug_print_h
+
+#define DEBUG_ALLOC 1
+#define DEBUG_STACK 2
+#define DEBUG_ARITH 4
+#define DEBUG_EVAL 8
+#define DEBUG_LAMBDA 16
+#define DEBUG_BOOTSTRAP 32
+#define DEBUG_IO 64
+
+extern int verbosity;
+void debug_print( wchar_t *message, int level );
+void debug_print_object( struct cons_pointer pointer, int level );
+void debug_dump_object( struct cons_pointer pointer, int level );
+#endif
diff --git a/src/init.c b/src/init.c
index 48516f6..bb722ae 100644
--- a/src/init.c
+++ b/src/init.c
@@ -11,26 +11,32 @@
 
 #include <stdbool.h>
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <wchar.h>
 
 #include "version.h"
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "debug.h"
 #include "intern.h"
 #include "lispops.h"
 #include "peano.h"
 #include "print.h"
 #include "repl.h"
 
+// extern char *optarg; /* defined in unistd.h */
+
 void bind_function( char *name, struct cons_pointer ( *executable )
-                     ( struct stack_frame *, struct cons_pointer ) ) {
+                     ( struct stack_frame *,
+                       struct cons_pointer, struct cons_pointer ) ) {
     deep_bind( c_string_to_lisp_symbol( name ),
                make_function( NIL, executable ) );
 }
 
 void bind_special( char *name, struct cons_pointer ( *executable )
-                    ( struct stack_frame * frame, struct cons_pointer env ) ) {
+                    ( struct stack_frame *,
+                      struct cons_pointer, struct cons_pointer ) ) {
     deep_bind( c_string_to_lisp_symbol( name ),
                make_special( NIL, executable ) );
 }
@@ -46,7 +52,7 @@ int main( int argc, char *argv[] ) {
     bool dump_at_end = false;
     bool show_prompt = false;
 
-    while ( ( option = getopt( argc, argv, "pdc" ) ) != -1 ) {
+    while ( ( option = getopt( argc, argv, "pdcv:" ) ) != -1 ) {
         switch ( option ) {
             case 'c':
                 print_use_colours = true;
@@ -57,6 +63,8 @@ int main( int argc, char *argv[] ) {
             case 'p':
                 show_prompt = true;
                 break;
+            case 'v':
+                verbosity = atoi( optarg );
             default:
                 fwprintf( stderr, L"Unexpected option %c\n", option );
                 break;
@@ -68,9 +76,15 @@ int main( int argc, char *argv[] ) {
                   L"Post scarcity software environment version %s\n\n",
                   VERSION );
     }
-
+#ifdef DEBUG
+    fputws( L"About to initialise cons pages\n", stderr );
+#endif
     initialise_cons_pages(  );
 
+#ifdef DEBUG
+    fputws( L"Initialised cons pages, about to bind\n", stderr );
+#endif
+
     /*
      * privileged variables (keywords)
      */
diff --git a/src/memory/conspage.c b/src/memory/conspage.c
index 13d8373..75bcdc8 100644
--- a/src/memory/conspage.c
+++ b/src/memory/conspage.c
@@ -18,6 +18,7 @@
 
 #include "consspaceobject.h"
 #include "conspage.h"
+#include "dump.h"
 
 /**
  * Flag indicating whether conspage initialisation has been done.
@@ -168,7 +169,7 @@ void free_cell( struct cons_pointer pointer ) {
             fwprintf( stderr, L"About to free vector-space object at %ld\n",
                       cell->payload.vectorp.address );
 #endif
-            free( ( void * ) cell->payload.vectorp.address );
+            //free( ( void * ) cell->payload.vectorp.address );
             break;
 
     }
diff --git a/src/memory/conspage.h b/src/memory/conspage.h
index 7b8b930..bc1361e 100644
--- a/src/memory/conspage.h
+++ b/src/memory/conspage.h
@@ -19,7 +19,7 @@
  * 4294967296.
  *
  * Note that this means the total number of addressable cons cells is
- * 1.8e19, each of 20 bytes; or 3e20 bytes in total; and there are 
+ * 1.8e19, each of 20 bytes; or 3e20 bytes in total; and there are
  * up to a maximum of 4e9 of heap space objects, each of potentially
  * 4e9 bytes. So we're talking about a potential total of 8e100 bytes
  * of addressable memory, which is only slightly more than the
@@ -38,7 +38,7 @@ struct cons_page {
 };
 
 /**
- * The (global) pointer to the (global) freelist. Not sure whether this ultimately 
+ * The (global) pointer to the (global) freelist. Not sure whether this ultimately
  * belongs in this file.
  */
 extern struct cons_pointer freelist;
diff --git a/src/memory/consspaceobject.h b/src/memory/consspaceobject.h
index 44b6a79..47bbed0 100644
--- a/src/memory/consspaceobject.h
+++ b/src/memory/consspaceobject.h
@@ -133,7 +133,7 @@
  * A pointer to an object in vector space.
  */
 #define VECTORPOINTTAG  "VECP"
-#define VECTORPOINTTV 0
+#define VECTORPOINTTV 1346585942
 /**
  * An open write stream.
  */
@@ -263,9 +263,10 @@
  * An indirect pointer to a cons cell
  */
 struct cons_pointer {
-    uint32_t page;              /* the index of the page on which this cell
-                                 * resides */
-    uint32_t offset;            /* the index of the cell within the page */
+   /** the index of the page on which this cell resides */
+    uint32_t page;
+    /** the index of the cell within the page */
+    uint32_t offset;
 };
 
 /*
@@ -421,7 +422,7 @@ struct vectorp_payload {
                                  * tag. */
         uint32_t value;         /* the tag considered as a number */
     } tag;
-    struct vector_space_object *address;
+    void *address;
     /* the address of the actual vector space
      * object (TODO: will change when I actually
      * implement vector space) */
diff --git a/src/memory/cursor.c b/src/memory/cursor.c
new file mode 100644
index 0000000..31a38b2
--- /dev/null
+++ b/src/memory/cursor.c
@@ -0,0 +1,9 @@
+/*
+ * a cursor is a cons-space object which holds:
+ * 1. a pointer to a vector (i.e. a vector-space object which holds an
+ *    array of `cons_pointer`);
+ * 2. an integer offset into that array.
+ *
+ * this provides a mechanism for iterating through vectors (actually, in
+ * either direction)
+ */
diff --git a/src/memory/cursor.h b/src/memory/cursor.h
new file mode 100644
index 0000000000000000000000000000000000000000..a50aff600d3015faae07bdd40e47973ce43ee241
GIT binary patch
literal 614
zcmZWm!A=4(6!g4b@d6hmWLeOJpvH)3xR5|Vx$c&3$rei=X}gg9dtX~H7&qC&wDac8
zbb6gm0v!Ne8;d5b2n75txMGGmiP{3k{T?+q1f~=rI<g1G1>j~UxU*@T3WK-&4hC6&
z2rKDl-VEZmfM@H`>kez9MYCr*<@_b^XOatTMG3Vog@Nf}21j8m?S(;_bpcHmn1hBU
z0T12}VcmdYj_7BqH_%Ixw%n4)7V<pC$*ZJISZZ;7l=Nce@i{bbq0}Sv??=N?_Atzb
zLF_U(`C6{#%g^x?{MYiZ^{aZmT!*`B1=``$xk?xTjDB}QII+h1qs!g{YZS7Q9<){^
zYy?EFWeRh0EIpT!OXrm$r$Qn!D0~I^0i~ulC?YK&8o{`MY1EQ41;zSfvM55v=!hi$
sa*HE%h$at}=CRV^DafD?aOEW0@H!VK)|r|+>fyfx^&xaAx5-WN1CG$cHvj+t

literal 0
HcmV?d00001

diff --git a/src/memory/dump.c b/src/memory/dump.c
index 5aaedfb..e0c2bbc 100644
--- a/src/memory/dump.c
+++ b/src/memory/dump.c
@@ -20,6 +20,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "debug.h"
 #include "print.h"
 #include "stack.h"
 #include "vectorspace.h"
@@ -111,11 +112,25 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
             dump_string_cell( output, L"Symbol", pointer );
             break;
         case VECTORPOINTTV:{
+                fwprintf( output,
+                          L"\t\tPointer to vector-space object at %p\n",
+                          cell.payload.vectorp.address );
                 struct vector_space_object *vso = cell.payload.vectorp.address;
                 fwprintf( output,
                           L"\t\tVector space object of type %4.4s, payload size %d bytes\n",
-                          vso->header.tag, vso->header.size );
+                          &vso->header.tag.bytes, vso->header.size );
+                switch ( vso->header.tag.value ) {
+                    case STACKFRAMETV:
+                        dump_frame( output, pointer );
+                        break;
+                    default:
+                        fputws( L"(Unknown vector type)\n", output );
+                        break;
+                }
             }
             break;
+        default:
+            fputws( L"(Unknown cons space type)\n", output );
+            break;
     }
 }
diff --git a/src/memory/stack.c b/src/memory/stack.c
index 9f0f6f8..069b1ed 100644
--- a/src/memory/stack.c
+++ b/src/memory/stack.c
@@ -19,6 +19,8 @@
 
 #include "consspaceobject.h"
 #include "conspage.h"
+#include "debug.h"
+#include "dump.h"
 #include "lispops.h"
 #include "print.h"
 #include "stack.h"
@@ -30,21 +32,24 @@
  */
 struct stack_frame *get_stack_frame( struct cons_pointer pointer ) {
     struct stack_frame *result = NULL;
-    fputws
+    debug_print
         ( L"get_stack_frame: about to get a pointer to the vector space object\n",
-          stderr );
+          DEBUG_ALLOC );
     struct vector_space_object *vso =
         pointer2cell( pointer ).payload.vectorp.address;
-    fputws( L"get_stack_frame: got a pointer, about to test it\n", stderr );
+    debug_print( L"get_stack_frame: got a pointer, about to test it\n",
+                 DEBUG_ALLOC );
 
-    if ( vectorpointp( pointer ) ) {  // && stackframep(vso)){
-        fputws( L"get_stack_frame: pointer is good, about to set the result\n",
-                stderr );
+    if ( vectorpointp( pointer ) && stackframep( vso ) ) {
+        debug_print
+            ( L"get_stack_frame: pointer is good, about to set the result\n",
+              DEBUG_ALLOC );
 
         result = ( struct stack_frame * ) &( vso->payload );
-        fputws( L"get_stack_frame: all good, returning\n", stderr );
+        fwprintf( stderr, L"get_stack_frame: all good, returning %p\n",
+                  result );
     } else {
-        fputws( L"get_stack_frame: fail, returning NULL\n", stderr );
+        debug_print( L"get_stack_frame: fail, returning NULL\n", DEBUG_ALLOC );
     }
 
     return result;
@@ -57,11 +62,20 @@ struct stack_frame *get_stack_frame( struct cons_pointer pointer ) {
  * @return the new frame, or NULL if memory is exhausted.
  */
 struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
-    fputws( L"Entering make_empty_frame\n", stderr );
+    debug_print( L"Entering make_empty_frame\n", DEBUG_ALLOC );
     struct cons_pointer result =
         make_vso( STACKFRAMETAG, sizeof( struct stack_frame ) );
+
+    debug_dump_object( result, DEBUG_ALLOC );
+
+    fwprintf( stderr,
+              L"make_empty_frame: got vector_space_object with size %lu, tag %4.4s\n",
+              pointer_to_vso( result )->header.size,
+              &pointer_to_vso( result )->header.tag.bytes );
+
     if ( !nilp( result ) ) {
-        fputws( L"make_empty_frame: about to call get_stack_frame\n", stderr );
+        debug_print( L"make_empty_frame: about to call get_stack_frame\n",
+                     DEBUG_ALLOC );
         struct stack_frame *frame = get_stack_frame( result );
         /*
          * TODO: later, pop a frame off a free-list of stack frames
@@ -69,9 +83,10 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
 
         fwprintf( stderr,
                   L"make_empty_frame: about to set previous to %4.4s\n",
-                  pointer2cell( previous ).tag );
+                  &pointer2cell( previous ).tag.bytes );
         frame->previous = previous;
-        fputws( L"make_empty_frame: about to call inc_ref\n", stderr );
+        debug_print( L"make_empty_frame: about to call inc_ref\n",
+                     DEBUG_ALLOC );
         inc_ref( previous );
 
         /*
@@ -82,13 +97,13 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
         frame->function = NIL;
         frame->args = 0;
 
-        fputws( L"make_empty_frame: about to initialise arg registers\n",
-                stderr );
+        debug_print( L"make_empty_frame: about to initialise arg registers\n",
+                     DEBUG_ALLOC );
         for ( int i = 0; i < args_in_frame; i++ ) {
             set_reg( frame, i, NIL );
         }
     }
-    fputws( L"Leaving make_empty_frame\n", stderr );
+    debug_print( L"Leaving make_empty_frame\n", DEBUG_ALLOC );
 
     return result;
 }
@@ -104,7 +119,7 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
 struct cons_pointer make_stack_frame( struct cons_pointer previous,
                                       struct cons_pointer args,
                                       struct cons_pointer env ) {
-    fputws( L"Entering make_stack_frame\n", stderr );
+    debug_print( L"Entering make_stack_frame\n", DEBUG_ALLOC );
     struct cons_pointer result = make_empty_frame( previous );
 
     if ( nilp( result ) ) {
@@ -164,12 +179,11 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
                 frame->more = more;
                 inc_ref( more );
             }
-#ifdef DEBUG
-            dump_frame( stderr, result );
-#endif
+
+            debug_dump_object( result, DEBUG_ALLOC );
         }
     }
-    fputws( L"Leaving make_stack_frame\n", stderr );
+    debug_print( L"Leaving make_stack_frame\n", DEBUG_ALLOC );
 
     return result;
 }
@@ -185,7 +199,7 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
 struct cons_pointer make_special_frame( struct cons_pointer previous,
                                         struct cons_pointer args,
                                         struct cons_pointer env ) {
-    fputws( L"Entering make_special_frame\n", stderr );
+    debug_print( L"Entering make_special_frame\n", DEBUG_ALLOC );
 
     struct cons_pointer result = make_empty_frame( previous );
 
@@ -213,12 +227,11 @@ struct cons_pointer make_special_frame( struct cons_pointer previous,
                 frame->more = args;
                 inc_ref( args );
             }
-#ifdef DEBUG
-            dump_frame( stderr, result );
-#endif
+
+            debug_dump_object( result, DEBUG_ALLOC );
         }
     }
-    fputws( L"Leaving make_special_frame\n", stderr );
+    debug_print( L"Leaving make_special_frame\n", DEBUG_ALLOC );
 
     return result;
 }
diff --git a/src/memory/stack.h b/src/memory/stack.h
index 20acd73..b56f432 100644
--- a/src/memory/stack.h
+++ b/src/memory/stack.h
@@ -33,13 +33,13 @@
 /**
  * is this vector-space object a stack frame?
  */
-#define stackframep(vso)(vso->header.tag.value == STACKFRAMETV)
+#define stackframep(vso)(((struct vector_space_object *)vso)->header.tag.value == STACKFRAMETV)
 
 /**
  * set a register in a stack frame. Alwaye use this macro to do so,
  • because that way we can be sure the inc_ref happens!
  */
-#define set_reg(frame,register,value)frame->arg[register]=value; inc_ref(value)
+#define set_reg(frame,register,value){frame->arg[register]=value; inc_ref(value);}
 
 struct stack_frame *get_stack_frame( struct cons_pointer pointer );
 
diff --git a/src/memory/vectorspace.c b/src/memory/vectorspace.c
index db39b48..7dbe682 100644
--- a/src/memory/vectorspace.c
+++ b/src/memory/vectorspace.c
@@ -21,6 +21,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "dump.h"
 #include "vectorspace.h"
 
 
@@ -30,19 +31,18 @@
  * NOTE that `tag` should be the vector-space tag of the particular type of
  * vector-space object, NOT `VECTORPOINTTAG`.
  */
-struct cons_pointer make_vec_pointer( char *tag,
-                                      struct vector_space_object *address ) {
+struct cons_pointer make_vec_pointer( struct vector_space_object *address ) {
     fputws( L"Entered make_vec_pointer\n", stderr );
     struct cons_pointer pointer = allocate_cell( VECTORPOINTTAG );
-    struct cons_space_object cell = pointer2cell( pointer );
+    struct cons_space_object *cell = &pointer2cell( pointer );
     fwprintf( stderr,
-              L"make_vec_pointer: allocated cell, about to write tag '%s'\n",
-              tag );
-    strncpy( &cell.payload.vectorp.tag.bytes[0], tag, 4 );
-    fputws( L"make_vec_pointer: tag written, about to set pointer address\n",
-            stderr );
-    cell.payload.vectorp.address = address;
-    fputws( L"make_vec_pointer: all good, returning\n", stderr );
+              L"make_vec_pointer: tag written, about to set pointer address to %p\n",
+              address );
+    cell->payload.vectorp.address = address;
+    fwprintf( stderr, L"make_vec_pointer: all good, returning pointer to %p\n",
+              cell->payload.vectorp.address );
+
+    dump_object( stderr, pointer );
 
     return pointer;
 }
@@ -66,24 +66,32 @@ struct cons_pointer make_vso( char *tag, uint64_t payload_size ) {
     struct vector_space_object *vso = malloc( padded );
 
     if ( vso != NULL ) {
-        fwprintf( stderr, L"make_vso: about to write tag '%s'\n", tag );
+        fwprintf( stderr,
+                  L"make_vso: about to write tag '%s' into vso at %p\n", tag,
+                  vso );
         strncpy( &vso->header.tag.bytes[0], tag, TAGLENGTH );
-        vso->header.vecp = make_vec_pointer( tag, vso );
+        result = make_vec_pointer( vso );
+        dump_object( stderr, result );
+        vso->header.vecp = result;
+        // memcpy(vso->header.vecp, result, sizeof(struct cons_pointer));
+
         vso->header.size = payload_size;
 
 #ifdef DEBUG
         fwprintf( stderr,
-                  L"Allocated vector-space object of type %4.4s, total size %ld, payload size %ld\n",
-                  tag, total_size, payload_size );
+                  L"Allocated vector-space object of type %4.4s, total size %ld, payload size %ld, at address %p, payload address %p\n",
+                  &vso->header.tag.bytes, total_size, vso->header.size, vso,
+                  &vso->payload );
         if ( padded != total_size ) {
             fwprintf( stderr, L"\t\tPadded from %d to %d\n",
                       total_size, padded );
         }
 #endif
-
-        result = vso->header.vecp;
     }
-    fputws( L"make_vso: all good, returning\n", stderr );
+#ifdef DEBUG
+    fwprintf( stderr, L"make_vso: all good, returning pointer to %p\n",
+              pointer2cell( result ).payload.vectorp.address );
+#endif
 
     return result;
 }
diff --git a/src/memory/vectorspace.h b/src/memory/vectorspace.h
index caec968..1438d37 100644
--- a/src/memory/vectorspace.h
+++ b/src/memory/vectorspace.h
@@ -40,7 +40,7 @@
 #define VECTORTAG "VECT"
 #define VECTORTV 0
 
-#define pointer_to_vso(pointer)((vectorpointp(pointer)? pointer2cell(pointer).payload.vectorp.address : NULL))
+#define pointer_to_vso(pointer)((vectorpointp(pointer)? (struct vector_space_object *) pointer2cell(pointer).payload.vectorp.address : (struct vector_space_object *) NULL))
 #define vso_get_vecp(vso)((vso->header.vecp))
 
 struct cons_pointer make_vso( char *tag, uint64_t payload_size );
diff --git a/src/ops/intern.c b/src/ops/intern.c
index 100589a..8dea7c8 100644
--- a/src/ops/intern.c
+++ b/src/ops/intern.c
@@ -21,6 +21,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "debug.h"
 #include "equal.h"
 #include "lispops.h"
 #include "print.h"
@@ -56,22 +57,22 @@ internedp( struct cons_pointer key, struct cons_pointer store ) {
             struct cons_space_object entry =
                 pointer2cell( pointer2cell( next ).payload.cons.car );
 
-            fputws( L"Internedp: checking whether `", stderr );
-            print( stderr, key );
-            fputws( L"` equals `", stderr );
-            print( stderr, entry.payload.cons.car );
-            fputws( L"`\n", stderr );
+            debug_print( L"Internedp: checking whether `", DEBUG_ALLOC );
+            debug_print_object( key, DEBUG_ALLOC );
+            debug_print( L"` equals `", DEBUG_ALLOC );
+            debug_print_object( entry.payload.cons.car, DEBUG_ALLOC );
+            debug_print( L"`\n", DEBUG_ALLOC );
 
             if ( equal( key, entry.payload.cons.car ) ) {
                 result = entry.payload.cons.car;
             }
         }
     } else {
-        fputws( L"`", stderr );
-        print( stderr, key );
-        fputws( L"` is a ", stderr );
-        print( stderr, c_type( key ) );
-        fputws( L", not a SYMB", stderr );
+        debug_print( L"`", DEBUG_ALLOC );
+        debug_print_object( key, DEBUG_ALLOC );
+        debug_print( L"` is a ", DEBUG_ALLOC );
+        debug_print_object( c_type( key ), DEBUG_ALLOC );
+        debug_print( L", not a SYMB", DEBUG_ALLOC );
     }
 
     return result;
@@ -120,7 +121,17 @@ bind( struct cons_pointer key, struct cons_pointer value,
  */
 struct cons_pointer
 deep_bind( struct cons_pointer key, struct cons_pointer value ) {
+    debug_print( L"Entering deep_bind\n", DEBUG_ALLOC );
+    debug_print( L"\tSetting ", DEBUG_ALLOC );
+    debug_print_object( key, DEBUG_ALLOC );
+    debug_print( L" to ", DEBUG_ALLOC );
+    debug_print_object( value, DEBUG_ALLOC );
+    debug_print( L"\n", DEBUG_ALLOC );
+
     oblist = bind( key, value, oblist );
+
+    debug_print( L"Leaving deep_bind\n", DEBUG_ALLOC );
+
     return oblist;
 }
 
diff --git a/src/ops/lispops.c b/src/ops/lispops.c
index 1e6712d..da3bc82 100644
--- a/src/ops/lispops.c
+++ b/src/ops/lispops.c
@@ -26,6 +26,8 @@
 
 #include "consspaceobject.h"
 #include "conspage.h"
+#include "debug.h"
+#include "dump.h"
 #include "equal.h"
 #include "integer.h"
 #include "intern.h"
@@ -83,9 +85,8 @@ struct cons_pointer eval_form( struct stack_frame *parent,
                                struct cons_pointer parent_pointer,
                                struct cons_pointer form,
                                struct cons_pointer env ) {
-    fputws( L"eval_form: ", stderr );
-    print( stderr, form );
-    fputws( L"\n", stderr );
+    debug_print( L"eval_form: ", DEBUG_EVAL );
+    debug_dump_object( form, DEBUG_EVAL );
 
     struct cons_pointer result = NIL;
     struct cons_pointer next_pointer = make_empty_frame( parent_pointer );
@@ -148,9 +149,8 @@ struct cons_pointer compose_body( struct stack_frame *frame ) {
         }
     }
 
-    fputws( L"compose_body returning ", stderr );
-    print( stderr, body );
-    fputws( L"\n", stderr );
+    debug_print( L"compose_body returning ", DEBUG_LAMBDA );
+    debug_dump_object( body, DEBUG_LAMBDA );
 
     return body;
 }
@@ -180,13 +180,10 @@ lisp_nlambda( struct stack_frame *frame, struct cons_pointer frame_pointer,
 }
 
 void log_binding( struct cons_pointer name, struct cons_pointer val ) {
-#ifdef DEBUG
-    fputws( L"\n\tBinding ", stderr );
-    print( stderr, name );
-    fputws( L" to ", stderr );
-    print( stderr, val );
-    fputws( L"\"\n", stderr );
-#endif
+    debug_print( L"\n\tBinding ", DEBUG_ALLOC );
+    debug_dump_object( name, DEBUG_ALLOC );
+    debug_print( L" to ", DEBUG_ALLOC );
+    debug_dump_object( val, DEBUG_ALLOC );
 }
 
 /**
@@ -236,9 +233,9 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
     while ( !nilp( body ) ) {
         struct cons_pointer sexpr = c_car( body );
         body = c_cdr( body );
-#ifdef DEBUG
-        fputws( L"In lambda: ", stderr );
-#endif
+
+        debug_print( L"In lambda: ", DEBUG_LAMBDA );
+
         result = eval_form( frame, frame_pointer, sexpr, new_env );
     }
 
@@ -414,8 +411,8 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
     struct cons_pointer result = frame->arg[0];
     struct cons_space_object cell = pointer2cell( frame->arg[0] );
 
+    debug_print( L"Eval: ", DEBUG_EVAL );
 #ifdef DEBUG
-    fputws( L"Eval: ", stderr );
     dump_frame( stderr, frame_pointer );
 #endif
 
@@ -455,11 +452,8 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
             break;
     }
 
-#ifdef DEBUG
-    fputws( L"Eval returning ", stderr );
-    print( stderr, result );
-    fputws( L"\n", stderr );
-#endif
+    debug_print( L"Eval returning ", DEBUG_EVAL );
+    debug_dump_object( result, DEBUG_EVAL );
 
     return result;
 }
@@ -476,7 +470,7 @@ struct cons_pointer
 lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
             struct cons_pointer env ) {
 #ifdef DEBUG
-    fputws( L"Apply: ", stderr );
+    debug_print( L"Apply: ", DEBUG_EVAL );
     dump_frame( stderr, frame_pointer );
 #endif
     set_reg( frame, 0, make_cons( frame->arg[0], frame->arg[1] ) );
@@ -484,11 +478,8 @@ lisp_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
 
     struct cons_pointer result = c_apply( frame, frame_pointer, env );
 
-#ifdef DEBUG
-    fputws( L"Apply returning ", stderr );
-    print( stderr, result );
-    fputws( L"\n", stderr );
-#endif
+    debug_print( L"Apply returning ", DEBUG_EVAL );
+    debug_dump_object( result, DEBUG_EVAL );
 
     return result;
 }
@@ -690,13 +681,20 @@ lisp_equal( struct stack_frame *frame, struct cons_pointer frame_pointer,
 struct cons_pointer
 lisp_read( struct stack_frame *frame, struct cons_pointer frame_pointer,
            struct cons_pointer env ) {
+#ifdef DEBUG
+    debug_print( L"entering lisp_read\n", DEBUG_IO );
+#endif
     FILE *input = stdin;
 
     if ( readp( frame->arg[0] ) ) {
         input = pointer2cell( frame->arg[0] ).payload.stream.stream;
     }
 
-    return read( frame, frame_pointer, input );
+    struct cons_pointer result = read( frame, frame_pointer, input );
+    debug_print( L"lisp_read returning\n", DEBUG_IO );
+    debug_dump_object( result, DEBUG_IO );
+
+    return result;
 }
 
 
@@ -745,23 +743,22 @@ struct cons_pointer lisp_reverse( struct stack_frame *frame,
 struct cons_pointer
 lisp_print( struct stack_frame *frame, struct cons_pointer frame_pointer,
             struct cons_pointer env ) {
-#ifdef DEBUG
-    fputws( L"Entering print\n", stderr );
-#endif
+    debug_print( L"Entering print\n", DEBUG_IO );
     struct cons_pointer result = NIL;
     FILE *output = stdout;
 
     if ( writep( frame->arg[1] ) ) {
+        debug_print( L"lisp_print: setting output stream\n", DEBUG_IO );
+        debug_dump_object( frame->arg[1], DEBUG_IO );
         output = pointer2cell( frame->arg[1] ).payload.stream.stream;
     }
+    debug_print( L"lisp_print: about to print\n", DEBUG_IO );
+    debug_dump_object( frame->arg[0], DEBUG_IO );
 
     result = print( output, frame->arg[0] );
 
-#ifdef DEBUG
-    fputws( L"Print returning ", stderr );
-    // print( stderr, result );
-    fputws( L"\n", stderr );
-#endif
+    debug_print( L"lisp_print returning\n", DEBUG_IO );
+    debug_dump_object( result, DEBUG_IO );
 
     return result;
 }
@@ -828,8 +825,8 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer,
 
     for ( int i = 0; i < args_in_frame && !done; i++ ) {
         struct cons_pointer clause_pointer = frame->arg[i];
-        fputws( L"Cond clause: ", stderr );
-        print( stderr, clause_pointer );
+        debug_print( L"Cond clause: ", DEBUG_EVAL );
+        debug_dump_object( clause_pointer, DEBUG_EVAL );
 
         if ( consp( clause_pointer ) ) {
             struct cons_space_object cell = pointer2cell( clause_pointer );
@@ -876,8 +873,8 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer,
 struct cons_pointer
 throw_exception( struct cons_pointer message,
                  struct cons_pointer frame_pointer ) {
-    fwprintf( stderr, L"\nERROR: " );
-    print( stderr, message );
+    debug_print( L"\nERROR: ", DEBUG_EVAL );
+    debug_dump_object( message, DEBUG_EVAL );
     struct cons_pointer result = NIL;
 
     struct cons_space_object cell = pointer2cell( message );
diff --git a/src/ops/read.c b/src/ops/read.c
index 7d21dbe..e3cb480 100644
--- a/src/ops/read.c
+++ b/src/ops/read.c
@@ -18,6 +18,8 @@
 #include <wctype.h>
 
 #include "consspaceobject.h"
+#include "debug.h"
+#include "dump.h"
 #include "integer.h"
 #include "intern.h"
 #include "lispops.h"
@@ -59,6 +61,7 @@ struct cons_pointer c_quote( struct cons_pointer arg ) {
 struct cons_pointer read_continuation( struct stack_frame *frame,
                                        struct cons_pointer frame_pointer,
                                        FILE * input, wint_t initial ) {
+    debug_print( L"entering read_continuation\n", DEBUG_IO );
     struct cons_pointer result = NIL;
 
     wint_t c;
@@ -141,6 +144,8 @@ struct cons_pointer read_continuation( struct stack_frame *frame,
                 break;
         }
     }
+    debug_print( L"read_continuation returning\n", DEBUG_IO );
+    debug_dump_object( result, DEBUG_IO );
 
     return result;
 }
@@ -154,6 +159,7 @@ struct cons_pointer read_number( struct stack_frame *frame,
                                  struct cons_pointer frame_pointer,
                                  FILE * input,
                                  wint_t initial, bool seen_period ) {
+    debug_print( L"entering read_number\n", DEBUG_IO );
     struct cons_pointer result = NIL;
     int64_t accumulator = 0;
     int64_t dividend = 0;
@@ -210,9 +216,6 @@ struct cons_pointer read_number( struct stack_frame *frame,
         if ( negative ) {
             rv = 0 - rv;
         }
-#ifdef DEBUG
-        fwprintf( stderr, L"read_numer returning %Lf\n", rv );
-#endif
         result = make_real( rv );
     } else if ( dividend != 0 ) {
         result =
@@ -225,6 +228,9 @@ struct cons_pointer read_number( struct stack_frame *frame,
         result = make_integer( accumulator );
     }
 
+    debug_print( L"read_number returning\n", DEBUG_IO );
+    debug_dump_object( result, DEBUG_IO );
+
     return result;
 }
 
@@ -248,12 +254,9 @@ struct cons_pointer read_list( struct stack_frame *frame,
             make_cons( car,
                        read_list( frame, frame_pointer, input,
                                   fgetwc( input ) ) );
+    } else {
+        debug_print( L"End of list detected\n", DEBUG_IO );
     }
-#ifdef DEBUG
-    else {
-        fwprintf( stderr, L"End of list detected\n" );
-    }
-#endif
 
     return result;
 }
@@ -324,11 +327,8 @@ struct cons_pointer read_symbol( FILE * input, wint_t initial ) {
             break;
     }
 
-#ifdef DEBUG
-    fputws( L"Read symbol '", stderr );
-    print( stderr, result );
-    fputws( L"'\n", stderr );
-#endif
+    debug_print( L"read_symbol returning\n", DEBUG_IO );
+    debug_dump_object( result, DEBUG_IO );
 
     return result;
 }
diff --git a/src/repl.c b/src/repl.c
index d077ba8..f0dcbfa 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -13,6 +13,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "dump.h"
 #include "intern.h"
 #include "lispops.h"
 #include "read.h"
@@ -32,19 +33,25 @@
  */
 struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
     struct cons_pointer result = NIL;
+    fputws( L"Entered repl_read\n", stderr );
     struct cons_pointer frame_pointer = make_empty_frame( NIL );
+    fputws( L"repl_read: got stack_frame pointer\n", stderr );
+    dump_object( stderr, frame_pointer );
     if ( !nilp( frame_pointer ) ) {
         inc_ref( frame_pointer );
         struct stack_frame *frame = get_stack_frame( frame_pointer );
 
         if ( frame != NULL ) {
-
+            fputws( L"repl_read: about to set register\n", stderr );
             set_reg( frame, 0, stream_pointer );
+            fputws( L"repl_read: about to read\n", stderr );
             struct cons_pointer result =
                 lisp_read( frame, frame_pointer, oblist );
         }
         dec_ref( frame_pointer );
     }
+    fputws( L"repl_read: returning\n", stderr );
+    dump_object( stderr, result );
 
     return result;
 }
@@ -53,6 +60,7 @@ struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
  * Dummy up a Lisp eval call with its own stack frame.
  */
 struct cons_pointer repl_eval( struct cons_pointer input ) {
+    fputws( L"Entered repl_eval\n", stderr );
     struct cons_pointer result = NIL;
     struct cons_pointer frame_pointer = make_empty_frame( NIL );
     if ( !nilp( frame_pointer ) ) {
@@ -66,6 +74,8 @@ struct cons_pointer repl_eval( struct cons_pointer input ) {
 
         dec_ref( frame_pointer );
     }
+    fputws( L"repl_eval: returning\n", stderr );
+    dump_object( stderr, result );
 
     return result;
 }
@@ -75,6 +85,7 @@ struct cons_pointer repl_eval( struct cons_pointer input ) {
  */
 struct cons_pointer repl_print( struct cons_pointer stream_pointer,
                                 struct cons_pointer value ) {
+
     struct cons_pointer result = NIL;
     struct cons_pointer frame_pointer = make_empty_frame( NIL );
     if ( !nilp( frame_pointer ) ) {
@@ -102,12 +113,12 @@ struct cons_pointer repl_print( struct cons_pointer stream_pointer,
 void
 repl( FILE * in_stream, FILE * out_stream, FILE * error_stream,
       bool show_prompt ) {
+    fputws( L"Entered repl\n", stderr );
     struct cons_pointer input_stream = make_read_stream( in_stream );
-    pointer2cell( input_stream ).count = MAXREFERENCE;
+    inc_ref( input_stream );
 
     struct cons_pointer output_stream = make_write_stream( out_stream );
-    pointer2cell( output_stream ).count = MAXREFERENCE;
-
+    inc_ref( output_stream );
     while ( !feof( pointer2cell( input_stream ).payload.stream.stream ) ) {
         if ( show_prompt ) {
             fwprintf( out_stream, L"\n:: " );

From e52ccce0ebce25dc02e170db050a51365f171f2a Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Fri, 28 Dec 2018 15:50:37 +0000
Subject: [PATCH 4/6] Much progress! Half the unit tests pass.

---
 src/arith/peano.c                 |  26 ++++-----
 src/arith/ratio.c                 |  52 ++++++++----------
 src/debug.c                       |  19 +++++++
 src/debug.h                       |   4 ++
 src/init.c                        |  88 +++++++++++++++---------------
 src/memory/conspage.c             |  29 ++++------
 src/memory/consspaceobject.c      |  25 +++++----
 src/memory/consspaceobject.h      |   4 +-
 src/memory/dump.c                 |  26 +++++----
 src/memory/stack.c                |  57 ++++++++++---------
 src/memory/vectorspace.c          |  24 ++++----
 src/ops/lispops.c                 |  45 +++++++--------
 src/ops/print.c                   |   9 ++-
 src/ops/read.c                    |  36 ++++++------
 src/repl.c                        |  62 ++++++++-------------
 utils_src/debugflags/debugflags   | Bin 0 -> 8520 bytes
 utils_src/debugflags/debugflags.c |  43 +++++++++++++++
 17 files changed, 296 insertions(+), 253 deletions(-)
 create mode 100755 utils_src/debugflags/debugflags
 create mode 100644 utils_src/debugflags/debugflags.c

diff --git a/src/arith/peano.c b/src/arith/peano.c
index 4cb8abd..9f5e0fb 100644
--- a/src/arith/peano.c
+++ b/src/arith/peano.c
@@ -89,7 +89,7 @@ long double to_long_double( struct cons_pointer arg ) {
 
     debug_print( L"to_long_double( ", DEBUG_ARITH );
     debug_print_object( arg, DEBUG_ARITH );
-    fwprintf( stderr, L") => %lf\n", result );
+    debug_printf( DEBUG_ARITH, L") => %lf\n", result );
 
     return result;
 }
@@ -166,7 +166,7 @@ struct cons_pointer add_2( struct stack_frame *frame,
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                                  ( "Cannot add: not a number" ),
+                                                  ( L"Cannot add: not a number" ),
                                                   frame_pointer );
                         break;
                 }
@@ -190,7 +190,7 @@ struct cons_pointer add_2( struct stack_frame *frame,
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                                  ( "Cannot add: not a number" ),
+                                                  ( L"Cannot add: not a number" ),
                                                   frame_pointer );
                         break;
                 }
@@ -203,7 +203,7 @@ struct cons_pointer add_2( struct stack_frame *frame,
             default:
                 result = exceptionp( arg2 ) ? arg2 :
                     throw_exception( c_string_to_lisp_string
-                                     ( "Cannot add: not a number" ),
+                                     ( L"Cannot add: not a number" ),
                                      frame_pointer );
         }
     }
@@ -300,7 +300,7 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                                  ( "Cannot multiply: not a number" ),
+                                                  ( L"Cannot multiply: not a number" ),
                                                   frame_pointer );
                         break;
                 }
@@ -326,7 +326,7 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                         break;
                     default:
                         result = throw_exception( c_string_to_lisp_string
-                                                  ( "Cannot multiply: not a number" ),
+                                                  ( L"Cannot multiply: not a number" ),
                                                   frame_pointer );
                 }
                 break;
@@ -337,7 +337,7 @@ struct cons_pointer multiply_2( struct stack_frame *frame,
                 break;
             default:
                 result = throw_exception( c_string_to_lisp_string
-                                          ( "Cannot multiply: not a number" ),
+                                          ( L"Cannot multiply: not a number" ),
                                           frame_pointer );
                 break;
         }
@@ -473,7 +473,7 @@ struct cons_pointer lisp_subtract( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                              ( "Cannot subtract: not a number" ),
+                                              ( L"Cannot subtract: not a number" ),
                                               frame_pointer );
                     break;
             }
@@ -506,7 +506,7 @@ struct cons_pointer lisp_subtract( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                              ( "Cannot subtract: not a number" ),
+                                              ( L"Cannot subtract: not a number" ),
                                               frame_pointer );
                     break;
             }
@@ -518,7 +518,7 @@ struct cons_pointer lisp_subtract( struct
             break;
         default:
             result = throw_exception( c_string_to_lisp_string
-                                      ( "Cannot subtract: not a number" ),
+                                      ( L"Cannot subtract: not a number" ),
                                       frame_pointer );
             break;
     }
@@ -580,7 +580,7 @@ struct cons_pointer lisp_divide( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                              ( "Cannot divide: not a number" ),
+                                              ( L"Cannot divide: not a number" ),
                                               frame_pointer );
                     break;
             }
@@ -615,7 +615,7 @@ struct cons_pointer lisp_divide( struct
                     break;
                 default:
                     result = throw_exception( c_string_to_lisp_string
-                                              ( "Cannot divide: not a number" ),
+                                              ( L"Cannot divide: not a number" ),
                                               frame_pointer );
                     break;
             }
@@ -627,7 +627,7 @@ struct cons_pointer lisp_divide( struct
             break;
         default:
             result = throw_exception( c_string_to_lisp_string
-                                      ( "Cannot divide: not a number" ),
+                                      ( L"Cannot divide: not a number" ),
                                       frame_pointer );
             break;
     }
diff --git a/src/arith/ratio.c b/src/arith/ratio.c
index f12acbb..ca83335 100644
--- a/src/arith/ratio.c
+++ b/src/arith/ratio.c
@@ -78,7 +78,7 @@ struct cons_pointer simplify_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( make_cons( c_string_to_lisp_string
-                                        ( "Shouldn't happen: bad arg to simplify_ratio" ),
+                                        ( L"Shouldn't happen: bad arg to simplify_ratio" ),
                                         arg ), frame_pointer );
     }
 
@@ -97,13 +97,11 @@ struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
                                      struct cons_pointer arg2 ) {
     struct cons_pointer r, result;
 
-#ifdef DEBUG
-    fputws( L"add_ratio_ratio( arg1 = ", stderr );
-    print( stderr, arg1 );
-    fputws( L"; arg2 = ", stderr );
-    print( stderr, arg2 );
-    fputws( L")\n", stderr );
-#endif
+    debug_print( L"add_ratio_ratio( arg1 = ", DEBUG_ARITH );
+    debug_print_object( arg1, DEBUG_ARITH );
+    debug_print( L"; arg2 = ", DEBUG_ARITH );
+    debug_print_object( arg2, DEBUG_ARITH );
+    debug_print( L")\n", DEBUG_ARITH );
 
     if ( ratiop( arg1 ) && ratiop( arg2 ) ) {
         struct cons_space_object cell1 = pointer2cell( arg1 );
@@ -119,9 +117,7 @@ struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
             lcm = least_common_multiple( dr1v, dr2v ),
             m1 = lcm / dr1v, m2 = lcm / dr2v;
 
-#ifdef DEBUG
-        fwprintf( stderr, L"); lcm = %ld; m1 = %ld; m2 = %ld", lcm, m1, m2 );
-#endif
+        debug_printf( DEBUG_ARITH, L"); lcm = %ld; m1 = %ld; m2 = %ld", lcm, m1, m2 );
 
         if ( dr1v == dr2v ) {
             r = make_ratio( frame_pointer,
@@ -151,17 +147,15 @@ struct cons_pointer add_ratio_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( make_cons( c_string_to_lisp_string
-                                        ( "Shouldn't happen: bad arg to add_ratio_ratio" ),
+                                        ( L"Shouldn't happen: bad arg to add_ratio_ratio" ),
                                         make_cons( arg1,
                                                    make_cons( arg2, NIL ) ) ),
                              frame_pointer );
     }
 
-#ifdef DEBUG
-    fputws( L" => ", stderr );
-    print( stderr, result );
-    fputws( L"\n", stderr );
-#endif
+    debug_print( L" => ", DEBUG_ARITH );
+    debug_print_object( result, DEBUG_ARITH );
+    debug_print( L"\n", DEBUG_ARITH );
 
     return result;
 }
@@ -188,7 +182,7 @@ struct cons_pointer add_integer_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( make_cons( c_string_to_lisp_string
-                                        ( "Shouldn't happen: bad arg to add_integer_ratio" ),
+                                        ( L"Shouldn't happen: bad arg to add_integer_ratio" ),
                                         make_cons( intarg,
                                                    make_cons( ratarg,
                                                               NIL ) ) ),
@@ -210,7 +204,8 @@ struct cons_pointer divide_ratio_ratio( struct cons_pointer frame_pointer,
                                         pointer2cell( arg2 ).payload.
                                         ratio.divisor,
                                         pointer2cell( arg2 ).payload.
-                                        ratio.dividend ), result =
+                                        ratio.dividend ),
+    result =
         multiply_ratio_ratio( frame_pointer, arg1, i );
 
     dec_ref( i );
@@ -228,13 +223,12 @@ struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, str
                                           cons_pointer arg2 ) {
     struct cons_pointer result;
 
-#ifdef DEBUG
-    fputws( L"multiply_ratio_ratio( arg1 = ", stderr );
-    print( stderr, arg1 );
-    fputws( L"; arg2 = ", stderr );
-    print( stderr, arg2 );
-    fputws( L")\n", stderr );
-#endif
+    debug_print( L"multiply_ratio_ratio( arg1 = ", DEBUG_ARITH );
+    debug_print_object( arg1, DEBUG_ARITH );
+    debug_print( L"; arg2 = ", DEBUG_ARITH );
+    debug_print_object( arg2, DEBUG_ARITH );
+    debug_print( L")\n", DEBUG_ARITH );
+
     if ( ratiop( arg1 ) && ratiop( arg2 ) ) {
         struct cons_space_object cell1 = pointer2cell( arg1 );
         struct cons_space_object cell2 = pointer2cell( arg2 );
@@ -259,7 +253,7 @@ struct cons_pointer multiply_ratio_ratio( struct cons_pointer frame_pointer, str
     } else {
         result =
             throw_exception( c_string_to_lisp_string
-                             ( "Shouldn't happen: bad arg to multiply_ratio_ratio" ),
+                             ( L"Shouldn't happen: bad arg to multiply_ratio_ratio" ),
                              frame_pointer );
     }
 
@@ -286,7 +280,7 @@ struct cons_pointer multiply_integer_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( c_string_to_lisp_string
-                             ( "Shouldn't happen: bad arg to multiply_integer_ratio" ),
+                             ( L"Shouldn't happen: bad arg to multiply_integer_ratio" ),
                              frame_pointer );
     }
 
@@ -329,7 +323,7 @@ struct cons_pointer make_ratio( struct cons_pointer frame_pointer,
     } else {
         result =
             throw_exception( c_string_to_lisp_string
-                             ( "Dividend and divisor of a ratio must be integers" ),
+                             ( L"Dividend and divisor of a ratio must be integers" ),
                              frame_pointer );
     }
     debug_dump_object( result, DEBUG_ARITH );
diff --git a/src/debug.c b/src/debug.c
index 27f7634..657998f 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -8,6 +8,7 @@
  */
 
 #include <ctype.h>
+#include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -35,11 +36,27 @@ int verbosity = 0;
 void debug_print( wchar_t *message, int level ) {
 #ifdef DEBUG
     if ( level & verbosity ) {
+        fwide( stderr, 1 );
         fputws( message, stderr );
     }
 #endif
 }
 
+/**
+ * `wprintf` adapted for the debug logging system. Print to stderr only
+ * `verbosity` matches `level`. All other arguments as for `wprintf`.
+ */
+void debug_printf( int level, wchar_t * format, ...) {
+  #ifdef DEBUG
+  if ( level & verbosity ) {
+    fwide( stderr, 1 );
+    va_list(args);
+    va_start(args, format);
+    vfwprintf(stderr, format, args);
+  }
+  #endif
+}
+
 /**
  * print the object indicated by this `pointer` to stderr, if `verbosity`
  * matches `level`.`verbosity is a set of flags, see debug_print.h; so you can
@@ -48,6 +65,7 @@ void debug_print( wchar_t *message, int level ) {
 void debug_print_object( struct cons_pointer pointer, int level ) {
 #ifdef DEBUG
     if ( level & verbosity ) {
+        fwide( stderr, 1 );
         print( stderr, pointer );
     }
 #endif
@@ -59,6 +77,7 @@ void debug_print_object( struct cons_pointer pointer, int level ) {
 void debug_dump_object( struct cons_pointer pointer, int level ) {
 #ifdef DEBUG
     if ( level & verbosity ) {
+          fwide( stderr, 1 );
         dump_object( stderr, pointer );
     }
 #endif
diff --git a/src/debug.h b/src/debug.h
index 9c0448b..10d07c3 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -20,9 +20,13 @@
 #define DEBUG_LAMBDA 16
 #define DEBUG_BOOTSTRAP 32
 #define DEBUG_IO 64
+#define DEBUG_REPL 128
 
 extern int verbosity;
+
 void debug_print( wchar_t *message, int level );
+void debug_printf( int level, wchar_t * format, ...);
 void debug_print_object( struct cons_pointer pointer, int level );
 void debug_dump_object( struct cons_pointer pointer, int level );
+
 #endif
diff --git a/src/init.c b/src/init.c
index bb722ae..d81aa00 100644
--- a/src/init.c
+++ b/src/init.c
@@ -27,14 +27,14 @@
 
 // extern char *optarg; /* defined in unistd.h */
 
-void bind_function( char *name, struct cons_pointer ( *executable )
+void bind_function( wchar_t *name, struct cons_pointer ( *executable )
                      ( struct stack_frame *,
                        struct cons_pointer, struct cons_pointer ) ) {
     deep_bind( c_string_to_lisp_symbol( name ),
                make_function( NIL, executable ) );
 }
 
-void bind_special( char *name, struct cons_pointer ( *executable )
+void bind_special( wchar_t *name, struct cons_pointer ( *executable )
                     ( struct stack_frame *,
                       struct cons_pointer, struct cons_pointer ) ) {
     deep_bind( c_string_to_lisp_symbol( name ),
@@ -52,7 +52,7 @@ int main( int argc, char *argv[] ) {
     bool dump_at_end = false;
     bool show_prompt = false;
 
-    while ( ( option = getopt( argc, argv, "pdcv:" ) ) != -1 ) {
+    while ( ( option = getopt( argc, argv, "cpdv:" ) ) != -1 ) {
         switch ( option ) {
             case 'c':
                 print_use_colours = true;
@@ -65,6 +65,7 @@ int main( int argc, char *argv[] ) {
                 break;
             case 'v':
                 verbosity = atoi( optarg );
+                break;
             default:
                 fwprintf( stderr, L"Unexpected option %c\n", option );
                 break;
@@ -76,62 +77,61 @@ int main( int argc, char *argv[] ) {
                   L"Post scarcity software environment version %s\n\n",
                   VERSION );
     }
-#ifdef DEBUG
-    fputws( L"About to initialise cons pages\n", stderr );
-#endif
+
+    debug_print( L"About to initialise cons pages\n", DEBUG_BOOTSTRAP );
+
     initialise_cons_pages(  );
 
-#ifdef DEBUG
-    fputws( L"Initialised cons pages, about to bind\n", stderr );
-#endif
+    debug_print( L"Initialised cons pages, about to bind\n", DEBUG_BOOTSTRAP );
 
     /*
      * privileged variables (keywords)
      */
-    deep_bind( c_string_to_lisp_symbol( "nil" ), NIL );
-    deep_bind( c_string_to_lisp_symbol( "t" ), TRUE );
+    deep_bind( c_string_to_lisp_symbol( L"nil" ), NIL );
+    deep_bind( c_string_to_lisp_symbol( L"t" ), TRUE );
 
     /*
      * primitive function operations
      */
-    bind_function( "add", &lisp_add );
-    bind_function( "apply", &lisp_apply );
-    bind_function( "assoc", &lisp_assoc );
-    bind_function( "car", &lisp_car );
-    bind_function( "cdr", &lisp_cdr );
-    bind_function( "cons", &lisp_cons );
-    bind_function( "divide", &lisp_divide );
-    bind_function( "eq", &lisp_eq );
-    bind_function( "equal", &lisp_equal );
-    bind_function( "eval", &lisp_eval );
-    bind_function( "exception", &lisp_exception );
-    bind_function( "multiply", &lisp_multiply );
-    bind_function( "read", &lisp_read );
-    bind_function( "oblist", &lisp_oblist );
-    bind_function( "print", &lisp_print );
-    bind_function( "progn", &lisp_progn );
-    bind_function( "reverse", &lisp_reverse );
-    bind_function( "set", &lisp_set );
-    bind_function( "subtract", &lisp_subtract );
-    bind_function( "throw", &lisp_exception );
-    bind_function( "type", &lisp_type );
+     bind_function( L"add", &lisp_add );
+     bind_function( L"apply", &lisp_apply );
+     bind_function( L"assoc", &lisp_assoc );
+     bind_function( L"car", &lisp_car );
+     bind_function( L"cdr", &lisp_cdr );
+     bind_function( L"cons", &lisp_cons );
+     bind_function( L"divide", &lisp_divide );
+     bind_function( L"eq", &lisp_eq );
+     bind_function( L"equal", &lisp_equal );
+     bind_function( L"eval", &lisp_eval );
+     bind_function( L"exception", &lisp_exception );
+     bind_function( L"multiply", &lisp_multiply );
+     bind_function( L"read", &lisp_read );
+     bind_function( L"oblist", &lisp_oblist );
+     bind_function( L"print", &lisp_print );
+     bind_function( L"progn", &lisp_progn );
+     bind_function( L"reverse", &lisp_reverse );
+     bind_function( L"set", &lisp_set );
+     bind_function( L"subtract", &lisp_subtract );
+     bind_function( L"throw", &lisp_exception );
+     bind_function( L"type", &lisp_type );
 
-    bind_function( "+", &lisp_add );
-    bind_function( "*", &lisp_multiply );
-    bind_function( "-", &lisp_subtract );
-    bind_function( "/", &lisp_divide );
-    bind_function( "=", &lisp_equal );
+     bind_function( L"+", &lisp_add );
+     bind_function( L"*", &lisp_multiply );
+     bind_function( L"-", &lisp_subtract );
+     bind_function( L"/", &lisp_divide );
+     bind_function( L"=", &lisp_equal );
 
     /*
      * primitive special forms
      */
-    bind_special( "cond", &lisp_cond );
-    bind_special( "lambda", &lisp_lambda );
-    /* bind_special( "λ", &lisp_lambda ); */
-    bind_special( "nlambda", &lisp_nlambda );
-    bind_special( "progn", &lisp_progn );
-    bind_special( "quote", &lisp_quote );
-    bind_special( "set!", &lisp_set_shriek );
+     bind_special( L"cond", &lisp_cond );
+     bind_special( L"lambda", &lisp_lambda );
+     // bind_special( L"λ", &lisp_lambda );
+     bind_special( L"nlambda", &lisp_nlambda );
+     // bind_special( L"nλ", &lisp_nlambda );
+     bind_special( L"progn", &lisp_progn );
+     bind_special( L"quote", &lisp_quote );
+     bind_special( L"set!", &lisp_set_shriek );
 
     repl( stdin, stdout, stderr, show_prompt );
 
diff --git a/src/memory/conspage.c b/src/memory/conspage.c
index 75bcdc8..cf87028 100644
--- a/src/memory/conspage.c
+++ b/src/memory/conspage.c
@@ -18,6 +18,7 @@
 
 #include "consspaceobject.h"
 #include "conspage.h"
+#include "debug.h"
 #include "dump.h"
 
 /**
@@ -65,7 +66,7 @@ void make_cons_page(  ) {
                         cell->count = MAXREFERENCE;
                         cell->payload.free.car = NIL;
                         cell->payload.free.cdr = NIL;
-                        fwprintf( stderr, L"Allocated special cell NIL\n" );
+                        debug_printf( DEBUG_ALLOC, L"Allocated special cell NIL\n" );
                         break;
                     case 1:
                         /*
@@ -79,7 +80,7 @@ void make_cons_page(  ) {
                         cell->payload.free.cdr = ( struct cons_pointer ) {
                             0, 1
                         };
-                        fwprintf( stderr, L"Allocated special cell T\n" );
+                        debug_printf( DEBUG_ALLOC, L"Allocated special cell T\n" );
                         break;
                 }
             } else {
@@ -96,7 +97,7 @@ void make_cons_page(  ) {
 
         initialised_cons_pages++;
     } else {
-        fwprintf( stderr,
+        debug_printf( DEBUG_ALLOC,
                   L"FATAL: Failed to allocate memory for cons page %d\n",
                   initialised_cons_pages );
         exit( 1 );
@@ -128,10 +129,8 @@ void dump_pages( FILE * output ) {
 void free_cell( struct cons_pointer pointer ) {
     struct cons_space_object *cell = &pointer2cell( pointer );
 
-#ifdef DEBUG
-    fwprintf( stderr, L"Freeing cell " );
-    dump_object( stderr, pointer );
-#endif
+    debug_printf( DEBUG_ALLOC, L"Freeing cell " );
+    debug_dump_object( pointer, DEBUG_ALLOC );
 
     switch ( cell->tag.value ) {
             /* for all the types of cons-space object which point to other
@@ -165,10 +164,8 @@ void free_cell( struct cons_pointer pointer ) {
         case VECTORPOINTTV:
             /* for vector space pointers, free the actual vector-space
              * object. Dangerous! */
-#ifdef DEBUG
-            fwprintf( stderr, L"About to free vector-space object at %ld\n",
+            debug_printf( DEBUG_ALLOC, L"About to free vector-space object at %ld\n",
                       cell->payload.vectorp.address );
-#endif
             //free( ( void * ) cell->payload.vectorp.address );
             break;
 
@@ -181,12 +178,12 @@ void free_cell( struct cons_pointer pointer ) {
             cell->payload.free.cdr = freelist;
             freelist = pointer;
         } else {
-            fwprintf( stderr,
+            debug_printf( DEBUG_ALLOC,
                       L"ERROR: Attempt to free cell with %d dangling references at page %d, offset %d\n",
                       cell->count, pointer.page, pointer.offset );
         }
     } else {
-        fwprintf( stderr,
+        debug_printf( DEBUG_ALLOC,
                   L"ERROR: Attempt to free cell which is already FREE at page %d, offset %d\n",
                   pointer.page, pointer.offset );
     }
@@ -218,13 +215,11 @@ struct cons_pointer allocate_cell( char *tag ) {
             cell->payload.cons.car = NIL;
             cell->payload.cons.cdr = NIL;
 
-#ifdef DEBUG
-            fwprintf( stderr,
+            debug_printf( DEBUG_ALLOC,
                       L"Allocated cell of type '%s' at %d, %d \n", tag,
                       result.page, result.offset );
-#endif
         } else {
-            fwprintf( stderr, L"WARNING: Allocating non-free cell!" );
+            debug_printf( DEBUG_ALLOC, L"WARNING: Allocating non-free cell!" );
         }
     }
 
@@ -243,7 +238,7 @@ void initialise_cons_pages(  ) {
         make_cons_page(  );
         conspageinitihasbeencalled = true;
     } else {
-        fwprintf( stderr,
+        debug_printf( DEBUG_ALLOC,
                   L"WARNING: initialise_cons_pages() called a second or subsequent time\n" );
     }
 }
diff --git a/src/memory/consspaceobject.c b/src/memory/consspaceobject.c
index acca2a8..f5cc8b8 100644
--- a/src/memory/consspaceobject.c
+++ b/src/memory/consspaceobject.c
@@ -20,6 +20,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
+#include "debug.h"
 #include "print.h"
 #include "stack.h"
 
@@ -178,11 +179,13 @@ make_string_like_thing( wint_t c, struct cons_pointer tail, char *tag ) {
         cell->payload.string.character = c;
         cell->payload.string.cdr.page = tail.page;
         /* TODO: There's a problem here. Sometimes the offsets on
-         * strings are quite massively off. */
+         * strings are quite massively off. Fix is probably
+         * cell->payload.string.cdr = tsil */
         cell->payload.string.cdr.offset = tail.offset;
     } else {
-        fwprintf( stderr,
-                  L"Warning: only NIL and %s can be appended to %s\n",
+      // TODO: should throw an exception!
+        debug_printf( DEBUG_ALLOC,
+                  L"Warning: only NIL and %s can be prepended to %s\n",
                   tag, tag );
     }
 
@@ -249,26 +252,26 @@ struct cons_pointer make_write_stream( FILE * output ) {
 }
 
 /**
- * Return a lisp string representation of this old skool ASCII string.
+ * Return a lisp string representation of this wide character string.
  */
-struct cons_pointer c_string_to_lisp_string( char *string ) {
+struct cons_pointer c_string_to_lisp_string( wchar_t *string ) {
     struct cons_pointer result = NIL;
 
-    for ( int i = strlen( string ); i > 0; i-- ) {
-        result = make_string( ( wint_t ) string[i - 1], result );
+    for ( int i = wcslen( string ); i > 0; i-- ) {
+        result = make_string( string[i - 1], result );
     }
 
     return result;
 }
 
 /**
- * Return a lisp symbol representation of this old skool ASCII string.
+ * Return a lisp symbol representation of this wide character string.
  */
-struct cons_pointer c_string_to_lisp_symbol( char *symbol ) {
+struct cons_pointer c_string_to_lisp_symbol( wchar_t *symbol ) {
     struct cons_pointer result = NIL;
 
-    for ( int i = strlen( symbol ); i > 0; i-- ) {
-        result = make_symbol( ( wint_t ) symbol[i - 1], result );
+    for ( int i = wcslen( symbol ); i > 0; i-- ) {
+        result = make_symbol( symbol[i - 1], result );
     }
 
     return result;
diff --git a/src/memory/consspaceobject.h b/src/memory/consspaceobject.h
index 47bbed0..523fdaa 100644
--- a/src/memory/consspaceobject.h
+++ b/src/memory/consspaceobject.h
@@ -582,11 +582,11 @@ struct cons_pointer make_write_stream( FILE * output );
 /**
  * Return a lisp string representation of this old skool ASCII string.
  */
-struct cons_pointer c_string_to_lisp_string( char *string );
+struct cons_pointer c_string_to_lisp_string( wchar_t *string );
 
 /**
  * Return a lisp symbol representation of this old skool ASCII string.
  */
-struct cons_pointer c_string_to_lisp_symbol( char *symbol );
+struct cons_pointer c_string_to_lisp_symbol( wchar_t *symbol );
 
 #endif
diff --git a/src/memory/dump.c b/src/memory/dump.c
index e0c2bbc..3129761 100644
--- a/src/memory/dump.c
+++ b/src/memory/dump.c
@@ -55,11 +55,8 @@ void dump_string_cell( FILE * output, wchar_t *prefix,
 void dump_object( FILE * output, struct cons_pointer pointer ) {
     struct cons_space_object cell = pointer2cell( pointer );
     fwprintf( output,
-              L"\t%c%c%c%c (%d) at page %d, offset %d count %u\n",
-              cell.tag.bytes[0],
-              cell.tag.bytes[1],
-              cell.tag.bytes[2],
-              cell.tag.bytes[3],
+              L"\t%4.4s (%d) at page %d, offset %d count %u\n",
+              cell.tag.bytes,
               cell.tag.value, pointer.page, pointer.offset, cell.count );
 
     switch ( cell.tag.value ) {
@@ -91,6 +88,8 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
             fwprintf( output, L";\n\t\t\tbody: " );
             print( output, cell.payload.lambda.body );
             break;
+        case NILTV:
+            break;
         case RATIOTV:
             fwprintf( output,
                       L"\t\tRational cell: value %ld/%ld, count %u\n",
@@ -101,6 +100,7 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
             break;
         case READTV:
             fwprintf( output, L"\t\tInput stream\n" );
+            break;
         case REALTV:
             fwprintf( output, L"\t\tReal cell: value %Lf, count %u\n",
                       cell.payload.real.value, cell.count );
@@ -111,26 +111,28 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
         case SYMBOLTV:
             dump_string_cell( output, L"Symbol", pointer );
             break;
+        case TRUETV:
+            break;
         case VECTORPOINTTV:{
                 fwprintf( output,
                           L"\t\tPointer to vector-space object at %p\n",
                           cell.payload.vectorp.address );
                 struct vector_space_object *vso = cell.payload.vectorp.address;
                 fwprintf( output,
-                          L"\t\tVector space object of type %4.4s, payload size %d bytes\n",
-                          &vso->header.tag.bytes, vso->header.size );
+                          L"\t\tVector space object of type %4.4s (%d), payload size %d bytes\n",
+                          &vso->header.tag.bytes, vso->header.tag.value, vso->header.size );
+          if (stackframep(vso)) {
+            dump_frame(output, pointer);
+          }
                 switch ( vso->header.tag.value ) {
                     case STACKFRAMETV:
                         dump_frame( output, pointer );
                         break;
-                    default:
-                        fputws( L"(Unknown vector type)\n", output );
-                        break;
                 }
             }
             break;
-        default:
-            fputws( L"(Unknown cons space type)\n", output );
+        case WRITETV:
+            fwprintf( output, L"\t\tOutput stream\n" );
             break;
     }
 }
diff --git a/src/memory/stack.c b/src/memory/stack.c
index 069b1ed..a167244 100644
--- a/src/memory/stack.c
+++ b/src/memory/stack.c
@@ -32,24 +32,15 @@
  */
 struct stack_frame *get_stack_frame( struct cons_pointer pointer ) {
     struct stack_frame *result = NULL;
-    debug_print
-        ( L"get_stack_frame: about to get a pointer to the vector space object\n",
-          DEBUG_ALLOC );
     struct vector_space_object *vso =
         pointer2cell( pointer ).payload.vectorp.address;
-    debug_print( L"get_stack_frame: got a pointer, about to test it\n",
-                 DEBUG_ALLOC );
 
     if ( vectorpointp( pointer ) && stackframep( vso ) ) {
-        debug_print
-            ( L"get_stack_frame: pointer is good, about to set the result\n",
-              DEBUG_ALLOC );
-
         result = ( struct stack_frame * ) &( vso->payload );
-        fwprintf( stderr, L"get_stack_frame: all good, returning %p\n",
+        debug_printf( DEBUG_STACK, L"get_stack_frame: all good, returning %p\n",
                   result );
     } else {
-        debug_print( L"get_stack_frame: fail, returning NULL\n", DEBUG_ALLOC );
+        debug_print( L"get_stack_frame: fail, returning NULL\n", DEBUG_STACK );
     }
 
     return result;
@@ -62,31 +53,31 @@ struct stack_frame *get_stack_frame( struct cons_pointer pointer ) {
  * @return the new frame, or NULL if memory is exhausted.
  */
 struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
-    debug_print( L"Entering make_empty_frame\n", DEBUG_ALLOC );
+    debug_print( L"Entering make_empty_frame\n", DEBUG_STACK );
     struct cons_pointer result =
         make_vso( STACKFRAMETAG, sizeof( struct stack_frame ) );
 
-    debug_dump_object( result, DEBUG_ALLOC );
+    debug_dump_object( result, DEBUG_STACK );
 
-    fwprintf( stderr,
+    debug_printf( DEBUG_STACK,
               L"make_empty_frame: got vector_space_object with size %lu, tag %4.4s\n",
               pointer_to_vso( result )->header.size,
               &pointer_to_vso( result )->header.tag.bytes );
 
     if ( !nilp( result ) ) {
         debug_print( L"make_empty_frame: about to call get_stack_frame\n",
-                     DEBUG_ALLOC );
+                     DEBUG_STACK );
         struct stack_frame *frame = get_stack_frame( result );
         /*
          * TODO: later, pop a frame off a free-list of stack frames
          */
 
-        fwprintf( stderr,
+        debug_printf( DEBUG_STACK,
                   L"make_empty_frame: about to set previous to %4.4s\n",
                   &pointer2cell( previous ).tag.bytes );
         frame->previous = previous;
         debug_print( L"make_empty_frame: about to call inc_ref\n",
-                     DEBUG_ALLOC );
+                     DEBUG_STACK );
         inc_ref( previous );
 
         /*
@@ -98,12 +89,12 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
         frame->args = 0;
 
         debug_print( L"make_empty_frame: about to initialise arg registers\n",
-                     DEBUG_ALLOC );
+                     DEBUG_STACK );
         for ( int i = 0; i < args_in_frame; i++ ) {
             set_reg( frame, i, NIL );
         }
     }
-    debug_print( L"Leaving make_empty_frame\n", DEBUG_ALLOC );
+    debug_print( L"Leaving make_empty_frame\n", DEBUG_STACK );
 
     return result;
 }
@@ -119,13 +110,13 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
 struct cons_pointer make_stack_frame( struct cons_pointer previous,
                                       struct cons_pointer args,
                                       struct cons_pointer env ) {
-    debug_print( L"Entering make_stack_frame\n", DEBUG_ALLOC );
+    debug_print( L"Entering make_stack_frame\n", DEBUG_STACK );
     struct cons_pointer result = make_empty_frame( previous );
 
     if ( nilp( result ) ) {
         /* i.e. out of memory */
         result =
-            make_exception( c_string_to_lisp_string( "Memory exhausted." ),
+            make_exception( c_string_to_lisp_string( L"Memory exhausted." ),
                             previous );
     } else {
         struct stack_frame *frame = get_stack_frame( result );
@@ -149,11 +140,13 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
             if ( nilp( arg_frame_pointer ) ) {
                 result =
                     make_exception( c_string_to_lisp_string
-                                    ( "Memory exhausted." ), previous );
+                                    ( L"Memory exhausted." ), previous );
                 break;
             } else {
                 struct stack_frame *arg_frame =
                     get_stack_frame( arg_frame_pointer );
+                    debug_print( L"Setting argument 0 of arg_frame to ", DEBUG_STACK);
+                    debug_print_object(cell.payload.cons.car, DEBUG_STACK);
                 set_reg( arg_frame, 0, cell.payload.cons.car );
 
                 struct cons_pointer val =
@@ -162,6 +155,8 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
                     result = val;
                     break;
                 } else {
+                    debug_printf( DEBUG_STACK, L"Setting argument %d to ", frame->args);
+                    debug_print_object(cell.payload.cons.car, DEBUG_STACK);
                     set_reg( frame, frame->args, val );
                 }
 
@@ -180,10 +175,10 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
                 inc_ref( more );
             }
 
-            debug_dump_object( result, DEBUG_ALLOC );
+            debug_dump_object( result, DEBUG_STACK );
         }
     }
-    debug_print( L"Leaving make_stack_frame\n", DEBUG_ALLOC );
+    debug_print( L"Leaving make_stack_frame\n", DEBUG_STACK );
 
     return result;
 }
@@ -199,14 +194,14 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
 struct cons_pointer make_special_frame( struct cons_pointer previous,
                                         struct cons_pointer args,
                                         struct cons_pointer env ) {
-    debug_print( L"Entering make_special_frame\n", DEBUG_ALLOC );
+    debug_print( L"Entering make_special_frame\n", DEBUG_STACK );
 
     struct cons_pointer result = make_empty_frame( previous );
 
     if ( nilp( result ) ) {
         /* i.e. out of memory */
         result =
-            make_exception( c_string_to_lisp_string( "Memory exhausted." ),
+            make_exception( c_string_to_lisp_string( L"Memory exhausted." ),
                             previous );
     } else {
         struct stack_frame *frame = get_stack_frame( result );
@@ -228,10 +223,10 @@ struct cons_pointer make_special_frame( struct cons_pointer previous,
                 inc_ref( args );
             }
 
-            debug_dump_object( result, DEBUG_ALLOC );
+            debug_dump_object( result, DEBUG_STACK );
         }
     }
-    debug_print( L"Leaving make_special_frame\n", DEBUG_ALLOC );
+    debug_print( L"Leaving make_special_frame\n", DEBUG_STACK );
 
     return result;
 }
@@ -263,6 +258,7 @@ void dump_frame( FILE * output, struct cons_pointer frame_pointer ) {
     struct stack_frame *frame = get_stack_frame( frame_pointer );
 
     if ( frame != NULL ) {
+        fwprintf( output, L"Stack frame with %d arguments:\n", frame->args);
         for ( int arg = 0; arg < frame->args; arg++ ) {
             struct cons_space_object cell = pointer2cell( frame->arg[arg] );
 
@@ -274,16 +270,19 @@ void dump_frame( FILE * output, struct cons_pointer frame_pointer ) {
             print( output, frame->arg[arg] );
             fputws( L"\n", output );
         }
+      if (!nilp(frame->more))
+      {
         fputws( L"More: \t", output );
         print( output, frame->more );
         fputws( L"\n", output );
+      }
     }
 }
 
 void dump_stack_trace( FILE * output, struct cons_pointer pointer ) {
     if ( exceptionp( pointer ) ) {
         print( output, pointer2cell( pointer ).payload.exception.message );
-        fwprintf( output, L"\n" );
+        fputws( L"\n", output );
         dump_stack_trace( output,
                           pointer2cell( pointer ).payload.exception.frame );
     } else {
diff --git a/src/memory/vectorspace.c b/src/memory/vectorspace.c
index 7dbe682..c30f120 100644
--- a/src/memory/vectorspace.c
+++ b/src/memory/vectorspace.c
@@ -21,7 +21,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
-#include "dump.h"
+#include "debug.h"
 #include "vectorspace.h"
 
 
@@ -32,17 +32,17 @@
  * vector-space object, NOT `VECTORPOINTTAG`.
  */
 struct cons_pointer make_vec_pointer( struct vector_space_object *address ) {
-    fputws( L"Entered make_vec_pointer\n", stderr );
+    debug_print( L"Entered make_vec_pointer\n", DEBUG_ALLOC );
     struct cons_pointer pointer = allocate_cell( VECTORPOINTTAG );
     struct cons_space_object *cell = &pointer2cell( pointer );
-    fwprintf( stderr,
+    debug_printf( DEBUG_ALLOC,
               L"make_vec_pointer: tag written, about to set pointer address to %p\n",
               address );
     cell->payload.vectorp.address = address;
-    fwprintf( stderr, L"make_vec_pointer: all good, returning pointer to %p\n",
+    debug_printf( DEBUG_ALLOC, L"make_vec_pointer: all good, returning pointer to %p\n",
               cell->payload.vectorp.address );
 
-    dump_object( stderr, pointer );
+    debug_dump_object( pointer, DEBUG_ALLOC );
 
     return pointer;
 }
@@ -55,41 +55,41 @@ struct cons_pointer make_vec_pointer( struct vector_space_object *address ) {
  * Returns NIL if the vector could not be allocated due to memory exhaustion.
  */
 struct cons_pointer make_vso( char *tag, uint64_t payload_size ) {
-    fputws( L"Entered make_vso\n", stderr );
+    debug_print( L"Entered make_vso\n", DEBUG_ALLOC );
     struct cons_pointer result = NIL;
     int64_t total_size = sizeof( struct vector_space_header ) + payload_size;
 
     /* Pad size to 64 bit words. This is intended to promote access efficiancy
      * on 64 bit machines but may just be voodoo coding */
     uint64_t padded = ceil( ( total_size * 8.0 ) / 8.0 );
-    fputws( L"make_vso: about to malloc\n", stderr );
+    debug_print( L"make_vso: about to malloc\n", DEBUG_ALLOC );
     struct vector_space_object *vso = malloc( padded );
 
     if ( vso != NULL ) {
-        fwprintf( stderr,
+        debug_printf( DEBUG_ALLOC,
                   L"make_vso: about to write tag '%s' into vso at %p\n", tag,
                   vso );
         strncpy( &vso->header.tag.bytes[0], tag, TAGLENGTH );
         result = make_vec_pointer( vso );
-        dump_object( stderr, result );
+        debug_dump_object( result, DEBUG_ALLOC );
         vso->header.vecp = result;
         // memcpy(vso->header.vecp, result, sizeof(struct cons_pointer));
 
         vso->header.size = payload_size;
 
 #ifdef DEBUG
-        fwprintf( stderr,
+        debug_printf( DEBUG_ALLOC,
                   L"Allocated vector-space object of type %4.4s, total size %ld, payload size %ld, at address %p, payload address %p\n",
                   &vso->header.tag.bytes, total_size, vso->header.size, vso,
                   &vso->payload );
         if ( padded != total_size ) {
-            fwprintf( stderr, L"\t\tPadded from %d to %d\n",
+            debug_printf( DEBUG_ALLOC, L"\t\tPadded from %d to %d\n",
                       total_size, padded );
         }
 #endif
     }
 #ifdef DEBUG
-    fwprintf( stderr, L"make_vso: all good, returning pointer to %p\n",
+    debug_printf( DEBUG_ALLOC, L"make_vso: all good, returning pointer to %p\n",
               pointer2cell( result ).payload.vectorp.address );
 #endif
 
diff --git a/src/ops/lispops.c b/src/ops/lispops.c
index da3bc82..43665e9 100644
--- a/src/ops/lispops.c
+++ b/src/ops/lispops.c
@@ -193,7 +193,7 @@ struct cons_pointer
 eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
              struct cons_pointer frame_pointer, struct cons_pointer env ) {
     struct cons_pointer result = NIL;
-    fwprintf( stderr, L"eval_lambda called\n" );
+    debug_print( L"eval_lambda called\n", DEBUG_EVAL );
 
     struct cons_pointer new_env = env;
     struct cons_pointer names = cell.payload.lambda.args;
@@ -355,13 +355,12 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
             break;
         default:
             {
-                char *buffer = malloc( 1024 );
-                memset( buffer, '\0', 1024 );
-                sprintf( buffer,
-                         "Unexpected cell with tag %d (%c%c%c%c) in function position",
-                         fn_cell.tag.value, fn_cell.tag.bytes[0],
-                         fn_cell.tag.bytes[1], fn_cell.tag.bytes[2],
-                         fn_cell.tag.bytes[3] );
+              int bs = sizeof(wchar_t) * 1024;
+                wchar_t *buffer = malloc( bs );
+                memset( buffer, '\0', bs );
+                swprintf( buffer, bs,
+                         L"Unexpected cell with tag %d (%4.4s) in function position",
+                         fn_cell.tag.value, &fn_cell.tag.bytes[0] );
                 struct cons_pointer message =
                     c_string_to_lisp_string( buffer );
                 free( buffer );
@@ -380,13 +379,13 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
  * @return As a Lisp string, the tag of the object which is at that pointer.
  */
 struct cons_pointer c_type( struct cons_pointer pointer ) {
-    char *buffer = malloc( TAGLENGTH + 1 );
-    memset( buffer, 0, TAGLENGTH + 1 );
+    struct cons_pointer result = NIL;
     struct cons_space_object cell = pointer2cell( pointer );
-    strncpy( buffer, cell.tag.bytes, TAGLENGTH );
 
-    struct cons_pointer result = c_string_to_lisp_string( buffer );
-    free( buffer );
+    for (int i = TAGLENGTH; i >= 0; i--)
+    {
+      result = make_string((wchar_t)cell.tag.bytes[i], result);
+    }
 
     return result;
 }
@@ -408,14 +407,12 @@ struct cons_pointer c_type( struct cons_pointer pointer ) {
 struct cons_pointer
 lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
            struct cons_pointer env ) {
+    debug_print( L"Eval: ", DEBUG_EVAL );
+    debug_dump_object( frame_pointer, DEBUG_EVAL );
+
     struct cons_pointer result = frame->arg[0];
     struct cons_space_object cell = pointer2cell( frame->arg[0] );
 
-    debug_print( L"Eval: ", DEBUG_EVAL );
-#ifdef DEBUG
-    dump_frame( stderr, frame_pointer );
-#endif
-
     switch ( cell.tag.value ) {
         case CONSTV:
             {
@@ -430,7 +427,7 @@ lisp_eval( struct stack_frame *frame, struct cons_pointer frame_pointer,
                 if ( nilp( canonical ) ) {
                     struct cons_pointer message =
                         make_cons( c_string_to_lisp_string
-                                   ( "Attempt to take value of unbound symbol." ),
+                                   ( L"Attempt to take value of unbound symbol." ),
                                    frame->arg[0] );
                     result = throw_exception( message, frame_pointer );
                 } else {
@@ -522,7 +519,7 @@ lisp_set( struct stack_frame *frame, struct cons_pointer frame_pointer,
         result =
             make_exception( make_cons
                             ( c_string_to_lisp_string
-                              ( "The first argument to `set!` is not a symbol: " ),
+                              ( L"The first argument to `set` is not a symbol: " ),
                               make_cons( frame->arg[0], NIL ) ),
                             frame_pointer );
     }
@@ -556,7 +553,7 @@ lisp_set_shriek( struct stack_frame *frame, struct cons_pointer frame_pointer,
         result =
             make_exception( make_cons
                             ( c_string_to_lisp_string
-                              ( "The first argument to `set!` is not a symbol: " ),
+                              ( L"The first argument to `set!` is not a symbol: " ),
                               make_cons( frame->arg[0], NIL ) ),
                             frame_pointer );
     }
@@ -610,7 +607,7 @@ lisp_car( struct stack_frame *frame, struct cons_pointer frame_pointer,
         result = make_string( cell.payload.string.character, NIL );
     } else {
         struct cons_pointer message =
-            c_string_to_lisp_string( "Attempt to take CAR of non sequence" );
+            c_string_to_lisp_string( L"Attempt to take CAR of non sequence" );
         result = throw_exception( message, frame_pointer );
     }
 
@@ -635,7 +632,7 @@ lisp_cdr( struct stack_frame *frame, struct cons_pointer frame_pointer,
         result = cell.payload.string.cdr;
     } else {
         struct cons_pointer message =
-            c_string_to_lisp_string( "Attempt to take CDR of non sequence" );
+            c_string_to_lisp_string( L"Attempt to take CDR of non sequence" );
         result = throw_exception( message, frame_pointer );
     }
 
@@ -850,7 +847,7 @@ lisp_cond( struct stack_frame *frame, struct cons_pointer frame_pointer,
             done = true;
         } else {
             result = throw_exception( c_string_to_lisp_string
-                                      ( "Arguments to `cond` must be lists" ),
+                                      ( L"Arguments to `cond` must be lists" ),
                                       frame_pointer );
         }
     }
diff --git a/src/ops/print.c b/src/ops/print.c
index 99cd7f3..49adca7 100644
--- a/src/ops/print.c
+++ b/src/ops/print.c
@@ -37,7 +37,7 @@ int print_use_colours = 0;
 void print_string_contents( FILE * output, struct cons_pointer pointer ) {
     while ( stringp( pointer ) || symbolp( pointer ) ) {
         struct cons_space_object *cell = &pointer2cell( pointer );
-        wint_t c = cell->payload.string.character;
+        wchar_t c = cell->payload.string.character;
 
         if ( c != '\0' ) {
             fputwc( c, output );
@@ -131,7 +131,7 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
             fwprintf( output, L"%ld%", cell.payload.integer.value );
             break;
         case LAMBDATV:
-            print( output, make_cons( c_string_to_lisp_symbol( "lambda" ),
+            print( output, make_cons( c_string_to_lisp_symbol( L"lambda" ),
                                       make_cons( cell.payload.lambda.args,
                                                  cell.payload.lambda.
                                                  body ) ) );
@@ -140,7 +140,7 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
             fwprintf( output, L"nil" );
             break;
         case NLAMBDATV:
-            print( output, make_cons( c_string_to_lisp_symbol( "nlambda" ),
+            print( output, make_cons( c_string_to_lisp_symbol( L"nlambda" ),
                                       make_cons( cell.payload.lambda.args,
                                                  cell.payload.lambda.
                                                  body ) ) );
@@ -190,6 +190,9 @@ struct cons_pointer print( FILE * output, struct cons_pointer pointer ) {
         case TRUETV:
             fwprintf( output, L"t" );
             break;
+        case WRITETV:
+            fwprintf( output, L"(Output stream)" );
+            break;
         default:
             fwprintf( stderr,
                       L"%sError: Unrecognised tag value %d (%c%c%c%c)\n",
diff --git a/src/ops/read.c b/src/ops/read.c
index e3cb480..a9b1ffe 100644
--- a/src/ops/read.c
+++ b/src/ops/read.c
@@ -49,7 +49,7 @@ struct cons_pointer read_symbol( FILE * input, wint_t initial );
  * quote reader macro in C (!)
  */
 struct cons_pointer c_quote( struct cons_pointer arg ) {
-    return make_cons( c_string_to_lisp_symbol( "quote" ),
+    return make_cons( c_string_to_lisp_symbol( L"quote" ),
                       make_cons( arg, NIL ) );
 }
 
@@ -71,8 +71,8 @@ struct cons_pointer read_continuation( struct stack_frame *frame,
 
     if ( feof( input ) ) {
         result =
-            make_exception( c_string_to_lisp_string
-                            ( "End of file while reading" ), frame_pointer );
+            throw_exception( c_string_to_lisp_string
+                            ( L"End of file while reading" ), frame_pointer );
     } else {
         switch ( c ) {
             case ';':
@@ -81,7 +81,7 @@ struct cons_pointer read_continuation( struct stack_frame *frame,
                 break;
             case EOF:
                 result = throw_exception( c_string_to_lisp_string
-                                          ( "End of input while reading" ),
+                                          ( L"End of input while reading" ),
                                           frame_pointer );
                 break;
             case '\'':
@@ -136,8 +136,8 @@ struct cons_pointer read_continuation( struct stack_frame *frame,
                     result = read_symbol( input, c );
                 } else {
                     result =
-                        make_exception( make_cons( c_string_to_lisp_string
-                                                   ( "Unrecognised start of input character" ),
+                        throw_exception( make_cons( c_string_to_lisp_string
+                                                   ( L"Unrecognised start of input character" ),
                                                    make_string( c, NIL ) ),
                                         frame_pointer );
                 }
@@ -170,23 +170,23 @@ struct cons_pointer read_number( struct stack_frame *frame,
     if ( negative ) {
         initial = fgetwc( input );
     }
-#ifdef DEBUG
-    fwprintf( stderr, L"read_number starting '%c' (%d)\n", initial, initial );
-#endif
+
+    debug_printf( DEBUG_IO, L"read_number starting '%c' (%d)\n", initial, initial );
+
     for ( c = initial; iswdigit( c )
           || c == btowc( '.' ) || c == btowc( '/' ); c = fgetwc( input ) ) {
         if ( c == btowc( '.' ) ) {
             if ( seen_period || dividend != 0 ) {
-                return make_exception( c_string_to_lisp_string
-                                       ( "Malformed number: too many periods" ),
+                return throw_exception( c_string_to_lisp_string
+                                       ( L"Malformed number: too many periods" ),
                                        frame_pointer );
             } else {
                 seen_period = true;
             }
         } else if ( c == btowc( '/' ) ) {
             if ( seen_period || dividend > 0 ) {
-                return make_exception( c_string_to_lisp_string
-                                       ( "Malformed number: dividend of rational must be integer" ),
+                return throw_exception( c_string_to_lisp_string
+                                       ( L"Malformed number: dividend of rational must be integer" ),
                                        frame_pointer );
             } else {
                 dividend = negative ? 0 - accumulator : accumulator;
@@ -195,11 +195,11 @@ struct cons_pointer read_number( struct stack_frame *frame,
             }
         } else {
             accumulator = accumulator * 10 + ( ( int ) c - ( int ) '0' );
-#ifdef DEBUG
-            fwprintf( stderr,
+
+            debug_printf( DEBUG_IO,
                       L"Added character %c, accumulator now %ld\n",
                       c, accumulator );
-#endif
+
             if ( seen_period ) {
                 places_of_decimals++;
             }
@@ -243,10 +243,8 @@ struct cons_pointer read_list( struct stack_frame *frame,
                                FILE * input, wint_t initial ) {
     struct cons_pointer result = NIL;
     if ( initial != ')' ) {
-#ifdef DEBUG
-        fwprintf( stderr,
+        debug_printf( DEBUG_IO,
                   L"read_list starting '%C' (%d)\n", initial, initial );
-#endif
         struct cons_pointer car =
             read_continuation( frame, frame_pointer, input,
                                initial );
diff --git a/src/repl.c b/src/repl.c
index f0dcbfa..04cf33c 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -13,7 +13,7 @@
 
 #include "conspage.h"
 #include "consspaceobject.h"
-#include "dump.h"
+#include "debug.h"
 #include "intern.h"
 #include "lispops.h"
 #include "read.h"
@@ -33,25 +33,17 @@
  */
 struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
     struct cons_pointer result = NIL;
-    fputws( L"Entered repl_read\n", stderr );
-    struct cons_pointer frame_pointer = make_empty_frame( NIL );
-    fputws( L"repl_read: got stack_frame pointer\n", stderr );
-    dump_object( stderr, frame_pointer );
+    debug_print( L"Entered repl_read\n", DEBUG_REPL );
+    struct cons_pointer frame_pointer = make_stack_frame( NIL, make_cons(stream_pointer, NIL), oblist );
+    debug_print( L"repl_read: got stack_frame pointer\n",  DEBUG_REPL );
+    debug_dump_object( frame_pointer, DEBUG_REPL );
     if ( !nilp( frame_pointer ) ) {
         inc_ref( frame_pointer );
-        struct stack_frame *frame = get_stack_frame( frame_pointer );
-
-        if ( frame != NULL ) {
-            fputws( L"repl_read: about to set register\n", stderr );
-            set_reg( frame, 0, stream_pointer );
-            fputws( L"repl_read: about to read\n", stderr );
-            struct cons_pointer result =
-                lisp_read( frame, frame_pointer, oblist );
-        }
+        result = lisp_read( get_stack_frame( frame_pointer ), frame_pointer, oblist );
         dec_ref( frame_pointer );
     }
-    fputws( L"repl_read: returning\n", stderr );
-    dump_object( stderr, result );
+    debug_print( L"repl_read: returning\n",  DEBUG_REPL );
+    debug_dump_object( result, DEBUG_REPL );
 
     return result;
 }
@@ -60,22 +52,18 @@ struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
  * Dummy up a Lisp eval call with its own stack frame.
  */
 struct cons_pointer repl_eval( struct cons_pointer input ) {
-    fputws( L"Entered repl_eval\n", stderr );
+     debug_print( L"Entered repl_eval\n",  DEBUG_REPL );
     struct cons_pointer result = NIL;
-    struct cons_pointer frame_pointer = make_empty_frame( NIL );
-    if ( !nilp( frame_pointer ) ) {
-        inc_ref( frame_pointer );
-        struct stack_frame *frame = get_stack_frame( frame_pointer );
+    struct cons_pointer frame_pointer = make_stack_frame( NIL, make_cons( input, NIL ), oblist);
 
-        if ( frame != NULL ) {
-            set_reg( frame, 0, input );
-            result = lisp_eval( frame, frame_pointer, oblist );
-        }
+    if ( !nilp( frame_pointer ) ) {
+    inc_ref(frame_pointer);
+            result = lisp_eval( get_stack_frame( frame_pointer ), frame_pointer, oblist );
 
         dec_ref( frame_pointer );
     }
-    fputws( L"repl_eval: returning\n", stderr );
-    dump_object( stderr, result );
+    debug_print( L"repl_eval: returning\n",  DEBUG_REPL );
+    debug_dump_object( result, DEBUG_REPL );
 
     return result;
 }
@@ -85,20 +73,17 @@ struct cons_pointer repl_eval( struct cons_pointer input ) {
  */
 struct cons_pointer repl_print( struct cons_pointer stream_pointer,
                                 struct cons_pointer value ) {
-
+     debug_print( L"Entered repl_print\n",  DEBUG_REPL );
+    debug_dump_object( value, DEBUG_REPL );
     struct cons_pointer result = NIL;
-    struct cons_pointer frame_pointer = make_empty_frame( NIL );
+    struct cons_pointer frame_pointer = make_stack_frame( NIL, make_cons( value, NIL ), oblist);
     if ( !nilp( frame_pointer ) ) {
-        struct stack_frame *frame = get_stack_frame( frame_pointer );
-
-        if ( frame != NULL ) {
-            set_reg( frame, 0, value );
-            set_reg( frame, 1, stream_pointer );
-            result = lisp_print( frame, frame_pointer, oblist );
-            free_stack_frame( frame );
-        }
+    inc_ref(frame_pointer);
+        result = lisp_print( get_stack_frame( frame_pointer ), frame_pointer, oblist );
         dec_ref( frame_pointer );
     }
+    debug_print( L"repl_print: returning\n",  DEBUG_REPL );
+    debug_dump_object( result, DEBUG_REPL );
 
     return result;
 }
@@ -113,7 +98,7 @@ struct cons_pointer repl_print( struct cons_pointer stream_pointer,
 void
 repl( FILE * in_stream, FILE * out_stream, FILE * error_stream,
       bool show_prompt ) {
-    fputws( L"Entered repl\n", stderr );
+     debug_print( L"Entered repl\n",  DEBUG_REPL );
     struct cons_pointer input_stream = make_read_stream( in_stream );
     inc_ref( input_stream );
 
@@ -138,4 +123,5 @@ repl( FILE * in_stream, FILE * out_stream, FILE * error_stream,
         }
         dec_ref( input );
     }
+     debug_print( L"Leaving repl\n",  DEBUG_REPL );
 }
diff --git a/utils_src/debugflags/debugflags b/utils_src/debugflags/debugflags
new file mode 100755
index 0000000000000000000000000000000000000000..49b2a0854c3ae04e0551caba08f8019ff3a2cd8c
GIT binary patch
literal 8520
zcmeHN-)kII6u#56HHm4nc`(FSb^2qa?L(raw8dK3NiuXow#}MsM8$H+{%Etf*@WF0
zZ5|dDqTnzM?33V&{tJcTi%1D1m^>8hLmz_V!G|ali5Nj-k&yK}Gk22NP4vwN;T|}1
z&pF?nGv|JH2JYUw-~aXN?sJSOEsRx;FvdEei$@vzl&P>7dl70tIZtRe_4oC$QHnN-
z(&!%QQJyt)<UFarn{4dj-5+U;G2x>&c1$Ss;M~mKH_7s)IbZAq1_S7kD2jXxXJ3x8
z%DzMSN~V=6?S-22{c+OI*CBcYesDvp$ah=>{Cs>Wo1e`V5o^vz1XF3}f&}o1_dPjK
zU%F%#bA@}NLvy}!BHsgnlOL9b+yFSY3LobR8J;WLo$>s}`FJSu(VUZz-<-oo{433?
z3*~%BOKKqm^XE-LFt1H5%`4uyz1*A^^1L)Rotnw>S+n?$`GPd`e$f4a5dYyiInPi2
zTfPYHr}~0?<cIT7ec|_J|2v2e-yYG2hJ$xlZ5k(h62lujW0XgjUi=Kcv)9Q|8EZw;
zina%BAgby?EQU6QAdQLe&s4^|ckHzPJwA_E0vZ;oKhSVIY`dz+6Ar@0YfdFGde8f<
zQn5duOZ8{w@)`IfFF~n}l_OWa`t#bAN8dcCeDK@x^5>TjQ=tl!oox4%Y>&&1FO-Y0
z1CFW7d5oX(RPkMgg`Rs2N*Im#*y;x8SN3Z`J>zpFGdtZk(1*HmDRhFo2BrKJ)#vkq
z@QE)ek^#wpWI!??8ITM}2L1~MCJg&0V}47u%R9DJGwg}&6@7~y<XAgrt=jx9>-^+Z
zxW>YbudyyN9BbQ|s6AwE86LXQTFKU3N8d8$m(@E<B42Dp-=Qpa896P=NgdJax?byC
zc*D!2ZyV`bTZZ%2s(X<F3pehep=6ee2b_ZQ7z*Hp_s}|J*Vcb@N9y(ZV_IP$d^-rQ
zyO$|U3tof=z3{rS;^?kjUb9!+ZbE6f3X~r1l-C6M3}|f^C@sQ(zT%<J1o{-{4}_{d
zdcs4W3iJukZwZb0XdR7Hej?CSpkESN@zGyAbXB0sKr28o>U9FFW#v2D+HkB54E;1B
zw!R3u<`)%P-`ZS4Pe<PY#j!g})q1oWb=0FhxW*S=R?ukU_2}=ot2%`X+x!{houVb_
z<~pplwrEK`AI)4)rzg$yRJL@zoyD^sW%Ft@^JY66(g!APaxESo9TfI>QX3oz;$y=}
zL)iK|T3ncM?bg7MCY*uM(d2k?OiKuVcvKi;dLqu+qM6{q?cO^36x9d`w=|>lTlX?r
zQu>`rLN=|%J8);jU!_wRLq1$0;`d*#Xb<ltqmlv1fMh^2AQ_MhNCqSWk^#wpWI!??
z8ITP8pBU&m6B(m=yJB?M=N*Rg6wZfnc>Q*fRar6872}iUOpfdx*t0l{Ht)g{qHvtg
zxA5sHp1q$<TV@t#-;;EEA9hO8AM!kHl(0+Fleq%BO1l&-Y_S)YDxE0ezXrVtuO*~Y
zp-m)zbE4bx{XGrZtT-!tIyWSr&iT;p?PK&e`B$5K+5@5OE&4A3Bo_E8PMQza&cn5H
NuXdk=VE6~f`Wu3Prndk9

literal 0
HcmV?d00001

diff --git a/utils_src/debugflags/debugflags.c b/utils_src/debugflags/debugflags.c
new file mode 100644
index 0000000..a9850d1
--- /dev/null
+++ b/utils_src/debugflags/debugflags.c
@@ -0,0 +1,43 @@
+#include <inttypes.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+#define DEBUG_ALLOC 1
+#define DEBUG_STACK 2
+#define DEBUG_ARITH 4
+#define DEBUG_EVAL 8
+#define DEBUG_LAMBDA 16
+#define DEBUG_BOOTSTRAP 32
+#define DEBUG_IO 64
+#define DEBUG_REPL 128
+
+int check_level( int v, int level, char * name) {
+  int result = 0;
+  if (v & level) {
+    printf("\t\t%s (%d) matches;\n", name, level);
+    result = 1;
+  }
+
+  return result;
+}
+
+int main( int argc, char *argv[] ) {
+
+  for (int i = 1; i < argc; i++) {
+    int v = atoi(argv[i]);
+
+    printf("Level %d:\n", v);
+    int matches = check_level(v, DEBUG_ALLOC, "DEBUG_ALLOC") +
+    check_level(v, DEBUG_STACK, "DEBUG_STACK") +
+    check_level(v, DEBUG_ARITH, "DEBUG_ARITH") +
+    check_level(v, DEBUG_EVAL, "DEBUG_EVAL") +
+    check_level(v, DEBUG_LAMBDA, "DEBUG_LAMBDA") +
+    check_level(v, DEBUG_BOOTSTRAP, "DEBUG_BOOTSTRAP") +
+    check_level(v, DEBUG_IO, "DEBUG_IO") +
+    check_level(v, DEBUG_REPL, "DEBUG_REPL");
+    printf("\t%d matches\n", matches);
+  }
+}

From 96dad29f91480736011f9f5ff31174f3c5e4d698 Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Fri, 28 Dec 2018 21:21:11 +0000
Subject: [PATCH 5/6] Good news: only one test failing. Bad news: it's nlambda.

---
 src/debug.c        | 15 +++++++++
 src/debug.h        |  1 +
 src/memory/dump.c  |  4 ++-
 src/memory/stack.c | 76 ++++++++++++++++++----------------------------
 src/memory/stack.h |  4 ++-
 src/ops/intern.c   |  6 ++++
 src/ops/lispops.c  | 42 +++++++++++--------------
 src/repl.c         | 22 ++++----------
 8 files changed, 80 insertions(+), 90 deletions(-)

diff --git a/src/debug.c b/src/debug.c
index 657998f..b21f4af 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -42,6 +42,21 @@ void debug_print( wchar_t *message, int level ) {
 #endif
 }
 
+/**
+ * print a line feed to stderr, if `verbosity` matches `level`.
+ * `verbosity is a set of flags, see debug_print.h; so you can
+ * turn debugging on for only one part of the system.
+ */
+void debug_println( int level ) {
+#ifdef DEBUG
+    if ( level & verbosity ) {
+        fwide( stderr, 1 );
+        fputws( L"\n", stderr );
+    }
+#endif
+}
+
+
 /**
  * `wprintf` adapted for the debug logging system. Print to stderr only
  * `verbosity` matches `level`. All other arguments as for `wprintf`.
diff --git a/src/debug.h b/src/debug.h
index 10d07c3..22f5591 100644
--- a/src/debug.h
+++ b/src/debug.h
@@ -25,6 +25,7 @@
 extern int verbosity;
 
 void debug_print( wchar_t *message, int level );
+void debug_println( int level );
 void debug_printf( int level, wchar_t * format, ...);
 void debug_print_object( struct cons_pointer pointer, int level );
 void debug_dump_object( struct cons_pointer pointer, int level );
diff --git a/src/memory/dump.c b/src/memory/dump.c
index 3129761..e88332a 100644
--- a/src/memory/dump.c
+++ b/src/memory/dump.c
@@ -62,11 +62,13 @@ void dump_object( FILE * output, struct cons_pointer pointer ) {
     switch ( cell.tag.value ) {
         case CONSTV:
             fwprintf( output,
-                      L"\t\tCons cell: car at page %d offset %d, cdr at page %d offset %d, count %u\n",
+                      L"\t\tCons cell: car at page %d offset %d, cdr at page %d offset %d, count %u :",
                       cell.payload.cons.car.page,
                       cell.payload.cons.car.offset,
                       cell.payload.cons.cdr.page,
                       cell.payload.cons.cdr.offset, cell.count );
+            print( output, pointer);
+            fputws( L"\n", output);
             break;
         case EXCEPTIONTV:
             fwprintf( output, L"\t\tException cell: " );
diff --git a/src/memory/stack.c b/src/memory/stack.c
index a167244..f91d896 100644
--- a/src/memory/stack.c
+++ b/src/memory/stack.c
@@ -26,6 +26,18 @@
 #include "stack.h"
 #include "vectorspace.h"
 
+void set_reg(struct stack_frame * frame, int reg, struct cons_pointer value) {
+  debug_printf(DEBUG_STACK, L"Setting register %d to ", reg);
+  debug_print_object(value, DEBUG_STACK);
+  debug_println(DEBUG_STACK);
+  frame->arg[reg++] = value;
+  inc_ref(value);
+  if (reg > frame->args) {
+    frame->args = reg;
+  }
+}
+
+
 /**
  * get the actual stackframe object from this `pointer`, or NULL if
  * `pointer` is not a stackframe pointer.
@@ -53,32 +65,24 @@ struct stack_frame *get_stack_frame( struct cons_pointer pointer ) {
  * @return the new frame, or NULL if memory is exhausted.
  */
 struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
-    debug_print( L"Entering make_empty_frame\n", DEBUG_STACK );
+    debug_print( L"Entering make_empty_frame\n", DEBUG_ALLOC );
     struct cons_pointer result =
         make_vso( STACKFRAMETAG, sizeof( struct stack_frame ) );
 
-    debug_dump_object( result, DEBUG_STACK );
+    debug_dump_object( result, DEBUG_ALLOC );
 
-    debug_printf( DEBUG_STACK,
-              L"make_empty_frame: got vector_space_object with size %lu, tag %4.4s\n",
-              pointer_to_vso( result )->header.size,
-              &pointer_to_vso( result )->header.tag.bytes );
+//    debug_printf( DEBUG_STACK,
+//              L"make_empty_frame: got vector_space_object with size %lu, tag %4.4s\n",
+//              pointer_to_vso( result )->header.size,
+//              &pointer_to_vso( result )->header.tag.bytes );
 
     if ( !nilp( result ) ) {
-        debug_print( L"make_empty_frame: about to call get_stack_frame\n",
-                     DEBUG_STACK );
         struct stack_frame *frame = get_stack_frame( result );
         /*
          * TODO: later, pop a frame off a free-list of stack frames
          */
 
-        debug_printf( DEBUG_STACK,
-                  L"make_empty_frame: about to set previous to %4.4s\n",
-                  &pointer2cell( previous ).tag.bytes );
         frame->previous = previous;
-        debug_print( L"make_empty_frame: about to call inc_ref\n",
-                     DEBUG_STACK );
-        inc_ref( previous );
 
         /*
          * clearing the frame with memset would probably be slightly quicker, but
@@ -88,13 +92,12 @@ struct cons_pointer make_empty_frame( struct cons_pointer previous ) {
         frame->function = NIL;
         frame->args = 0;
 
-        debug_print( L"make_empty_frame: about to initialise arg registers\n",
-                     DEBUG_STACK );
         for ( int i = 0; i < args_in_frame; i++ ) {
-            set_reg( frame, i, NIL );
+            frame->arg[i] = NIL;
         }
     }
-    debug_print( L"Leaving make_empty_frame\n", DEBUG_STACK );
+    debug_print( L"Leaving make_empty_frame\n", DEBUG_ALLOC );
+    debug_dump_object( result, DEBUG_ALLOC);
 
     return result;
 }
@@ -121,8 +124,7 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
     } else {
         struct stack_frame *frame = get_stack_frame( result );
 
-        for ( frame->args = 0; frame->args < args_in_frame && consp( args );
-              frame->args++ ) {
+        while ( frame->args < args_in_frame && consp( args )) {
             /* iterate down the arg list filling in the arg slots in the
              * frame. When there are no more slots, if there are still args,
              * stash them on more */
@@ -134,23 +136,7 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
              * processor to be evaled in parallel; but see notes here:
              * https://github.com/simon-brooke/post-scarcity/wiki/parallelism
              */
-            struct cons_pointer arg_frame_pointer = make_empty_frame( result );
-            inc_ref( arg_frame_pointer );
-
-            if ( nilp( arg_frame_pointer ) ) {
-                result =
-                    make_exception( c_string_to_lisp_string
-                                    ( L"Memory exhausted." ), previous );
-                break;
-            } else {
-                struct stack_frame *arg_frame =
-                    get_stack_frame( arg_frame_pointer );
-                    debug_print( L"Setting argument 0 of arg_frame to ", DEBUG_STACK);
-                    debug_print_object(cell.payload.cons.car, DEBUG_STACK);
-                set_reg( arg_frame, 0, cell.payload.cons.car );
-
-                struct cons_pointer val =
-                    lisp_eval( arg_frame, arg_frame_pointer, env );
+                struct cons_pointer val = eval_form(frame, result, cell.payload.cons.car, env);
                 if ( exceptionp( val ) ) {
                     result = val;
                     break;
@@ -160,11 +146,9 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
                     set_reg( frame, frame->args, val );
                 }
 
-                dec_ref( arg_frame_pointer );
-
                 args = cell.payload.cons.cdr;
             }
-        }
+
         if ( !exceptionp( result ) ) {
             if ( consp( args ) ) {
                 /* if we still have args, eval them and stick the values on `more` */
@@ -175,10 +159,10 @@ struct cons_pointer make_stack_frame( struct cons_pointer previous,
                 inc_ref( more );
             }
 
-            debug_dump_object( result, DEBUG_STACK );
         }
     }
-    debug_print( L"Leaving make_stack_frame\n", DEBUG_STACK );
+    debug_print( L"make_stack_frame: returning\n", DEBUG_STACK );
+    debug_dump_object( result, DEBUG_STACK );
 
     return result;
 }
@@ -206,8 +190,7 @@ struct cons_pointer make_special_frame( struct cons_pointer previous,
     } else {
         struct stack_frame *frame = get_stack_frame( result );
 
-        for ( frame->args = 0; frame->args < args_in_frame && !nilp( args );
-              frame->args++ ) {
+        while ( frame->args < args_in_frame && !nilp( args )) {
             /* iterate down the arg list filling in the arg slots in the
              * frame. When there are no more slots, if there are still args,
              * stash them on more */
@@ -222,11 +205,10 @@ struct cons_pointer make_special_frame( struct cons_pointer previous,
                 frame->more = args;
                 inc_ref( args );
             }
-
-            debug_dump_object( result, DEBUG_STACK );
         }
     }
-    debug_print( L"Leaving make_special_frame\n", DEBUG_STACK );
+    debug_print( L"make_special_frame: returning\n", DEBUG_STACK );
+    debug_dump_object( result, DEBUG_STACK );
 
     return result;
 }
diff --git a/src/memory/stack.h b/src/memory/stack.h
index b56f432..79cd1e2 100644
--- a/src/memory/stack.h
+++ b/src/memory/stack.h
@@ -39,7 +39,9 @@
  * set a register in a stack frame. Alwaye use this macro to do so,
  • because that way we can be sure the inc_ref happens!
  */
-#define set_reg(frame,register,value){frame->arg[register]=value; inc_ref(value);}
+//#define set_reg(frame,register,value){frame->arg[register]=value; inc_ref(value);}
+
+void set_reg(struct stack_frame * frame, int reg, struct cons_pointer value);
 
 struct stack_frame *get_stack_frame( struct cons_pointer pointer );
 
diff --git a/src/ops/intern.c b/src/ops/intern.c
index 8dea7c8..27c745d 100644
--- a/src/ops/intern.c
+++ b/src/ops/intern.c
@@ -111,6 +111,12 @@ struct cons_pointer c_assoc( struct cons_pointer key,
 struct cons_pointer
 bind( struct cons_pointer key, struct cons_pointer value,
       struct cons_pointer store ) {
+  debug_print(L"Binding ", DEBUG_ALLOC);
+  debug_print_object(key, DEBUG_ALLOC);
+  debug_print(L" to ", DEBUG_ALLOC);
+  debug_print_object(value, DEBUG_ALLOC);
+  debug_println(DEBUG_ALLOC);
+
     return make_cons( make_cons( key, value ), store );
 }
 
diff --git a/src/ops/lispops.c b/src/ops/lispops.c
index 43665e9..79195e4 100644
--- a/src/ops/lispops.c
+++ b/src/ops/lispops.c
@@ -94,6 +94,7 @@ struct cons_pointer eval_form( struct stack_frame *parent,
 
     struct stack_frame *next = get_stack_frame( next_pointer );
     set_reg( next, 0, form );
+    next->args = 1;
 
     result = lisp_eval( next, next_pointer, env );
 
@@ -253,25 +254,15 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
 struct cons_pointer
 c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
          struct cons_pointer env ) {
-    struct cons_pointer result = NIL;
+  debug_print(L"Entering c_apply\n", DEBUG_EVAL);
+  struct cons_pointer result = NIL;
 
-    /* construct a child frame and within it evaluate the first argument - the
-     * argument in the function position. */
-    struct cons_pointer fn_frame_pointer = make_empty_frame( frame_pointer );
-    inc_ref( fn_frame_pointer );
-    struct stack_frame *fn_frame = get_stack_frame( fn_frame_pointer );
-
-    set_reg( fn_frame, 0, c_car( frame->arg[0] ) );
     struct cons_pointer fn_pointer =
-        lisp_eval( fn_frame, fn_frame_pointer, env );
-
-    if ( !exceptionp( result ) ) {
-        /* if we're returning an exception, we should NOT free the
-         * stack frame. Corollary is, when we free an exception, we
-         * should free all the frames it's holding on to. */
-        dec_ref( fn_frame_pointer );
-    }
+        eval_form( frame, frame_pointer, c_car( frame->arg[0] ), env );
 
+    if ( exceptionp( fn_pointer ) ) {
+        result = fn_pointer;
+    } else {
     struct cons_space_object fn_cell = pointer2cell( fn_pointer );
     struct cons_pointer args = c_cdr( frame->arg[0] );
 
@@ -327,9 +318,7 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
                     struct stack_frame *next =
                         get_stack_frame( frame_pointer );
                     result = eval_lambda( fn_cell, next, next_pointer, env );
-                    if ( !exceptionp( result ) ) {
                         dec_ref( next_pointer );
-                    }
                 }
             }
             break;
@@ -341,15 +330,14 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
                 if ( exceptionp( next_pointer ) ) {
                     result = next_pointer;
                 } else {
-                    struct stack_frame *next =
-                        get_stack_frame( frame_pointer );
                     result =
-                        ( *fn_cell.payload.special.executable ) ( next,
+                        ( *fn_cell.payload.special.executable ) ( get_stack_frame( next_pointer ),
                                                                   next_pointer,
                                                                   env );
-                    if ( !exceptionp( result ) ) {
-                        dec_ref( next_pointer );
-                    }
+                   debug_print(L"Special form returning: ", DEBUG_EVAL);
+                  debug_print_object(result, DEBUG_EVAL);
+                  debug_println(DEBUG_EVAL);
+                    dec_ref( next_pointer );
                 }
             }
             break;
@@ -367,7 +355,11 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
                 result = throw_exception( message, frame_pointer );
             }
     }
-    dec_ref( fn_frame_pointer );
+    }
+
+    debug_print(L"c_apply: returning: ", DEBUG_EVAL);
+    debug_print_object(result, DEBUG_EVAL);
+    debug_println(DEBUG_EVAL);
 
     return result;
 }
diff --git a/src/repl.c b/src/repl.c
index 04cf33c..e0170b6 100644
--- a/src/repl.c
+++ b/src/repl.c
@@ -52,16 +52,11 @@ struct cons_pointer repl_read( struct cons_pointer stream_pointer ) {
  * Dummy up a Lisp eval call with its own stack frame.
  */
 struct cons_pointer repl_eval( struct cons_pointer input ) {
-     debug_print( L"Entered repl_eval\n",  DEBUG_REPL );
+    debug_print( L"Entered repl_eval\n",  DEBUG_REPL );
     struct cons_pointer result = NIL;
-    struct cons_pointer frame_pointer = make_stack_frame( NIL, make_cons( input, NIL ), oblist);
 
-    if ( !nilp( frame_pointer ) ) {
-    inc_ref(frame_pointer);
-            result = lisp_eval( get_stack_frame( frame_pointer ), frame_pointer, oblist );
+    result = eval_form( NULL, NIL, input, oblist );
 
-        dec_ref( frame_pointer );
-    }
     debug_print( L"repl_eval: returning\n",  DEBUG_REPL );
     debug_dump_object( result, DEBUG_REPL );
 
@@ -73,15 +68,10 @@ struct cons_pointer repl_eval( struct cons_pointer input ) {
  */
 struct cons_pointer repl_print( struct cons_pointer stream_pointer,
                                 struct cons_pointer value ) {
-     debug_print( L"Entered repl_print\n",  DEBUG_REPL );
+    debug_print( L"Entered repl_print\n",  DEBUG_REPL );
     debug_dump_object( value, DEBUG_REPL );
-    struct cons_pointer result = NIL;
-    struct cons_pointer frame_pointer = make_stack_frame( NIL, make_cons( value, NIL ), oblist);
-    if ( !nilp( frame_pointer ) ) {
-    inc_ref(frame_pointer);
-        result = lisp_print( get_stack_frame( frame_pointer ), frame_pointer, oblist );
-        dec_ref( frame_pointer );
-    }
+    struct cons_pointer result =
+      print( pointer2cell( stream_pointer ).payload.stream.stream, value );
     debug_print( L"repl_print: returning\n",  DEBUG_REPL );
     debug_dump_object( result, DEBUG_REPL );
 
@@ -98,7 +88,7 @@ struct cons_pointer repl_print( struct cons_pointer stream_pointer,
 void
 repl( FILE * in_stream, FILE * out_stream, FILE * error_stream,
       bool show_prompt ) {
-     debug_print( L"Entered repl\n",  DEBUG_REPL );
+    debug_print( L"Entered repl\n",  DEBUG_REPL );
     struct cons_pointer input_stream = make_read_stream( in_stream );
     inc_ref( input_stream );
 

From 570634bc4325f833624c2215a2303b013cb9cb3c Mon Sep 17 00:00:00 2001
From: Simon Brooke <simon@journeyman.cc>
Date: Fri, 28 Dec 2018 21:33:35 +0000
Subject: [PATCH 6/6] Success! All tests pass.

---
 src/ops/lispops.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/src/ops/lispops.c b/src/ops/lispops.c
index 79195e4..82746e0 100644
--- a/src/ops/lispops.c
+++ b/src/ops/lispops.c
@@ -203,7 +203,7 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
     if ( consp( names ) ) {
         /* if `names` is a list, bind successive items from that list
          * to values of arguments */
-        for ( int i = 0; i < args_in_frame && consp( names ); i++ ) {
+        for ( int i = 0; i < frame->args && consp( names ); i++ ) {
             struct cons_pointer name = c_car( names );
             struct cons_pointer val = frame->arg[i];
 
@@ -212,6 +212,7 @@ eval_lambda( struct cons_space_object cell, struct stack_frame *frame,
 
             names = c_cdr( names );
         }
+      /* TODO: if there's more than `args_in_frame` arguments, bind those too. */
     } else if ( symbolp( names ) ) {
         /* if `names` is a symbol, rather than a list of symbols,
          * then bind a list of the values of args to that symbol. */
@@ -316,7 +317,7 @@ c_apply( struct stack_frame *frame, struct cons_pointer frame_pointer,
                     result = next_pointer;
                 } else {
                     struct stack_frame *next =
-                        get_stack_frame( frame_pointer );
+                        get_stack_frame( next_pointer );
                     result = eval_lambda( fn_cell, next, next_pointer, env );
                         dec_ref( next_pointer );
                 }