فهرست منبع

Changed constant node types, added VarDecs|LocalFuns wrappers, implemented first steps of assembler

Taddeus Kroes 12 سال پیش
والد
کامیت
21fc065c8f
21فایلهای تغییر یافته به همراه469 افزوده شده و 331 حذف شده
  1. 1 1
      Makefile
  2. 2 0
      README.md
  3. 12 10
      main.ml
  4. 5 5
      parser.mly
  5. 50 39
      phases/assemble.ml
  6. 4 4
      phases/bool_op.ml
  7. 67 69
      phases/constant_propagation.ml
  8. 31 32
      phases/context_analysis.ml
  9. 39 40
      phases/desug.ml
  10. 1 1
      phases/dim_reduce.ml
  11. 1 1
      phases/expand_dims.ml
  12. 2 2
      phases/extern_vars.ml
  13. 1 1
      phases/parse.ml
  14. 37 23
      phases/print.ml
  15. 4 4
      phases/typecheck.ml
  16. 23 11
      stringify.ml
  17. 5 3
      stringify.mli
  18. 1 2
      test/old/array_dim.cvc
  19. 28 17
      types.ml
  20. 151 66
      util.ml
  21. 4 0
      util.mli

+ 1 - 1
Makefile

@@ -1,6 +1,6 @@
 RESULT := civicc
 RESULT := civicc
 PHASES := load parse print desug context_analysis expand_dims typecheck \
 PHASES := load parse print desug context_analysis expand_dims typecheck \
-	dim_reduce bool_op extern_vars constant_propagation
+	dim_reduce bool_op extern_vars constant_propagation depth_analysis assemble
 SOURCES := types.ml stringify.mli stringify.ml util.mli util.ml lexer.mll \
 SOURCES := types.ml stringify.mli stringify.ml util.mli util.ml lexer.mll \
 	parser.mly $(patsubst %,phases/%.ml,$(PHASES)) main.ml
 	parser.mly $(patsubst %,phases/%.ml,$(PHASES)) main.ml
 PRE_TARGETS := types.cmi types.o stringify.cmi stringify.o util.cmi util.o
 PRE_TARGETS := types.cmi types.o stringify.cmi stringify.o util.cmi util.o

+ 2 - 0
README.md

@@ -9,3 +9,5 @@ Issues & TODO
 
 
 - Keep file content in buffer to prevent error messages from crashing when
 - Keep file content in buffer to prevent error messages from crashing when
   reading from stdin.
   reading from stdin.
+- Maybe declarations should be saved as references to allow the declarations to
+  be modified (does make pattern matching a bit harder).

+ 12 - 10
main.ml

