diff --git a/arr.sml b/arr.sml
index f9ee69a0b25b0948132b2e8fd6fc8a9b7ba3313e..4fd419abdf3437cf899e11d5added8c22fb79218 100644
--- a/arr.sml
+++ b/arr.sml
@@ -9,21 +9,36 @@              | STOP
 and     arr  = Lf of atom (* arrays as binary trees - SML doesn't allow arbitrarily nested lists *)
              | Nd of arr * arr
 with
+exception Domain;
+exception BadStop;
+exception NYI;
 fun Word(x) = Lf(N(x));
 fun Fun0(f) = Lf(FN(f));
 fun Fun1(f) = Lf(FM(f));
 fun Fun2(f) = Lf(FD(f));
 fun Stop() = Lf(STOP);
-fun array [] = Stop()
-  | array (x::xs) = Nd(x,array(xs));
+fun Array [] = Stop()
+  | Array (x::xs) = Nd(x,Array(xs));
 fun str(Lf(STOP)) = "!!" (* TODO: box-drawing characters might be nice in the future *)
   | str(Lf(N(x))) = Word8.fmt StringCvt.HEX x
   | str(Lf(FN(x))) = "(Nilad)" (* TODO: would be nice to get actual function names *)
   | str(Lf(FM(x))) = "(Monad)"
   | str(Lf(FD(x))) = "(Dyad)"
-  | str(Nd(x,y)) = "[" ^ str(x) ^ " " ^ str(y) ^ "]"
-fun apply(f,Lf(STOP)) = Lf(STOP) (* traverse the array tree, applying f to each leaf in turn *)
-  | apply(f,Lf(N(x))) = Lf(N(f(x)))
-  (* TODO: higher-order functions *)
-  | apply(f,Nd(x,y)) = Nd(apply(f,x),apply(f,y));
+  | str(Nd(x,y)) = "[" ^ str(x) ^ " " ^ str(y) ^ "]" (* FIXME: clearer nesting would be nice *)
+(* TODO: higher-order functions *)
+fun apply0(f) = raise NYI; (* TODO - what if it generates a whole array? *)
+fun apply1(f,Lf(STOP)) = Lf(STOP) (* traverse the array tree, applying f to each leaf in turn *)
+  | apply1(f,Lf(N(x))) = Lf(N(f(x)))
+  | apply1(f,Nd(x,y)) = Nd(apply1(f,x),apply1(f,y));
+fun apply2(f,x,y) = raise NYI; (* TODO *)
+fun append(x,a) = Nd(x,a);
+fun addD(x,Lf(STOP)) = x (* dyadic add *)
+  | addD(Lf(N(x)),Lf(N(y))) = Lf(N(x+y))
+  | addD(Nd(x,xs),Lf(N(y))) = Nd(Lf(N(x+y)),add(xs,Lf(N(y)))) (* FIXME: doesn't work because x might be a Nd - need to do cases for Nd(Lf(N(x)),xs) &c. *)
+  | addD(Lf(N(x)),Nd(y,ys)) = Nd(Lf(N(x+y)),add(Lf(N(x)),ys))
+  | addD(Nd(x,xs),Nd(y,ys)) = raise NYI; (* TODO *)
 end;
+
+(* Test data *)
+val a = Array([Word(0w2),Word(0w3),Word(0w4),Word(0w5)]);
+val b = Array([Word(0w2),Array([Word(0w3),Word(0w4)]),Word(0w5)]);
diff --git a/ast.sml b/ast.sml
index d1c5335d0180cf42d734895fbaf6a7cf54b11fe1..20c94d3a80424f8674c0045fc4061562a71d667e 100644
--- a/ast.sml
+++ b/ast.sml
@@ -1,5 +1,7 @@
 (* AST for a K-like language *)
 
+use "arr.sml"; (* TODO: open, nto use, for compiled version *)
+
 datatype ast = Leaf of arr
              | Nilad of unit -> arr
              | Monad of (arr -> arr) * ast
@@ -12,6 +14,9 @@                        Leaf(a)     => a
                      | Nilad(f)    => f()
                      | Monad(f,r)  => f(eval_ast(r))
                      | Dyad(f,l,r) => f(eval_ast(l),eval_ast(r));
+
+(* TODO: codegen_ast (eval_ast evaluates it in ML, but we need to output ASM!) *)
+
 (*
 (* Test data *)
 val x = S(N(0w2));