@@ -12,28 +12,30 @@ let compile () =
     in
     in
     run_phases Empty [
     run_phases Empty [
         Load.phase;
         Load.phase;
-        Print.phase;
+        (*Print.phase;*)
         Parse.phase;
         Parse.phase;
-        Print.phase;
+        (*Print.phase;*)
         Desug.phase;
         Desug.phase;
-        Print.phase;
+        (*Print.phase;*)
         Context_analysis.phase;
         Context_analysis.phase;
-        Print.phase;
+        (*Print.phase;*)
         Typecheck.phase;
         Typecheck.phase;
-        Print.phase;
+        (*Print.phase;*)
         Expand_dims.phase;
         Expand_dims.phase;
-        Print.phase;
+        (*Print.phase;*)
         Bool_op.phase;
         Bool_op.phase;
-        Print.phase;
+        (*Print.phase;*)
         Dim_reduce.phase;
         Dim_reduce.phase;
-        Print.phase;
+        (*Print.phase;*)
         Extern_vars.phase;
         Extern_vars.phase;
-        Print.phase;
+        (*Print.phase;*)
         Constant_propagation.phase;
         Constant_propagation.phase;
         Print.phase;
         Print.phase;
-        (*
+        Depth_analysis.phase;
+        Print.phase;
         Assemble.phase;
         Assemble.phase;
         Print.phase;
         Print.phase;
+        (*
         Peephole.phase;
         Peephole.phase;
         Print.phase;
         Print.phase;
         *)
         *)

+ 5 - 5
parser.mly

@@ -117,7 +117,7 @@ param:
 
 
 fun_body:
 fun_body:
     | var_dec* local_fun_dec* statement* loption(return_statement)
     | var_dec* local_fun_dec* statement* loption(return_statement)
-    { $1 @ $2 @ $3 @ $4 }
+    { VarDecs $1 :: (LocalFuns $2) :: $3 @ $4 }
 
 
 return_statement:
 return_statement:
     (* return statement: use location of return value *)
     (* return statement: use location of return value *)
@@ -177,7 +177,7 @@ statement:
     | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN;
     | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN;
       body=block
       body=block
     { let loc = loc $startpos(cnt) $endpos(cnt) in
     { let loc = loc $startpos(cnt) $endpos(cnt) in
-        For (cnt, start, stop, IntConst (1, []), Block body, loc) }
+        For (cnt, start, stop, Const (IntVal 1, []), Block body, loc) }
 
 
     | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; COMMA;
     | FOR; LPAREN; INT; cnt=ID; ASSIGN; start=expr; COMMA; stop=expr; COMMA;
       step=expr; RPAREN; body=block
       step=expr; RPAREN; body=block
@@ -198,9 +198,9 @@ expr:
     | SUB; expr                         { Monop (Neg, $2, loc $startpos $endpos) }    %prec NEG
     | SUB; expr                         { Monop (Neg, $2, loc $startpos $endpos) }    %prec NEG
     | NOT; expr                         { Monop (Not, $2, loc $startpos $endpos) }
     | NOT; expr                         { Monop (Not, $2, loc $startpos $endpos) }
     | LPAREN; basic_type; RPAREN; expr  { TypeCast ($2, $4, loc $startpos $endpos) }  %prec CAST
     | LPAREN; basic_type; RPAREN; expr  { TypeCast ($2, $4, loc $startpos $endpos) }  %prec CAST
-    | FLOAT_CONST                       { FloatConst ($1, loc $startpos $endpos) }
-    | INT_CONST                         { IntConst ($1, loc $startpos $endpos) }
-    | BOOL_CONST                        { BoolConst ($1, loc $startpos $endpos) }
+    | FLOAT_CONST                       { Const (FloatVal $1, loc $startpos $endpos) }
+    | INT_CONST                         { Const (IntVal $1, loc $startpos $endpos) }
+    | BOOL_CONST                        { Const (BoolVal $1, loc $startpos $endpos) }
     | ID; array_const                   { Var ($1, Some $2, loc $startpos $endpos) }
     | ID; array_const                   { Var ($1, Some $2, loc $startpos $endpos) }
     | array_const                       { ArrayConst ($1, loc $startpos $endpos) }
     | array_const                       { ArrayConst ($1, loc $startpos $endpos) }
 
 

+ 50 - 39
phases/assemble.ml

@@ -1,9 +1,6 @@
 open Types
 open Types
 open Util
 open Util
 
 
-let store ctype = function
-    | 0 -> StoreGlob ()
-
 let assemble program =
 let assemble program =
     let labcounter = ref 0 in
     let labcounter = ref 0 in
     let genlabel suffix =
     let genlabel suffix =
@@ -11,63 +8,77 @@ let assemble program =
         string_of_int !labcounter ^ "_" ^ suffix
         string_of_int !labcounter ^ "_" ^ suffix
     in
     in
 
 
-    let consts = ref [] in
-    let const_index const =
-        let rec trav_consts i = function
-            | [] -> consts := !consts @ [const]; i
-            | hd :: _ when hd = const -> i
-            | hd :: tl -> trav_consts (i + 1) tl
-        in
-        trav_consts 0 !consts
-    in
+    let consts = Hashtbl.create 20 in
 
 
-    let rec trav node =
+    let rec trav_args callstack localfuns node =
+        let trav = trav_args callstack localfuns in
         let rec trav_all = function
         let rec trav_all = function
             | [] -> []
             | [] -> []
             | hd :: tl -> trav hd @ (trav_all tl)
             | hd :: tl -> trav hd @ (trav_all tl)
         in
         in
+        let rec traverse_localfuns = function
+            | LocalFuns funs -> trav_all funs
+            | Block body -> List.concat (List.map traverse_localfuns body)
+            | _ -> []
+        in
         match node with
         match node with
         | Program (decls, _) ->
         | Program (decls, _) ->
             trav_all decls
             trav_all decls
 
 
         | FunDec (ret_type, name, params, _) ->
         | FunDec (ret_type, name, params, _) ->
-            [Import (name, ret_type, List.map ctypeof params)]
+            [Import (name, ret_type, List.map typeof params)]
 
 
         | FunDef (export, ret_type, name, params, body, _) ->
         | FunDef (export, ret_type, name, params, body, _) ->
-            let label = name in
-            let param_types = List.map ctypeof params in
-            let export = match export with
-                | false -> []
-                | true -> [Export (name, ret_type, param_types, label)]
-            in
-            Comment ("function \"" ^ name ^ "\":") ::
-            (export @ (Label label :: (trav body)))
+            localfuns := node :: !localfuns;
+            let callstack = name :: callstack in
+            let localfuns = ref [] in
+            let label = String.concat "$" (List.rev callstack) in
+            (if export then
+                let param_types = List.map typeof params in
+                [Export (name, ret_type, param_types, label)]
+            else []) @
+            [
+                Comment ("function \"" ^ label ^ "\":");
+                Label label;
+                RtnEnter (indexof node);
+            ] @
+            (trav_args callstack localfuns body) @
+            (match ret_type with Void -> [Ret Void] | _ -> []) @
+            [EmptyLine] @
+            (traverse_localfuns body)
 
 
-        | VarDec (ctype, name, None, _) ->
-            []
+        (* Local fucntions are traversed elsewhere *)
+        | LocalFuns _ -> []
 
 
-        | VarLet (Assign (name, None, value, _), ctype, depth) ->
-            [store ctype depth]
-        (*
-        | VarLet (Assign (name, Some indices, value, _), ctype, depth) ->
-            [store deoth]
-        *)
+        | Block body -> trav_all body
 
 
-        | BoolConst _ ->
-            [LoadImm node]
+        | VarLet (dec, None, value, _) ->
+            let store = match (depthof dec, depthof node) with
+                | (0, _)            -> StoreGlob (typeof dec, indexof dec)
+                | (a, b) when a = b -> StoreLoc  (typeof dec, indexof dec)
+                | (a, b)            -> StoreRel  (typeof dec, b - a, indexof dec)
+            in
+            trav value @ [store]
 
 
-        | IntConst _ | FloatConst _ ->
-            [LoadConst (ctypeof node, const_index node)]
+        | Return (value, _) ->
+            trav value @ [Ret (typeof value)]
+
+        | Const (BoolVal _, _) ->
+            [LoadImm node]
+        | Const (value, _) ->
+            let def = if Hashtbl.mem consts value then [] else (
+                Hashtbl.add consts value true;
+                [ConstDef value]
+            ) in
+            def @ [LoadConst (typeof node, indexof node)]
 
 
         | _ -> []
         | _ -> []
         (*| _ -> raise InvalidNode*)
         (*| _ -> raise InvalidNode*)
     in
     in
-    let instrs = trav program in
-    let const_defs = List.map (fun c -> Const c) !consts in
-    const_defs @ instrs
+    trav_args [] (ref []) program
 
 
 let rec phase input =
 let rec phase input =
-    prerr_endline "- Assembly";
+    log_line 2 "- Assembly";
     match input with
     match input with
-    | Types node -> Assembly (assemble node)
+    | Ast node -> Assembly (assemble node)
     | _ -> raise (InvalidInput "assembly")
     | _ -> raise (InvalidInput "assembly")

+ 4 - 4
phases/bool_op.ml

@@ -21,9 +21,9 @@ open Util
 
 
 let cast ctype node = TypeCast (ctype, node, [Type ctype])
 let cast ctype node = TypeCast (ctype, node, [Type ctype])
 
 
-let boolconst  value = BoolConst  (value, [Type Bool])
-let intconst   value = IntConst   (value, [Type Int])
-let floatconst value = FloatConst (value, [Type Float])
+let boolconst  value = Const (BoolVal  value, [Type Bool])
+let intconst   value = Const (IntVal   value, [Type Int])
+let floatconst value = Const (FloatVal value, [Type Float])
 
 
 let rec trav_binop = function
 let rec trav_binop = function
     | ((Eq | Ne) as op, left, right, loc) ->
     | ((Eq | Ne) as op, left, right, loc) ->
@@ -62,5 +62,5 @@ and bool_op = function
 let rec phase input =
 let rec phase input =
     log_line 2 "- Convert bool operations";
     log_line 2 "- Convert bool operations";
     match input with
     match input with
-    | Types node -> Types (bool_op node)
+    | Ast node -> Ast (bool_op node)
     | _ -> raise (InvalidInput "bool operations")
     | _ -> raise (InvalidInput "bool operations")

+ 67 - 69
phases/constant_propagation.ml

@@ -16,77 +16,75 @@ open Util
 let is_const_name name =
 let is_const_name name =
     Str.string_match (Str.regexp "^.+\\$\\$[0-9]+$") name 0
     Str.string_match (Str.regexp "^.+\\$\\$[0-9]+$") name 0
 
 
-let is_const = function
-    | BoolConst _ | IntConst _ | FloatConst _ -> true
-    | _ -> false
+let is_const = function Const _ -> true | _ -> false
 
 
 let eval_monop = function
 let eval_monop = function
-    | (Not, BoolConst  (value, _), ann) -> BoolConst  (not value, ann)
-    | (Neg, IntConst   (value, _), ann) -> IntConst   (-value, ann)
-    | (Neg, FloatConst (value, _), ann) -> FloatConst (-.value, ann)
+    | (Not, Const (BoolVal  value, _), ann) -> Const (BoolVal  (not value), ann)
+    | (Neg, Const (IntVal   value, _), ann) -> Const (IntVal   (-value), ann)
+    | (Neg, Const (FloatVal value, _), ann) -> Const (FloatVal (-.value), ann)
     | (op, opnd, ann) -> Monop (op, opnd, ann)
     | (op, opnd, ann) -> Monop (op, opnd, ann)
 
 
 let eval_binop = function
 let eval_binop = function
     (* Arithmetic *)
     (* Arithmetic *)
-    | (Add, IntConst (left, _), IntConst (right, _), ann) ->
-        IntConst (left + right, ann)
-    | (Add, FloatConst (left, _), FloatConst (right, _), ann) ->
-        FloatConst (left +. right, ann)
+    | (Add, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (IntVal (left + right), ann)
+    | (Add, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (FloatVal (left +. right), ann)
 
 
-    | (Sub, IntConst (left, _), IntConst (right, _), ann) ->
-        IntConst (left - right, ann)
-    | (Sub, FloatConst (left, _), FloatConst (right, _), ann) ->
-        FloatConst (left -. right, ann)
+    | (Sub, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (IntVal (left - right), ann)
+    | (Sub, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (FloatVal (left -. right), ann)
 
 
-    | (Mul, IntConst (left, _), IntConst (right, _), ann) ->
-        IntConst (left * right, ann)
-    | (Mul, FloatConst (left, _), FloatConst (right, _), ann) ->
-        FloatConst (left *. right, ann)
+    | (Mul, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (IntVal (left * right), ann)
+    | (Mul, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (FloatVal (left *. right), ann)
 
 
-    | (Div, IntConst (left, _), IntConst (right, _), ann) ->
-        IntConst (left / right, ann)
-    | (Div, FloatConst (left, _), FloatConst (right, _), ann) ->
-        FloatConst (left /. right, ann)
+    | (Div, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (IntVal (left / right), ann)
+    | (Div, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (FloatVal (left /. right), ann)
 
 
-    | (Mod, IntConst (left, _), IntConst (right, _), ann) ->
-        IntConst (left mod right, ann)
+    | (Mod, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (IntVal (left mod right), ann)
 
 
     (* Relational *)
     (* Relational *)
-    | (Eq, IntConst (left, _), IntConst (right, _), ann) ->
-        BoolConst (left = right, ann)
-    | (Eq, FloatConst (left, _), FloatConst (right, _), ann) ->
-        BoolConst (left = right, ann)
-
-    | (Ne, IntConst (left, _), IntConst (right, _), ann) ->
-        BoolConst (left != right, ann)
-    | (Ne, FloatConst (left, _), FloatConst (right, _), ann) ->
-        BoolConst (left != right, ann)
-
-    | (Gt, IntConst (left, _), IntConst (right, _), ann) ->
-        BoolConst (left > right, ann)
-    | (Gt, FloatConst (left, _), FloatConst (right, _), ann) ->
-        BoolConst (left > right, ann)
-
-    | (Lt, IntConst (left, _), IntConst (right, _), ann) ->
-        BoolConst (left < right, ann)
-    | (Lt, FloatConst (left, _), FloatConst (right, _), ann) ->
-        BoolConst (left < right, ann)
-
-    | (Ge, IntConst (left, _), IntConst (right, _), ann) ->
-        BoolConst (left >= right, ann)
-    | (Ge, FloatConst (left, _), FloatConst (right, _), ann) ->
-        BoolConst (left >= right, ann)
-
-    | (Le, IntConst (left, _), IntConst (right, _), ann) ->
-        BoolConst (left <= right, ann)
-    | (Le, FloatConst (left, _), FloatConst (right, _), ann) ->
-        BoolConst (left <= right, ann)
+    | (Eq, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (BoolVal (left = right), ann)
+    | (Eq, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (BoolVal (left = right), ann)
+
+    | (Ne, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (BoolVal (left != right), ann)
+    | (Ne, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (BoolVal (left != right), ann)
+
+    | (Gt, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (BoolVal (left > right), ann)
+    | (Gt, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (BoolVal (left > right), ann)
+
+    | (Lt, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (BoolVal (left < right), ann)
+    | (Lt, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (BoolVal (left < right), ann)
+
+    | (Ge, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (BoolVal (left >= right), ann)
+    | (Ge, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (BoolVal (left >= right), ann)
+
+    | (Le, Const (IntVal left, _), Const (IntVal right, _), ann) ->
+        Const (BoolVal (left <= right), ann)
+    | (Le, Const (FloatVal left, _), Const (FloatVal right, _), ann) ->
+        Const (BoolVal (left <= right), ann)
 
 
     (* Logical *)
     (* Logical *)
-    | (And, BoolConst (left, _), BoolConst (right, _), ann) ->
-        BoolConst (left && right, ann)
-    | (Or, BoolConst (left, _), BoolConst (right, _), ann) ->
-        BoolConst (left || right, ann)
+    | (And, Const (BoolVal left, _), Const (BoolVal right, _), ann) ->
+        Const (BoolVal (left && right), ann)
+    | (Or, Const (BoolVal left, _), Const (BoolVal right, _), ann) ->
+        Const (BoolVal (left || right), ann)
 
 
     | (op, left, right, ann) -> Binop (op, left, right, ann)
     | (op, left, right, ann) -> Binop (op, left, right, ann)
 
 
@@ -139,22 +137,22 @@ let rec propagate consts node =
         let texp = propagate texp in
         let texp = propagate texp in
         let fexp = propagate fexp in
         let fexp = propagate fexp in
         (match cond with
         (match cond with
-        | BoolConst (value, _) -> if value then texp else fexp
+        | Const (BoolVal value, _) -> if value then texp else fexp
         | _ -> Cond (cond, texp, fexp, ann)
         | _ -> Cond (cond, texp, fexp, ann)
         )
         )
 
 
     | TypeCast (ctype, value, ann) ->
     | TypeCast (ctype, value, ann) ->
         let value = propagate value in
         let value = propagate value in
         (match (ctype, value) with
         (match (ctype, value) with
-        | (Bool,  BoolConst  (value, _)) -> BoolConst (value, ann)
-        | (Bool,  IntConst   (value, _)) -> BoolConst (value != 1, ann)
-        | (Bool,  FloatConst (value, _)) -> BoolConst (value != 1.0, ann)
-        | (Int,   BoolConst  (value, _)) -> IntConst ((if value then 1 else 0), ann)
-        | (Int,   IntConst   (value, _)) -> IntConst (value, ann)
-        | (Int,   FloatConst (value, _)) -> IntConst (int_of_float value, ann)
-        | (Float, BoolConst  (value, _)) -> FloatConst ((if value then 1. else 0.), ann)
-        | (Float, IntConst   (value, _)) -> FloatConst (float_of_int value, ann)
-        | (Float, FloatConst (value, _)) -> FloatConst (value, ann)
+        | (Bool,  Const (BoolVal  value, _)) -> Const (BoolVal value, ann)
+        | (Bool,  Const (IntVal   value, _)) -> Const (BoolVal (value != 1), ann)
+        | (Bool,  Const (FloatVal value, _)) -> Const (BoolVal (value != 1.0), ann)
+        | (Int,   Const (BoolVal  value, _)) -> Const (IntVal (if value then 1 else 0), ann)
+        | (Int,   Const (IntVal   value, _)) -> Const (IntVal value, ann)
+        | (Int,   Const (FloatVal value, _)) -> Const (IntVal (int_of_float value), ann)
+        | (Float, Const (BoolVal  value, _)) -> Const (FloatVal (if value then 1. else 0.), ann)
+        | (Float, Const (IntVal   value, _)) -> Const (FloatVal (float_of_int value), ann)
+        | (Float, Const (FloatVal value, _)) -> Const (FloatVal value, ann)
         | _ -> TypeCast (ctype, value, ann)
         | _ -> TypeCast (ctype, value, ann)
         )
         )
 
 
@@ -167,8 +165,8 @@ let rec prune_vardecs consts = function
 let rec phase input =
 let rec phase input =
     log_line 2 "- Constant propagation";
     log_line 2 "- Constant propagation";
     match input with
     match input with
-    | Types node ->
+    | Ast node ->
         let consts = Hashtbl.create 32 in
         let consts = Hashtbl.create 32 in
         let node = propagate consts node in
         let node = propagate consts node in
-        Types (prune_vardecs consts node)
+        Ast (prune_vardecs consts node)
     | _ -> raise (InvalidInput "constant propagation")
     | _ -> raise (InvalidInput "constant propagation")

+ 31 - 32
phases/context_analysis.ml

@@ -25,28 +25,25 @@ let check_in_scope name errnode scope =
         in
         in
         raise (NodeError (errnode, msg))
         raise (NodeError (errnode, msg))
 
 
-let rec analyse scope depth args node =
-    (* add_to_scope uses args, so it needs to be defined here *)
-    let add_to_scope name dec depth scope =
-        let (vars, funs) = scope in
-        let (name, tbl, name_type) = match name with
-            | Varname name  -> (name, vars, "variable")
-            | Funcname name -> (name, funs, "function")
-        in
-        match mapfind name tbl with
-        (* Identifiers of lower depth may be overwritten, but idenetifiers at
-         * the same depth must be unique for consistency *)
-        | Some (orig, orig_depth, _) when orig_depth >= depth ->
-            let msg = sprintf "Error: cannot redeclare %s \"%s\"" name_type name in
-            prerr_loc_msg (locof dec) msg args.verbose;
-            prerr_loc_msg (locof orig) "Previously declared here:" args.verbose;
-            raise EmptyError
-        | Some _ ->
-            Hashtbl.replace tbl name (dec, depth, name_type)
-        | None ->
-            Hashtbl.add tbl name (dec, depth, name_type)
+let add_to_scope name dec depth (vars, funs) =
+    let (name, tbl, name_type) = match name with
+        | Varname name  -> (name, vars, "variable")
+        | Funcname name -> (name, funs, "function")
     in
     in
+    match mapfind name tbl with
+    (* Identifiers of lower depth may be overwritten, but idenetifiers at
+        * the same depth must be unique for consistency *)
+    | Some (orig, orig_depth, _) when orig_depth >= depth ->
+        let msg = sprintf "Error: cannot redeclare %s \"%s\"" name_type name in
+        prerr_loc_msg (locof dec) msg args.verbose;
+        prerr_loc_msg (locof orig) "Previously declared here:" args.verbose;
+        raise EmptyError
+    | Some _ ->
+        Hashtbl.replace tbl name (dec, depth, name_type)
+    | None ->
+        Hashtbl.add tbl name (dec, depth, name_type)
 
 
+let rec analyse scope depth node =
     let rec collect node = match node with
     let rec collect node = match node with
         (* Add node reference for this varname to vars map *)
         (* Add node reference for this varname to vars map *)
         | VarDec (ctype, name, init, ann) ->
         | VarDec (ctype, name, init, ann) ->
@@ -59,9 +56,12 @@ let rec analyse scope depth args node =
             node
             node
 
 
         (* For global vars, only the name and array dimensions *)
         (* For global vars, only the name and array dimensions *)
-        | GlobalDec (Array (ctype, dims), name, ann) ->
-            let node = GlobalDec (Array (ctype, List.map collect dims), name,
-                                  Depth depth :: ann) in
+        | GlobalDec (ctype, name, ann) ->
+            let ctype = match ctype with
+                | Array (ctype, dims) -> Array (ctype, List.map collect dims)
+                | _ -> ctype
+            in
+            let node = GlobalDec (ctype, name, Depth depth :: ann) in
             add_to_scope (Varname name) node depth scope;
             add_to_scope (Varname name) node depth scope;
             node
             node
 
 
@@ -70,12 +70,11 @@ let rec analyse scope depth args node =
             add_to_scope (Varname name) node depth scope;
             add_to_scope (Varname name) node depth scope;
             node
             node
 
 
-        | GlobalDec (ctype, name, ann) ->
-            let node = GlobalDec (ctype, name, Depth depth :: ann) in
-            add_to_scope (Varname name) node depth scope;
-            node
-
         | GlobalDef (export, ctype, name, init, ann) ->
         | GlobalDef (export, ctype, name, init, ann) ->
+            let ctype = match ctype with
+                | Array (ctype, dims) -> Array (ctype, List.map collect dims)
+                | _ -> ctype
+            in
             let node = GlobalDef (export, ctype, name, init, Depth depth :: ann) in
             let node = GlobalDef (export, ctype, name, init, Depth depth :: ann) in
             add_to_scope (Varname name) node depth scope;
             add_to_scope (Varname name) node depth scope;
             node
             node
@@ -117,7 +116,7 @@ let rec analyse scope depth args node =
             let (vars, funs) = scope in
             let (vars, funs) = scope in
             let local_scope = (Hashtbl.copy vars, Hashtbl.copy funs) in
             let local_scope = (Hashtbl.copy vars, Hashtbl.copy funs) in
             let params = List.map (traverse local_scope (depth + 1)) params in
             let params = List.map (traverse local_scope (depth + 1)) params in
-            let body = analyse local_scope (depth + 1) args body in
+            let body = analyse local_scope (depth + 1) body in
             FunDef (export, ret_type, name, params, body, ann)
             FunDef (export, ret_type, name, params, body, ann)
 
 
         | Param (Array (ctype, dims), name, ann) as node ->
         | Param (Array (ctype, dims), name, ann) as node ->
@@ -154,12 +153,12 @@ let rec analyse scope depth args node =
     let node = traverse scope depth node in
     let node = traverse scope depth node in
     node
     node
 
 
-let analyse_context args program =
+let analyse_context program =
     let scope = (Hashtbl.create 20, Hashtbl.create 20) in
     let scope = (Hashtbl.create 20, Hashtbl.create 20) in
-    analyse scope 0 args program
+    analyse scope 0 program
 
 
 let rec phase input =
 let rec phase input =
     log_line 2 "- Context analysis";
     log_line 2 "- Context analysis";
     match input with
     match input with
-    | Types node -> Types (analyse_context args node)
+    | Ast node -> Ast (analyse_context node)
     | _ -> raise (InvalidInput "context analysis")
     | _ -> raise (InvalidInput "context analysis")

+ 39 - 40
phases/desug.ml

@@ -53,46 +53,45 @@ let rec var_init = function
                alloc)
                alloc)
 
 
     (* Split local variable initialisations in declaration and assignment *)
     (* Split local variable initialisations in declaration and assignment *)
-    | FunDef (export, ret_type, name, params, Block body, ann) ->
-        let move_inits body =
-            let rec trav inits node = match node with
-                (* Translate scalar array initialisation to ArrayScalar node,
-                 * for easy replacement later on *)
-                | VarDec (Array _ as vtype, name, Some (BoolConst _  as v), ann) :: tl
-                | VarDec (Array _ as vtype, name, Some (FloatConst _ as v), ann) :: tl
-                | VarDec (Array _ as vtype, name, Some (IntConst _   as v), ann) :: tl ->
-                    let init = Some (ArrayInit (ArrayScalar v, vtype)) in
-                    trav inits (VarDec (vtype, name, init, ann) :: tl)
+    | FunDef (export, ret_type, name, params, body, ann) ->
+        let inits = ref [] in
+        let rec extract_inits = function
+            (* Translate scalar array initialisation to ArrayScalar node,
+                * for easy replacement later on *)
+            | VarDec (Array _ as vtype, name, Some (Const _   as v), ann) ->
+                let init = Some (ArrayInit (ArrayScalar v, vtype)) in
+                extract_inits (VarDec (vtype, name, init, ann))
 
 
-                (* Wrap ArrayConst in ArrayInit to pass dimensions *)
-                | VarDec (Array _ as vtype, name, Some (ArrayConst _ as v), ann) :: tl ->
-                    let init = Some (ArrayInit (v, vtype)) in
-                    trav inits (VarDec (vtype, name, init, ann) :: tl)
+            (* Wrap ArrayConst in ArrayInit to pass dimensions *)
+            | VarDec (Array _ as vtype, name, Some (ArrayConst _ as v), ann) ->
+                let init = Some (ArrayInit (v, vtype)) in
+                extract_inits (VarDec (vtype, name, init, ann))
 
 
-                | VarDec (ctype, name, init, ann) as dec :: tl ->
-                    (* array definition: create __allocate statement *)
-                    let alloc = match ctype with
-                        | Array (_, dims) -> [Allocate (name, dims, dec, ann)]
-                        | _ -> []
-                    in
-                    (* initialisation: create assign statement *)
-                    let add = match init with
-                        | Some value -> alloc @ [Assign (name, None, value, ann)]
-                        | None -> alloc
-                    in
-                    VarDec (ctype, name, None, ann) :: (trav (inits @ add) tl)
-
-                (* initialisations need to be placed after local functions *)
-                | (FunDef (_, _, _, _, _, _) as h) :: tl ->
-                    (var_init h) :: (trav inits tl)
+            | VarDec (ctype, name, init, ann) as dec ->
+                (* array definition: create __allocate statement *)
+                let alloc = match ctype with
+                    | Array (_, dims) -> [Allocate (name, dims, dec, ann)]
+                    | _ -> []
+                in
+                (* initialisation: create assign statement *)
+                let add = match init with
+                    | Some value -> alloc @ [Assign (name, None, value, ann)]
+                    | None -> alloc
+                in
+                inits := !inits @ add;
+                VarDec (ctype, name, None, ann)
 
 
-                (* rest of function body: recurse *)
-                | rest -> inits @ (List.map var_init rest)
-            in
-            flatten_blocks (trav [] body)
+            | node -> transform_children extract_inits node
+        in
+        let rec place_inits = function
+            (* initialisations need to be placed after local functions *)
+            | (LocalFuns _ as hd) :: tl -> hd :: !inits @ tl
+            | hd :: tl -> hd :: (place_inits tl)
+            | [] -> []
         in
         in
         let params = flatten_blocks (List.map var_init params) in
         let params = flatten_blocks (List.map var_init params) in
-        FunDef (export, ret_type, name, params, Block (move_inits body), ann)
+        let body = flatten_blocks (place_inits (block_body (extract_inits body))) in
+        FunDef (export, ret_type, name, params, Block body, ann)
 
 
     | node -> transform_children var_init node
     | node -> transform_children var_init node
 
 
@@ -127,7 +126,7 @@ let for_to_while node =
             let vstop = Var (_stop, None, annof stop) in
             let vstop = Var (_stop, None, annof stop) in
             let vstep = Var (_step, None, annof step) in
             let vstep = Var (_step, None, annof step) in
             let cond = Cond (
             let cond = Cond (
-                Binop (Gt, vstep, IntConst (0, []), []),
+                Binop (Gt, vstep, Const (IntVal 0, []), []),
                 Binop (Lt, vi, vstop, []),
                 Binop (Lt, vi, vstop, []),
                 Binop (Gt, vi, vstop, []),
                 Binop (Gt, vi, vstop, []),
                 []
                 []
@@ -161,7 +160,7 @@ let rec array_init = function
             | dim :: rest ->
             | dim :: rest ->
                 let counter = fresh_var "i" in
                 let counter = fresh_var "i" in
                 let body = Block [add_loop (indices @ [Var (counter, None, [])]) rest] in
                 let body = Block [add_loop (indices @ [Var (counter, None, [])]) rest] in
-                For (counter, IntConst (0, []), dim, IntConst (1, []), body, [])
+                For (counter, Const (IntVal 0, []), dim, Const (IntVal 1, []), body, [])
         in
         in
         add_loop [] dims
         add_loop [] dims
 
 
@@ -179,7 +178,7 @@ let rec array_init = function
             | ArrayConst (values, _) ->
             | ArrayConst (values, _) ->
                 make_assigns (depth + 1) 0 indices values
                 make_assigns (depth + 1) 0 indices values
             | value when depth = ndims ->
             | value when depth = ndims ->
-                let indices = List.map (fun i -> IntConst (i, [])) indices in
+                let indices = List.map (fun i -> Const (IntVal i, [])) indices in
                 [Assign (name, Some (List.rev indices), value, ann)]
                 [Assign (name, Some (List.rev indices), value, ann)]
             | node ->
             | node ->
                 let msg = sprintf
                 let msg = sprintf
@@ -253,6 +252,6 @@ let rec array_dims = function
 let rec phase input =
 let rec phase input =
     log_line 2 "- Desugaring";
     log_line 2 "- Desugaring";
     match input with
     match input with
-    | Types node ->
-            Types (for_to_while (array_init (var_init (array_dims node))))
+    | Ast node ->
+            Ast (for_to_while (array_init (var_init (array_dims node))))
     | _ -> raise (InvalidInput "desugar")
     | _ -> raise (InvalidInput "desugar")

+ 1 - 1
phases/dim_reduce.ml

@@ -50,5 +50,5 @@ let rec simplify_decs = function
 let rec phase input =
 let rec phase input =
     log_line 2 "- Array dimension reduction";
     log_line 2 "- Array dimension reduction";
     match input with
     match input with
-    | Types node -> Types (simplify_decs (dim_reduce 0 node))
+    | Ast node -> Ast (simplify_decs (dim_reduce 0 node))
     | _ -> raise (InvalidInput "dimension reduction")
     | _ -> raise (InvalidInput "dimension reduction")

+ 1 - 1
phases/expand_dims.ml

@@ -38,5 +38,5 @@ let rec expand_dims = function
 let rec phase input =
 let rec phase input =
     log_line 2 "- Expand array dimensions";
     log_line 2 "- Expand array dimensions";
     match input with
     match input with
-    | Types node -> Types (expand_dims node)
+    | Ast node -> Ast (expand_dims node)
     | _ -> raise (InvalidInput "expand dimensions")
     | _ -> raise (InvalidInput "expand dimensions")

+ 2 - 2
phases/extern_vars.ml

@@ -126,8 +126,8 @@ let rec replace_vars scope depth = function
 let rec phase input =
 let rec phase input =
     log_line 2 "- Create getters and setters for extern variables";
     log_line 2 "- Create getters and setters for extern variables";
     match input with
     match input with
-    | Types node ->
+    | Ast node ->
         let globals = Hashtbl.create 20 in
         let globals = Hashtbl.create 20 in
         let node = create_funcs globals node in
         let node = create_funcs globals node in
-        Types (replace_vars globals 0 node)
+        Ast (replace_vars globals 0 node)
     | _ -> raise (InvalidInput "extern vars")
     | _ -> raise (InvalidInput "extern vars")

+ 1 - 1
phases/parse.ml

@@ -25,5 +25,5 @@ let phase input =
         let ast = parse_with_error lexbuf in
         let ast = parse_with_error lexbuf in
         (match ast with
         (match ast with
             | None -> raise (CompileError "no syntax tree was constructed")
             | None -> raise (CompileError "no syntax tree was constructed")
-            | Some node -> Types node)
+            | Some node -> Ast node)
     | _ -> raise (InvalidInput "parse")
     | _ -> raise (InvalidInput "parse")

+ 37 - 23
phases/print.ml

@@ -4,6 +4,8 @@ open Stringify
 
 
 let tab = "    "
 let tab = "    "
 
 
+let si = string_of_int
+
 let rec repeat s n = if n < 1 then "" else s ^ (repeat s (n - 1))
 let rec repeat s n = if n < 1 then "" else s ^ (repeat s (n - 1))
 let pad width s = s ^ (repeat " " (String.length s - width))
 let pad width s = s ^ (repeat " " (String.length s - width))
 let paddall width = List.map (pad width)
 let paddall width = List.map (pad width)
@@ -13,12 +15,12 @@ let type2str = function
     | Array (t, dims) -> ctype2str t ^ repeat "," (List.length dims - 1)
     | Array (t, dims) -> ctype2str t ^ repeat "," (List.length dims - 1)
     | t -> ctype2str t
     | t -> ctype2str t
 
 
-let prefix node = match typeof node with
+let prefix = function
     | Bool _  -> "b"
     | Bool _  -> "b"
     | Int _   -> "i"
     | Int _   -> "i"
     | Float _ -> "f"
     | Float _ -> "f"
-    | Array _ -> "a"
-    | _ -> raise InvalidNode
+    | Void  _ -> ""
+    | _       -> "a"
 
 
 let instr2str = function
 let instr2str = function
     (* Global / directives *)
     (* Global / directives *)
@@ -32,23 +34,39 @@ let instr2str = function
     | Import (name, ret_type, arg_types) ->
     | Import (name, ret_type, arg_types) ->
         let types = List.map type2str (ret_type :: arg_types) in
         let types = List.map type2str (ret_type :: arg_types) in
         ".import \"" ^ name ^ "\" " ^ (String.concat " " types)
         ".import \"" ^ name ^ "\" " ^ (String.concat " " types)
-    | Const node ->
-        ".const  " ^ (node2str node)
+    | ConstDef node ->
+        ".const  " ^ (const2str node)
     | Global ctype ->
     | Global ctype ->
         ".global " ^ (type2str ctype)
         ".global " ^ (type2str ctype)
 
 
+    (* Store *)
+    | StoreGlob (ctype, index) ->
+        tab ^ prefix ctype ^ "storeg " ^ si index
+    | StoreLoc (ctype, index) ->
+        tab ^ prefix ctype ^ "store  " ^ si index
+    | StoreRel (ctype, nesting, index) ->
+        tab ^ prefix ctype ^ "storen " ^ si nesting ^ " " ^ si index
+
     (* Load constant *)
     (* Load constant *)
     | LoadConst (ctype, index) ->
     | LoadConst (ctype, index) ->
-        tab ^ type2str ctype ^ "loadc " ^ string_of_int index
-    | LoadImm (BoolConst (b, _)) ->
+        tab ^ prefix ctype ^ "loadc " ^ si index
+    | LoadImm (Const (BoolVal b, _)) ->
         tab ^ "bloadc_" ^ (if b then "t" else "f")
         tab ^ "bloadc_" ^ (if b then "t" else "f")
-    | LoadImm (IntConst (i, _)) when i < 0 ->
-        tab ^ "iloadc_m" ^ string_of_int (-i)
-    | LoadImm (IntConst (i, _)) ->
-        tab ^ "iloadc_" ^ string_of_int i
-    | LoadImm (FloatConst (i, _)) ->
-        tab ^ "floadc_" ^ string_of_int (int_of_float i)
+    | LoadImm (Const (IntVal i, _)) when i < 0 ->
+        tab ^ "iloadc_m" ^ si (-i)
+    | LoadImm (Const (IntVal i, _)) ->
+        tab ^ "iloadc_" ^ si i
+    | LoadImm (Const (FloatVal i, _)) ->
+        tab ^ "floadc_" ^ si (int_of_float i)
+
+    (* Control flow *)
+    | RtnEnter stack_len ->
+        tab ^ "esr " ^ si stack_len
+    | Ret ctype ->
+        tab ^ prefix ctype ^ "return"
 
 
+    | EmptyLine -> ""
+    | DummyInstr -> tab ^ "<dummy>"
     | _ -> tab ^ "<unknown instruction>"
     | _ -> tab ^ "<unknown instruction>"
 
 
 let rec print_assembly oc instrs =
 let rec print_assembly oc instrs =
@@ -69,15 +87,14 @@ let rec print_assembly oc instrs =
             trav tl
             trav tl
     in
     in
     trav instrs;
     trav instrs;
-    List.iter output_line (List.rev !endbuf)
-    (*
-    let hasdot ins = if String.length ins > 0 && ins.[0] = '.' then 1 else 0 in
-    let cmp a b = compare (hasdot a) (hasdot b) in
-    List.sort cmp (trav instrs)
-    *)
+    if List.length !endbuf > 1 then (
+        output_line (instr2str (Comment ("globals:")));
+        let cmp a b = compare (String.sub a 0 8) (String.sub b 0 8) in
+        List.iter output_line (List.sort cmp (List.rev !endbuf))
+    ); ()
 
 
 let phase = function
 let phase = function
-    | Types node as input ->
+    | Ast node as input ->
         if args.verbose >= 2 then (
         if args.verbose >= 2 then (
             prerr_endline "--------------------------------------------------";
             prerr_endline "--------------------------------------------------";
             prerr_endline (node2str node);
             prerr_endline (node2str node);
@@ -105,9 +122,6 @@ let phase = function
                 prerr_endline "--------------------------------------------------";
                 prerr_endline "--------------------------------------------------";
 
 
             print_assembly stdout instrs;
             print_assembly stdout instrs;
-
-            if args.verbose >= 2 then
-                prerr_endline "--------------------------------------------------"
         );
         );
         input
         input
 
 

+ 4 - 4
phases/typecheck.ml

@@ -175,9 +175,9 @@ let rec typecheck node =
         DoWhile (check_trav Bool cond, typecheck body, ann)
         DoWhile (check_trav Bool cond, typecheck body, ann)
 
 
     (* Constants *)
     (* Constants *)
-    | BoolConst  (value, ann) -> BoolConst  (value, Type Bool  :: ann)
-    | IntConst   (value, ann) -> IntConst   (value, Type Int   :: ann)
-    | FloatConst (value, ann) -> FloatConst (value, Type Float :: ann)
+    | Const (BoolVal  value, ann) -> Const (BoolVal  value, Type Bool  :: ann)
+    | Const (IntVal   value, ann) -> Const (IntVal   value, Type Int   :: ann)
+    | Const (FloatVal value, ann) -> Const (FloatVal value, Type Float :: ann)
 
 
     (* Variables inherit the type of their declaration *)
     (* Variables inherit the type of their declaration *)
     | VarUse (dec, None, ann) ->
     | VarUse (dec, None, ann) ->
@@ -213,5 +213,5 @@ let rec typecheck node =
 let rec phase input =
 let rec phase input =
     log_line 2 "- Type checking";
     log_line 2 "- Type checking";
     match input with
     match input with
-    | Types node -> Types (typecheck node)
+    | Ast node -> Ast (typecheck node)
     | _ -> raise (InvalidInput "typecheck")
     | _ -> raise (InvalidInput "typecheck")

+ 23 - 11
stringify.ml

@@ -5,11 +5,16 @@ let tab = "    "
 (* string -> string *)
 (* string -> string *)
 let indent = Str.global_replace (Str.regexp "^\\(.\\)") (tab ^ "\\1")
 let indent = Str.global_replace (Str.regexp "^\\(.\\)") (tab ^ "\\1")
 
 
-(* Add a trailing zero to a float stringification
- * float -> string *)
-let float2string f = match string_of_float f with
-    | s when s.[String.length s - 1] = '.' -> s ^ "0"
-    | s -> s
+(* const -> string *)
+let const2str = function
+    | BoolVal  b -> string_of_bool b
+    | IntVal   i -> string_of_int i
+    | FloatVal f ->
+        (* Add a trailing zero to a float stringification *)
+        (match string_of_float f with
+        | s when s.[String.length s - 1] = '.' -> s ^ "0"
+        | s -> s
+        )
 
 
 (* Copied from util.ml to avoid circular dependency *)
 (* Copied from util.ml to avoid circular dependency *)
 let nameof = function
 let nameof = function
@@ -102,19 +107,24 @@ and node2str node =
         "do " ^ str body ^ " while (" ^ str cond ^ ");"
         "do " ^ str body ^ " while (" ^ str cond ^ ");"
     | For (counter, start, stop, step, body, _) ->
     | For (counter, start, stop, step, body, _) ->
         let step = match step with
         let step = match step with
-            | IntConst (1, _) -> ""
+            | Const (IntVal 1, _) -> ""
             | value -> ", " ^ str value
             | value -> ", " ^ str value
         in
         in
         let range = str start ^ ", " ^ str stop ^ step in
         let range = str start ^ ", " ^ str stop ^ step in
         "for (int " ^ counter ^ " = " ^ range ^ ") " ^ str body
         "for (int " ^ counter ^ " = " ^ range ^ ") " ^ str body
     | Allocate (name, dims, _, _) ->
     | Allocate (name, dims, _, _) ->
         name ^ " := <allocate>(" ^ concat ", " dims ^ ");"
         name ^ " := <allocate>(" ^ concat ", " dims ^ ");"
-    | Block body -> "{\n" ^ indent (concat "\n" body) ^ "\n}"
+    | Block body ->
+        let rec append = function
+            | [] -> ""
+            | [last] -> last
+            | "" :: tl -> append tl
+            | hd :: tl -> hd ^ "\n" ^ append tl
+        in
+        "{\n" ^ indent (append (List.map str body)) ^ "\n}"
 
 
     (* Expressions *)
     (* Expressions *)
-    | BoolConst (b, _) -> string_of_bool b
-    | IntConst (i, _) -> string_of_int i
-    | FloatConst (f, _) -> float2string f
+    | Const (c, _) -> const2str c
     | ArrayConst (dims, _) -> "[" ^ concat ", " dims ^ "]"
     | ArrayConst (dims, _) -> "[" ^ concat ", " dims ^ "]"
     | Var (v, None, _) -> v
     | Var (v, None, _) -> v
     | Var (name, Some dims, _) -> name ^ (str (ArrayConst (dims, [])))
     | Var (name, Some dims, _) -> name ^ (str (ArrayConst (dims, [])))
@@ -147,11 +157,13 @@ and node2str node =
     | FunUse (dec, args, _) ->
     | FunUse (dec, args, _) ->
         node2str (FunCall (nameof dec, args, []))
         node2str (FunCall (nameof dec, args, []))
     | Dim (name, _) -> name
     | Dim (name, _) -> name
-
     | ArrayScalar node
     | ArrayScalar node
     | ArrayInit (node, _)
     | ArrayInit (node, _)
     | Arg node -> str node
     | Arg node -> str node
 
 
+    | VarDecs nodes
+    | LocalFuns nodes -> concat "\n" nodes
+
     | DummyNode -> "<dummy>"
     | DummyNode -> "<dummy>"
 
 
 (* ctype list -> string *)
 (* ctype list -> string *)

+ 5 - 3
stringify.mli

@@ -1,7 +1,9 @@
-val op2str : Types.operator -> string
+val const2str : Types.const -> string
 
 
-val node2str : Types.node -> string
+val op2str    : Types.operator -> string
 
 
-val type2str : Types.ctype -> string
+val node2str  : Types.node -> string
+
+val type2str  : Types.ctype -> string
 
 
 val types2str : Types.ctype list -> string
 val types2str : Types.ctype list -> string

+ 1 - 2
test/old/array_dim.cvc

@@ -4,9 +4,8 @@ int dim() {
     dims = dims + 1;
     dims = dims + 1;
     return 10;
     return 10;
 }
 }
-/*
+
 void foo() {
 void foo() {
    int[10, dim()] arr;
    int[10, dim()] arr;
    arr[1, 0] = 1;
    arr[1, 0] = 1;
 }
 }
-*/

+ 28 - 17
types.ml

@@ -5,6 +5,7 @@ type operator = Neg | Not
               | Add | Sub | Mul | Div | Mod
               | Add | Sub | Mul | Div | Mod
               | Eq | Ne | Lt | Le | Gt | Ge
               | Eq | Ne | Lt | Le | Gt | Ge
               | And | Or
               | And | Or
+type const = BoolVal of bool | IntVal of int | FloatVal of float
 type ctype = Void | Bool | Int | Float
 type ctype = Void | Bool | Int | Float
            | Array of ctype * node list
            | Array of ctype * node list
            | ArrayDepth of ctype * int  (* TODO: remove? *)
            | ArrayDepth of ctype * int  (* TODO: remove? *)
@@ -12,6 +13,7 @@ type ctype = Void | Bool | Int | Float
 and annotation =
 and annotation =
     | Loc of location
     | Loc of location
     | Depth of int
     | Depth of int
+    | Index of int
     | Type of ctype
     | Type of ctype
 and ann = annotation list
 and ann = annotation list
 and node =
 and node =
@@ -31,6 +33,9 @@ and node =
     | Dim of string * ann
     | Dim of string * ann
       (* dimension name in array Param *)
       (* dimension name in array Param *)
 
 
+    | VarDecs of node list
+    | LocalFuns of node list
+
     (* Statements *)
     (* Statements *)
     | VarDec of ctype * string * node option * ann
     | VarDec of ctype * string * node option * ann
       (* type, name, initialisation? *)
       (* type, name, initialisation? *)
@@ -49,9 +54,7 @@ and node =
     | DoWhile of node * node * ann           (* cond, body *)
     | DoWhile of node * node * ann           (* cond, body *)
 
 
     (* Expressions *)
     (* Expressions *)
-    | BoolConst of bool * ann                  (* bool value *)
-    | IntConst of int * ann                    (* int value *)
-    | FloatConst of float * ann                (* float value *)
+    | Const of const * ann                     (* bool|int|float value *)
     | ArrayConst of node list * ann            (* [<exprs>] *)
     | ArrayConst of node list * ann            (* [<exprs>] *)
     | Var of string * node list option * ann   (* <name> [<indices>]? *)
     | Var of string * node list option * ann   (* <name> [<indices>]? *)
     | Monop of operator * node * ann           (* op, operand *)
     | Monop of operator * node * ann           (* op, operand *)
@@ -82,22 +85,30 @@ type instr =
     (* .import "<name>" <ret_type> [ <arg_type>; ... ] *)
     (* .import "<name>" <ret_type> [ <arg_type>; ... ] *)
     | Import of string * ctype * ctype list
     | Import of string * ctype * ctype list
     (* .const <value> *)
     (* .const <value> *)
-    | Const of node
+    | ConstDef of const
     (* .global <type> *)
     (* .global <type> *)
     | Global of ctype
     | Global of ctype
 
 
-    (* [ifb]loadg G *)
-    | LoadGlob of node
-    (* [ifb]loadc C *)
-    | LoadConst of ctype * int
-    (* [ifb]load_[01tf] <value> *)
-    | LoadImm of node
+    | StoreGlob of ctype * int          (* [ifba]storeg G *)
+    | StoreLoc of ctype * int           (* [ifba]store L *)
+    | StoreRel of ctype * int * int     (* [ifba]storen N L *)
+
+    | LoadGlob of node                  (* [ifb]loadg G *)
+    | LoadConst of ctype * int          (* [ifb]loadc C *)
+    | LoadImm of node                   (* [ifb]load_[01tf] <value> *)
+
+    (* Control flow *)
+    | RtnEnter of int
+    | RtnInit
+    | RtnJmp
+    | Ret of ctype
 
 
     (* Instructions *)
     (* Instructions *)
-    (* i(inc|dec) L C *)
-    | Inc of int * int
-    (* i(inc|dec)_1 C *)
-    | IncOne of int
+    | Inc of int * int                  (* i(inc|dec) L C *)
+    | IncOne of int                     (* i(inc|dec)_1 C *)
+
+    | EmptyLine
+    | DummyInstr
 
 
 (* Container for command-line arguments *)
 (* Container for command-line arguments *)
 type args_record = {
 type args_record = {
@@ -112,8 +123,8 @@ let verbosity_default = 2  (* TODO: set to 1 when done with debugging *)
 let verbosity_debug   = 3
 let verbosity_debug   = 3
 
 
 (* Commandline args are stored in a global struct
 (* Commandline args are stored in a global struct
- * (yes, it IS dirty, but I'd rather have this than having to pass [args] around
- * everywhere) *)
+ * (yes, it IS dirty, but I don't know how to do this without passin [args] to
+ * every function) *)
 let args = {
 let args = {
     infile  = None;
     infile  = None;
     outfile = None;
     outfile = None;
@@ -125,7 +136,7 @@ let args = {
 type intermediate =
 type intermediate =
     | Empty
     | Empty
     | FileContent of string * string
     | FileContent of string * string
-    | Types of node
+    | Ast of node
     | Assembly of instr list
     | Assembly of instr list
 
 
 (* exceptions *)
 (* exceptions *)

+ 151 - 66
util.ml

@@ -44,18 +44,18 @@ let loc_from_lexpos pstart pend =
 let rec flatten_blocks lst =
 let rec flatten_blocks lst =
     let flatten = flatten_blocks in
     let flatten = flatten_blocks in
     let trav = function
     let trav = function
-        | FunDef (export, ret_type, name, params, Block body, loc) ->
-            FunDef (export, ret_type, name, flatten params, Block (flatten body), loc)
-        | If (cond, Block body, loc) ->
-            If (cond, Block (flatten body), loc)
-        | IfElse (cond, Block tbody, Block fbody, loc) ->
-            IfElse (cond, Block (flatten tbody), Block (flatten fbody), loc)
-        | While (cond, Block body, loc) ->
-            While (cond, Block (flatten body), loc)
-        | DoWhile (cond, Block body, loc) ->
-            DoWhile (cond, Block (flatten body), loc)
-        | For (counter, start, stop, step, Block body, loc) ->
-            For (counter, start, stop, step, Block (flatten body), loc)
+        | FunDef (export, ret_type, name, params, Block body, ann) ->
+            FunDef (export, ret_type, name, flatten params, Block (flatten body), ann)
+        | If (cond, Block body, ann) ->
+            If (cond, Block (flatten body), ann)
+        | IfElse (cond, Block tbody, Block fbody, ann) ->
+            IfElse (cond, Block (flatten tbody), Block (flatten fbody), ann)
+        | While (cond, Block body, ann) ->
+            While (cond, Block (flatten body), ann)
+        | DoWhile (cond, Block body, ann) ->
+            DoWhile (cond, Block (flatten body), ann)
+        | For (counter, start, stop, step, Block body, ann) ->
+            For (counter, start, stop, step, Block (flatten body), ann)
         | node -> node
         | node -> node
     in
     in
     match lst with
     match lst with
@@ -69,56 +69,56 @@ let rec flatten_blocks lst =
 let transform_children trav node =
 let transform_children trav node =
     let trav_all nodes = List.map trav nodes in
     let trav_all nodes = List.map trav nodes in
     match node with
     match node with
-    | Program (decls, loc) ->
-        Program (flatten_blocks (trav_all decls), loc)
-    | FunDec (ret_type, name, params, loc) ->
-        FunDec (ret_type, name, trav_all params, loc)
-    | FunDef (export, ret_type, name, params, body, loc) ->
-        FunDef (export, ret_type, name, trav_all params, trav body, loc)
-    | GlobalDec (ctype, name, loc) ->
-        GlobalDec (ctype, name, loc)
-    | GlobalDef (export, ctype, name, Some init, loc) ->
-        GlobalDef (export, ctype, name, Some (trav init), loc)
-
-    | VarDec (ctype, name, Some init, loc) ->
-        VarDec (ctype, name, Some (trav init), loc)
-    | Assign (name, None, value, loc) ->
-        Assign (name, None, trav value, loc)
-    | Assign (name, Some dims, value, loc) ->
-        Assign (name, Some (trav_all dims), trav value, loc)
-    | VarLet (dec, None, value, loc) ->
-        VarLet (dec, None, trav value, loc)
-    | VarLet (dec, Some dims, value, loc) ->
-        VarLet (dec, Some (trav_all dims), trav value, loc)
-    | Return (value, loc) ->
-        Return (trav value, loc)
-    | If (cond, body, loc) ->
-        If (trav cond, trav body, loc)
-    | IfElse (cond, true_body, false_body, loc) ->
-        IfElse (trav cond, trav true_body, trav false_body, loc)
-    | While (cond, body, loc) ->
-        While (trav cond, trav body, loc)
-    | DoWhile (cond, body, loc) ->
-        DoWhile (trav cond, trav body, loc)
-    | For (counter, start, stop, step, body, loc) ->
-        For (counter, trav start, trav stop, trav step, trav body, loc)
-    | Allocate (name, dims, dec, loc) ->
-        Allocate (name, trav_all dims, dec, loc)
+    | Program (decls, ann) ->
+        Program (flatten_blocks (trav_all decls), ann)
+    | FunDec (ret_type, name, params, ann) ->
+        FunDec (ret_type, name, trav_all params, ann)
+    | FunDef (export, ret_type, name, params, body, ann) ->
+        FunDef (export, ret_type, name, trav_all params, trav body, ann)
+    | GlobalDec (ctype, name, ann) ->
+        GlobalDec (ctype, name, ann)
+    | GlobalDef (export, ctype, name, Some init, ann) ->
+        GlobalDef (export, ctype, name, Some (trav init), ann)
+
+    | VarDec (ctype, name, Some init, ann) ->
+        VarDec (ctype, name, Some (trav init), ann)
+    | Assign (name, None, value, ann) ->
+        Assign (name, None, trav value, ann)
+    | Assign (name, Some dims, value, ann) ->
+        Assign (name, Some (trav_all dims), trav value, ann)
+    | VarLet (dec, None, value, ann) ->
+        VarLet (dec, None, trav value, ann)
+    | VarLet (dec, Some dims, value, ann) ->
+        VarLet (dec, Some (trav_all dims), trav value, ann)
+    | Return (value, ann) ->
+        Return (trav value, ann)
+    | If (cond, body, ann) ->
+        If (trav cond, trav body, ann)
+    | IfElse (cond, true_body, false_body, ann) ->
+        IfElse (trav cond, trav true_body, trav false_body, ann)
+    | While (cond, body, ann) ->
+        While (trav cond, trav body, ann)
+    | DoWhile (cond, body, ann) ->
+        DoWhile (trav cond, trav body, ann)
+    | For (counter, start, stop, step, body, ann) ->
+        For (counter, trav start, trav stop, trav step, trav body, ann)
+    | Allocate (name, dims, dec, ann) ->
+        Allocate (name, trav_all dims, dec, ann)
     | Expr value ->
     | Expr value ->
         Expr (trav value)
         Expr (trav value)
     | Block (body) ->
     | Block (body) ->
         Block (trav_all body)
         Block (trav_all body)
 
 
-    | Monop (op, value, loc) ->
-        Monop (op, trav value, loc)
-    | Binop (op, left, right, loc) ->
-        Binop (op, trav left, trav right, loc)
-    | Cond (cond, true_expr, false_expr, loc) ->
-        Cond (trav cond, trav true_expr, trav false_expr, loc)
-    | TypeCast (ctype, value, loc) ->
-        TypeCast (ctype, trav value, loc)
-    | FunCall (name, args, loc) ->
-        FunCall (name, trav_all args, loc)
+    | Monop (op, value, ann) ->
+        Monop (op, trav value, ann)
+    | Binop (op, left, right, ann) ->
+        Binop (op, trav left, trav right, ann)
+    | Cond (cond, true_expr, false_expr, ann) ->
+        Cond (trav cond, trav true_expr, trav false_expr, ann)
+    | TypeCast (ctype, value, ann) ->
+        TypeCast (ctype, trav value, ann)
+    | FunCall (name, args, ann) ->
+        FunCall (name, trav_all args, ann)
     | Arg value ->
     | Arg value ->
         Arg (trav value)
         Arg (trav value)
 
 
@@ -133,9 +133,78 @@ let transform_children trav node =
     | FunUse (dec, params, ann) ->
     | FunUse (dec, params, ann) ->
         FunUse (dec, trav_all params, ann)
         FunUse (dec, trav_all params, ann)
 
 
+    | VarDecs decs ->
+        VarDecs (trav_all decs)
+    | LocalFuns funs ->
+        LocalFuns (trav_all funs)
+
     | _ -> node
     | _ -> node
 
 
- let rec annof = function
+let annotate a = function
+    | Program (decls, ann) ->
+        Program (decls, a :: ann)
+    | FunDec (ret_type, name, params, ann) ->
+        FunDec (ret_type, name, params, a :: ann)
+    | FunDef (export, ret_type, name, params, body, ann) ->
+        FunDef (export, ret_type, name, params, body, a :: ann)
+    | GlobalDec (ctype, name, ann) ->
+        GlobalDec (ctype, name, a :: ann)
+    | GlobalDef (export, ctype, name, init, ann) ->
+        GlobalDef (export, ctype, name, init, a :: ann)
+    | VarDec (ctype, name, init, ann) ->
+        VarDec (ctype, name, init, a :: ann)
+    | Assign (name, dims, value, ann) ->
+        Assign (name, dims, value, a :: ann)
+    | VarLet (dec, dims, value, ann) ->
+        VarLet (dec, dims, value, a :: ann)
+    | Return (value, ann) ->
+        Return (value, a :: ann)
+    | If (cond, body, ann) ->
+        If (cond, body, a :: ann)
+    | IfElse (cond, true_body, false_body, ann) ->
+        IfElse (cond, true_body, false_body, a :: ann)
+    | While (cond, body, ann) ->
+        While (cond, body, a :: ann)
+    | DoWhile (cond, body, ann) ->
+        DoWhile (cond, body, a :: ann)
+    | For (counter, start, stop, step, body, ann) ->
+        For (counter, start, stop, step, body, a :: ann)
+    | Allocate (name, dims, dec, ann) ->
+        Allocate (name, dims, dec, a :: ann)
+    | Monop (op, value, ann) ->
+        Monop (op, value, a :: ann)
+    | Binop (op, left, right, ann) ->
+        Binop (op, left, right, a :: ann)
+    | Cond (cond, true_expr, false_expr, ann) ->
+        Cond (cond, true_expr, false_expr, a :: ann)
+    | TypeCast (ctype, value, ann) ->
+        TypeCast (ctype, value, a :: ann)
+    | FunCall (name, args, ann) ->
+        FunCall (name, args, a :: ann)
+    | Arg value ->
+        Arg (value)
+    | Var (dec, dims, ann) ->
+        Var (dec, dims, a :: ann)
+    | VarUse (dec, dims, ann) ->
+        VarUse (dec, dims, a :: ann)
+    | FunUse (dec, params, ann) ->
+        FunUse (dec, params, a :: ann)
+    | Const (BoolVal value, ann) ->
+        Const (BoolVal value, a :: ann)
+    | Const (IntVal value, ann) ->
+        Const (IntVal value, a :: ann)
+    | Const (FloatVal value, ann) ->
+        Const (FloatVal value, a :: ann)
+    | ArrayConst (value, ann) ->
+        ArrayConst (value, a :: ann)
+    | Param (ctype, name, ann) ->
+        Param (ctype, name, a :: ann)
+    | Dim (name, ann) ->
+        Dim (name, a :: ann)
+
+    | _ -> raise InvalidNode
+
+let rec annof = function
     | Program (_, ann)
     | Program (_, ann)
     | Param (_, _, ann)
     | Param (_, _, ann)
     | Dim (_, ann)
     | Dim (_, ann)
@@ -153,9 +222,9 @@ let transform_children trav node =
     | DoWhile (_, _, ann)
     | DoWhile (_, _, ann)
     | For (_, _, _, _, _, ann)
     | For (_, _, _, _, _, ann)
     | Allocate (_, _, _, ann)
     | Allocate (_, _, _, ann)
-    | BoolConst (_, ann)
-    | IntConst (_, ann)
-    | FloatConst (_, ann)
+    | Const (BoolVal _, ann)
+    | Const (IntVal _, ann)
+    | Const (FloatVal _, ann)
     | ArrayConst (_, ann)
     | ArrayConst (_, ann)
     | Var (_, _, ann)
     | Var (_, _, ann)
     | Monop (_, _, ann)
     | Monop (_, _, ann)
@@ -173,20 +242,33 @@ let transform_children trav node =
 
 
     | _ -> raise InvalidNode
     | _ -> raise InvalidNode
 
 
- let locof node =
+let locof node =
      let rec trav = function
      let rec trav = function
          | []            -> noloc
          | []            -> noloc
          | Loc loc :: tl -> loc
          | Loc loc :: tl -> loc
          | _ :: tl       -> trav tl
          | _ :: tl       -> trav tl
      in trav (annof node)
      in trav (annof node)
 
 
- let rec depthof node =
+let rec depthof node =
      let rec trav = function
      let rec trav = function
-         | []                -> raise InvalidNode
+         | [] ->
+            prerr_string "cannot get depth for: ";
+            prt_node node;
+            raise InvalidNode
          | Depth depth :: tl -> depth
          | Depth depth :: tl -> depth
          | _ :: tl           -> trav tl
          | _ :: tl           -> trav tl
      in trav (annof node)
      in trav (annof node)
 
 
+let rec indexof node =
+     let rec trav = function
+         | [] ->
+            prerr_string "cannot get index for: ";
+            prt_node node;
+            raise InvalidNode
+         | Index index :: tl -> index
+         | _ :: tl           -> trav tl
+     in trav (annof node)
+
 let typeof = function
 let typeof = function
     (* Some nodes have their type as property *)
     (* Some nodes have their type as property *)
     | VarDec (ctype, _, _, _)
     | VarDec (ctype, _, _, _)
@@ -201,7 +283,10 @@ let typeof = function
     (* Other nodes must be annotated during typechecking *)
     (* Other nodes must be annotated during typechecking *)
     | node ->
     | node ->
         let rec trav = function
         let rec trav = function
-            | []           -> prerr_string "cannot get type for: "; prt_node node; raise InvalidNode
+         | [] ->
+            prerr_string "cannot get type for: ";
+            prt_node node;
+            raise InvalidNode
             | Type t :: tl -> t
             | Type t :: tl -> t
             | _ :: tl      -> trav tl
             | _ :: tl      -> trav tl
         in trav (annof node)
         in trav (annof node)
@@ -210,7 +295,7 @@ let prerr_loc (fname, ystart, yend, xstart, xend) =
     let file = open_in fname in
     let file = open_in fname in
 
 
     (* skip lines until the first matched line *)
     (* skip lines until the first matched line *)
-    for i = 1 to ystart - 1 do input_line file done;
+    for i = 1 to ystart - 1 do let _ = input_line file in () done;
 
 
     (* for each line in `loc`, print the source line with an underline *)
     (* for each line in `loc`, print the source line with an underline *)
     for l = ystart to yend do
     for l = ystart to yend do

+ 4 - 0
util.mli

@@ -18,12 +18,16 @@ val loc_from_lexpos : Lexing.position -> Lexing.position -> Types.location
 (* Default transformation traversal for AST nodes *)
 (* Default transformation traversal for AST nodes *)
 val transform_children : (Types.node -> Types.node) -> Types.node -> Types.node
 val transform_children : (Types.node -> Types.node) -> Types.node -> Types.node
 
 
+(* Add a single annotation to a node (no traversal) *)
+val annotate : Types.annotation -> Types.node -> Types.node
+
 (*val visit_children : (Types.node -> unit) -> Types.node -> unit*)
 (*val visit_children : (Types.node -> unit) -> Types.node -> unit*)
 
 
 (* Extract annotation from node *)
 (* Extract annotation from node *)
 val annof   : Types.node -> Types.annotation list
 val annof   : Types.node -> Types.annotation list
 val locof   : Types.node -> Types.location
 val locof   : Types.node -> Types.location
 val depthof : Types.node -> int
 val depthof : Types.node -> int
+val indexof : Types.node -> int
 val typeof  : Types.node -> Types.ctype
 val typeof  : Types.node -> Types.ctype
 
 
 (* Print file location to stderr *)
 (* Print file location to stderr *)