소스 검색

Did a lot of stuff:

- Made positions work in lexer, parser, error messages, and AST.
- Started on context analysis.
- General fixes and code improvements.
Taddeus Kroes 12 년 전
부모
커밋
4f112ab59c
14개의 변경된 파일196개의 추가작업 그리고 132개의 파일을 삭제
  1. 2 1
      Makefile
  2. 10 7
      ast.ml
  3. 8 5
      lexer.mll
  4. 11 1
      main.ml
  5. 18 10
      parser.cpp.mly
  6. 58 0
      phases/context_analysis.ml
  7. 12 12
      phases/desug.ml
  8. 3 3
      phases/parse.ml
  9. 4 5
      phases/print.ml
  10. 41 74
      stringify.ml
  11. 4 0
      test/context.cvc
  12. 3 0
      test/scope.cvc
  13. 19 13
      util.ml
  14. 3 1
      util.mli

+ 2 - 1
Makefile

@@ -1,9 +1,10 @@
 RESULT := civicc
 SOURCES := ast.ml lexer.mll parser.mly util.mli util.ml stringify.mli \
 	stringify.ml \
-	phases/parse.ml  phases/print.ml phases/desug.ml \
+	phases/parse.ml phases/print.ml phases/desug.ml phases/context_analysis.ml \
 	main.ml
 PRE_TARGETS := ast.cmi
+LIBS := str
 
 OCAMLYACC := menhir
 YFLAGS := --infer

+ 10 - 7
ast.ml

@@ -13,7 +13,7 @@ and node =
     | Program of node list * loc
     | Param of ctype * string * loc
     | FunDec of ctype * string * node list * loc
-    | FunDef of bool * ctype * string * node list * node list * loc
+    | FunDef of bool * ctype * string * node list * node * loc
     | GlobalDec of ctype * string * loc
     | GlobalDef of bool * ctype * string * node option * loc
 
@@ -21,14 +21,14 @@ and node =
     | VarDec of ctype * string * node option * loc
     | Assign of string * node * loc
     | Return of node * loc
-    | If of node * node list * loc
-    | IfElse of node * node list * node list * loc
-    | While of node * node list * loc
-    | DoWhile of node * node list * loc
-    | For of string * node * node * node * node list * loc
+    | If of node * node * loc
+    | IfElse of node * node * node * loc
+    | While of node * node * loc
+    | DoWhile of node * node * loc
+    | For of string * node * node * node * node * loc
     | Allocate of string * node list * loc
     | Expr of node
-    | Statements of node list * loc
+    | Block of node list
 
     (* expressions *)
     | BoolConst of bool * loc
@@ -37,6 +37,7 @@ and node =
     | ArrayConst of node list * loc
     | ArrayScalar of node * loc
     | Var of string * loc
+    | VarUse of node * node ref * int
     | Deref of string * node list * loc
     | Monop of monop * node * loc
     | Binop of binop * node * node * loc
@@ -54,6 +55,8 @@ exception LocError of string * loc
 
 exception CompileError of string
 
+exception InvalidNode
+
 
 (*
  * Template for node matching follows below.

+ 8 - 5
lexer.mll

@@ -10,9 +10,6 @@ let next_line lexbuf =
         pos with pos_bol = lexbuf.lex_curr_pos;
                  pos_lnum = pos.pos_lnum + 1
     }
-
-let linenum = ref 0
-let filename = ref ""
 }
 
 rule token = parse
@@ -28,8 +25,14 @@ rule token = parse
          * the file name can be zero or more flags, these flags are 1, 2, 3, 4.
          * These flags can be ignored.
          *)
-        Scanf.sscanf marker "# %d \"%s\"" (fun i s -> linenum := i - 1;
-                                                      filename := String.copy s);
+        let scan line filename =
+            let pos = lexbuf.lex_curr_p in
+            lexbuf.lex_curr_p <- {
+                pos with pos_fname = filename;
+                         pos_lnum = line - 1
+            }
+        in
+        Scanf.sscanf marker "# %d \"%s\"" scan;
         token lexbuf
     }
 

+ 11 - 1
main.ml

@@ -1,3 +1,4 @@
+open Printf
 open Ast
 
 (* Compile infile to assembly code
@@ -12,6 +13,8 @@ let compile infile verbose =
         Print.phase;
         Desug.phase;
         Print.phase;
+        Context_analysis.phase;
+        Print.phase;
         (*Typecheck.phase;*)
         (*Extern_vars.phase;*)
         (*Dim_reduce.phase;*)
@@ -35,8 +38,15 @@ let main () =
         Arg.parse args (fun s -> filename := Some s) usage;
         let _ = compile !filename !verbose in
         0
-    with CompileError msg ->
+    with
+    | CompileError msg ->
         prerr_endline ("Error: " ^ msg);
         -1
+    | LocError (msg, loc) ->
+        let (file, ystart, yend, xstart, xend) = loc in
+        let yend = if yend = ystart then "" else "-" ^ string_of_int yend in
+        let xend = if xend = xstart then "" else "-" ^ string_of_int xend in
+        eprintf "Error: %s at %s:%d%s:%d%s" msg file ystart yend xstart xend;
+        -1
 
 let _ = exit (main ())

+ 18 - 10
parser.cpp.mly

@@ -1,6 +1,14 @@
-#define LOC ("", 0, 0, 0, 0)
+#define LOC (let pstart = $startpos in \
+             let pend = $endpos in ( \
+                pstart.pos_fname, \
+                pstart.pos_lnum, \
+                pend.pos_lnum, \
+                (pstart.pos_cnum - pstart.pos_bol + 1), \
+                (pend.pos_cnum - pend.pos_bol) \
+            ))
 
 %{
+open Lexing
 open Ast
 %}
 
@@ -50,7 +58,7 @@ program : decl*; EOF
 decl : EXTERN; fun_header; SEMICOL
        { let (t, n, p) = $2 in FunDec(t, n, p, LOC) }
      | boption(EXPORT); fun_header; LBRACE; fun_body; RBRACE
-       { let (t, n, p) = $2 in FunDef ($1, t, n, p, $4, LOC) }
+       { let (t, n, p) = $2 in FunDef ($1, t, n, p, Block $4, LOC) }
 
      | EXTERN; basic_type; ID; SEMICOL
        { GlobalDec ($2, $3, LOC) }
@@ -77,10 +85,10 @@ fun_header : ret=basic_type; name=ID; LPAREN; params=separated_list(COMMA, param
 param : basic_type; ID  { Param ($1, $2, LOC) }
 
 fun_body : var_dec* local_fun_dec* statement* loption(return_statement)
-           { $1 @ $2 @ $3 }
+           { $1 @ $2 @ $3 @ $4 }
 
 local_fun_dec : fun_header; LBRACE; fun_body; RBRACE
-                { let (t, n, p) = $1 in FunDef (false, t, n, p, $3, LOC) }
+                { let (t, n, p) = $1 in FunDef (false, t, n, p, Block $3, LOC) }
 
 var_dec : basic_type; ID; SEMICOL
           { VarDec ($1, $2, None, LOC) }
@@ -96,18 +104,18 @@ statement : ID; ASSIGN; expr; SEMICOL
           | name=ID; LPAREN; params=separated_list(COMMA, expr); RPAREN; SEMICOL
             { Expr (FunCall (name, params, LOC)) }
           | IF; LPAREN; expr; RPAREN; block
-            { If ($3, $5, LOC) }                                 %prec IF
+            { If ($3, Block $5, LOC) }                      %prec IF
           | IF; LPAREN; expr; RPAREN; block; ELSE; block
-            { IfElse ($3, $5, $7, LOC) }                         %prec ELSE
+            { IfElse ($3, Block $5, Block $7, LOC) }        %prec ELSE
           | WHILE; LPAREN; expr; RPAREN; block
-            { While ($3, $5, LOC) }
+            { While ($3, Block $5, LOC) }
           | DO; block; WHILE; LPAREN; expr; RPAREN; SEMICOL
-            { DoWhile ($5, $2, LOC) }
+            { DoWhile ($5, Block $2, LOC) }
           | FOR; LPAREN; INT; id=ID; ASSIGN; start=expr; COMMA; stop=expr; RPAREN; body=block
-            { For (id, start, stop, IntConst (1, noloc), body, LOC) }
+            { For (id, start, stop, IntConst (1, noloc), Block body, LOC) }
           | FOR; LPAREN; INT; id=ID; ASSIGN; start=expr; COMMA; stop=expr;
                 COMMA; step=expr; RPAREN; body=block
-            { For (id, start, stop, step, body, LOC) }
+            { For (id, start, stop, step, Block body, LOC) }
 
 return_statement : RETURN; expr; SEMICOL  { [Return ($2, LOC)] }
 

+ 58 - 0
phases/context_analysis.ml

@@ -0,0 +1,58 @@
+open Printf
+open Ast
+open Util
+
+module StrMap = Map.Make (String)
+
+let analyse_context node =
+    let scope = ref StrMap.empty in
+    let add_to_scope name decl depth desc =
+        if StrMap.mem name !scope then
+            raise (LocError (sprintf "cannot redeclare %s \"%s\"" desc name, (locof node)))
+        else
+            scope := StrMap.add name (decl, depth) !scope
+    in
+    let rec analyse depth = function
+        (* add node reference for this varname to vars map *)
+        | VarDec (ctype, name, init, loc) as node ->
+            let node = match init with
+                | Some value ->
+                    let value = analyse depth value in
+                    VarDec (ctype, name, Some value, loc)
+                | None -> node
+            in
+            add_to_scope name (ref node) depth "variable";
+            node
+
+        (* for a variable, look for its declaration in the current scope and
+         * save a reference with the relative nesting depth *)
+        | Var (name, loc) as node ->
+            if StrMap.mem name !scope then
+                let (decl, decl_depth) = StrMap.find name !scope in
+                VarUse (node, decl, depth - decl_depth)
+            else
+                raise (LocError (sprintf "undefined variable \"%s\"" name, loc))
+
+        (*
+        (* increase nesting level when entering function *)
+        | FunDef (export, ret_type, name, params, body, loc) as node ->
+            let vars = StrMap.add name (ref node) vars in
+            let inctrav vars = function
+                | [] -> []
+                | h :: t -> analyse vars h :: (inctrav vars
+            in
+            let body = inc_trav body
+            let body = List.map (analyse vars) body in
+            FunDef (export, ret_type, name, params, body, loc) as node ->
+        *)
+
+        | node -> transform_children (analyse depth) node
+    in
+    analyse 0 node
+
+let rec phase repr =
+    let _ = prerr_endline "- Context analysis" in
+    match repr with
+    | Node (node, verbose) ->
+        Node (analyse_context node, verbose)
+    | _ -> raise (CompileError "invalid input for this phase")

+ 12 - 12
phases/desug.ml

@@ -3,12 +3,12 @@ open Util
 
 let rec flatten = function
     | [] -> []
-    | Statements (nodes, _) :: t -> (flatten nodes) @ (flatten t)
+    | Block nodes :: t -> (flatten nodes) @ (flatten t)
     | h :: t -> h :: (flatten t)
 
 let rec var_init = function
     (* Split local variable initialisations in declaration and assignment *)
-    | FunDef (export, ret_type, name, params, body, loc) ->
+    | FunDef (export, ret_type, name, params, Block body, loc) ->
         let move_inits body =
             let rec trav inits node = match node with
                 (* translate scalar array initialisation to ArrayScalar node,
@@ -39,12 +39,12 @@ let rec var_init = function
                 | rest -> inits @ (List.map var_init rest)
             in trav [] body
         in
-        FunDef (export, ret_type, name, params, move_inits body, loc)
+        FunDef (export, ret_type, name, params, Block (move_inits body), loc)
 
     (* Move global variable initialisations to exported __init function *)
     | GlobalDef (export, ctype, name, Some init, loc) ->
-        Statements ([GlobalDef (export, ctype, name, None, loc);
-                     Assign (name, init, locof init)], loc)
+        Block [GlobalDef (export, ctype, name, None, loc);
+               Assign (name, init, locof init)]
 
     (* Move global initialisations to __init function *)
     | Program (decls, loc) ->
@@ -60,11 +60,11 @@ let rec var_init = function
         (match assigns with
             | [] -> Program (decls, loc)
             | assigns ->
-                let init_func = FunDef (true, Void, "__init", [], assigns, noloc) in
+                let init_func = FunDef (true, Void, "__init", [], Block assigns, noloc) in
                 Program (init_func :: decls, loc)
             )
 
-    | node -> transform var_init node
+    | node -> transform_children var_init node
 
 (*
 let rec array_init = function
@@ -80,14 +80,14 @@ let rec array_init = function
         in
         add_loop [] dims
 
-    | Assign (name, ArrayConst (dims)) -> Statements []
+    | Assign (name, ArrayConst (dims)) -> Block []
 
     | node -> transform array_init node
 *)
 
 let rec phase repr =
-    let _ = print_endline "- Var init" in
+    let _ = print_endline "- Desugaring" in
     match repr with
-        | Node (node, verbose) ->
-            Node (var_init node, verbose)
-        | _ -> failwith "invalid input for this phase"
+    | Node (node, verbose) ->
+        Node (var_init node, verbose)
+    | _ -> raise (CompileError "invalid input for this phase")

+ 3 - 3
phases/parse.ml

@@ -24,7 +24,7 @@ let parse_with_error lexbuf =
         (*raise (LocError ("syntax error" (get_loc lexbuf)))*)
 
 let phase repr =
-    print_endline "- Parse input";
+    let _ = print_endline "- Parse input" in
     match repr with
     | Inputfile (filename, verbose) ->
         (* TODO: run preprocessor *)
@@ -41,6 +41,6 @@ let phase repr =
         let ast = parse_with_error lexbuf in
         close_in infile;
         (match ast with
-            | None -> failwith "error during parsing"
+            | None -> raise (CompileError "error during parsing")
             | Some ast -> Node (ast, verbose))
-    | _ -> failwith "invalid input for this phase"
+    | _ -> raise (CompileError "invalid input for this phase")

+ 4 - 5
phases/print.ml

@@ -3,11 +3,10 @@ open Stringify
 
 let phase repr =
     (* TODO: check verbosity *)
-    (*print_endline "- Print AST";*)
     match repr with
     | Node (node, verbose) ->
-        print_endline "-------------------------------------------------------";
-        print_endline (node2str node);
-        print_endline "-------------------------------------------------------";
+        prerr_endline "-------------------------------------------------------";
+        prerr_endline (node2str node);
+        prerr_endline "-------------------------------------------------------";
         repr
-    | _ -> failwith "invalid input for this phase"
+    | _ -> raise (CompileError "invalid input for this phase")

+ 41 - 74
stringify.ml

@@ -2,10 +2,8 @@ open Ast
 
 let tab = "    "
 
-(* int -> string list -> string list *)
-let indent (lines : string list) =
-    let prepend_tab line = tab ^ line in
-    List.map prepend_tab lines
+(* string -> string *)
+let indent = Str.global_replace (Str.regexp "^\\(.\\)") (tab ^ "\\1")
 
 (* monop -> string *)
 let monop2str = function
@@ -37,111 +35,80 @@ let rec type2str = function
     | ArrayDec (t, dims) -> (type2str t) ^ "[" ^ (String.concat ", " dims) ^ "]"
     | ArrayDef (t, dims) -> (type2str t) ^ "[" ^ (String.concat ", " (List.map node2str dims)) ^ "]"
 
-(* decl -> string list *)
-and node2lines node =
-    let all_str = List.map node2str in
-    let all_lines = List.map node2lines in
+(* node -> string *)
+and node2str node =
+    let str = node2str in
+    let all_str = List.map str in
+    let concat sep nodes = String.concat sep (all_str nodes) in
     match node with
-    (* Decls *)
+
+    (* Global *)
+    | Program (decls, _) ->
+        concat "\n\n" decls
+    | Param (param_type, name, _) ->
+        (type2str param_type) ^ " " ^ name
     | FunDec (ret_type, name, params, _) ->
-        let params = String.concat ", " (all_str params) in
-        ["extern " ^ type2str ret_type ^ " " ^ name ^ "(" ^ params ^ ");"]
+        let params = concat ", " params in
+        "extern " ^ type2str ret_type ^ " " ^ name ^ "(" ^ params ^ ");"
     | FunDef (export, ret_type, name, params, body, _) ->
         let export = if export then "export " else "" in
-        let params = String.concat ", " (all_str params) in
-        let header = type2str ret_type ^ " " ^ name ^ "(" ^ params ^ ")" in
-        let body = indent (List.concat (all_lines body)) in
-        [export ^ header ^ " {"] @
-            body @
-        ["}"]
+        let params = "(" ^ (concat "," params) ^ ")" in
+        export ^ type2str ret_type ^ " " ^ name ^ params ^ " " ^ str body
     | GlobalDec (var_type, name, _) ->
-        ["extern " ^ type2str var_type ^ " " ^ name ^ ";"]
+        "extern " ^ type2str var_type ^ " " ^ name ^ ";"
     | GlobalDef (export, ret_type, name, init, _) ->
         let export = if export then "export " else "" in
         let init = match init with
-            | Some value -> " = " ^ node2str value
+            | Some value -> " = " ^ str value
             | None -> ""
         in
-        [export ^ (type2str ret_type) ^ " " ^ name ^ init ^ ";"]
+        export ^ (type2str ret_type) ^ " " ^ name ^ init ^ ";"
 
     (* Statements *)
     | VarDec (var_type, name, None, _) ->
-        [(type2str var_type) ^ " " ^ name ^ ";"]
+        (type2str var_type) ^ " " ^ name ^ ";"
     | VarDec (var_type, name, Some init, _) ->
-        [(type2str var_type) ^ " " ^ name ^ " = " ^ (node2str init) ^ ";"]
+        (type2str var_type) ^ " " ^ name ^ " = " ^ (str init) ^ ";"
     | Assign (name, value, _) ->
-        [name ^ " = " ^ (node2str value) ^ ";"]
+        name ^ " = " ^ (str value) ^ ";"
     | Expr expr ->
-        [node2str expr ^ ";"]
+        str expr ^ ";"
     | Return (value, _) ->
-        ["return " ^ (node2str value) ^ ";"]
+        "return " ^ (str value) ^ ";"
     | If (cond, body, _) ->
-        let body = indent (List.concat (all_lines body)) in
-        ["if (" ^ node2str cond ^ ") {"] @
-            body @
-        ["}"]
+        "if (" ^ str cond ^ ") " ^ str body
     | IfElse (cond, true_body, false_body, _) ->
-        let true_body = indent (List.concat (all_lines true_body)) in
-        let false_body = indent (List.concat (all_lines false_body)) in
-        ["if (" ^ node2str cond ^ ") {"] @
-            true_body @
-        ["} else {"] @
-            false_body @
-        ["}"]
+        "if (" ^ str cond ^ ") " ^ str true_body ^ " else " ^ str false_body
     | While (cond, body, _) ->
-        let body = indent (List.concat (all_lines body)) in
-        ["while (" ^ node2str cond ^ ") {"] @
-            body @
-        ["}"]
+        "while (" ^ str cond ^ ") " ^ str body
     | DoWhile (cond, body, _) ->
-        let body = indent (List.concat (all_lines body)) in
-        ["do {"] @
-            body @
-        ["} while (" ^ node2str cond ^ ");"]
+        "do " ^ str body ^ " while (" ^ str cond ^ ");"
     | For (counter, start, stop, step, body, _) ->
         let step = match step with
             | IntConst (1, _) -> ""
-            | value -> ", " ^ node2str value
+            | value -> ", " ^ str value
         in
-        let range = node2str start ^ ", " ^ node2str stop ^ step in
-        let body = indent (List.concat (all_lines body)) in
-        ["for (int " ^ counter ^ " = " ^ range ^ ") {"] @
-            body @
-        ["}"]
+        let range = str start ^ ", " ^ str stop ^ step in
+        "for (int " ^ counter ^ " = " ^ range ^ ") " ^ str body
     | Allocate (name, dims, _) ->
-        [name ^ " = __allocate(" ^ String.concat ", " (List.map node2str dims) ^ ");"]
-
-    | Statements (stats, _) -> List.concat (List.map node2lines stats)
-
-    (* Catch-all, whould never happen *)
-    | _ -> failwith "invalid node"
-
-(* node -> string *)
-and node2str node =
-    let concat sep nodes = String.concat sep (List.map node2str nodes) in
-    match node with
-    (* Global *)
-    | Program (decls, _) ->
-        let decl2str decl = String.concat "\n" (node2lines decl) in
-        String.concat "\n\n" (List.map decl2str decls)
-    | Param (param_type, name, _) -> (type2str param_type) ^ " " ^ name
+        name ^ " = __allocate(" ^ concat ", " dims ^ ");"
+    | Block body -> "{\n" ^ indent (concat "\n" body) ^ "\n}"
 
     (* Expressions *)
     | BoolConst (b, _) -> string_of_bool b
     | IntConst (i, _) -> string_of_int i
     | FloatConst (f, _) -> string_of_float f
     | ArrayConst (dims, _) -> "[" ^ concat ", " dims ^ "]"
-    | ArrayScalar (value, _) -> node2str value
+    | ArrayScalar (value, _) -> str value
     | Var (v, _) -> v
-    | Deref (name, dims, _) -> name ^ (node2str (ArrayConst (dims, noloc)))
-    | Monop (op, opnd, _) -> monop2str op ^ node2str opnd
+    | VarUse (var, _, _) -> str var
+    | Deref (name, dims, _) -> name ^ (str (ArrayConst (dims, noloc)))
+    | Monop (op, opnd, _) -> monop2str op ^ str opnd
     | Binop (op, left, right, _) ->
-        "(" ^ node2str left ^ binop2str op ^ node2str right ^ ")"
+        "(" ^ str left ^ binop2str op ^ str right ^ ")"
     | Cond (cond, t, f, _) ->
-        (node2str cond) ^ " ? " ^ node2str t ^ " : " ^ node2str f
+        (str cond) ^ " ? " ^ str t ^ " : " ^ str f
     | TypeCast (ctype, value, _) ->
-        "(" ^ type2str ctype ^ ")" ^ node2str value
+        "(" ^ type2str ctype ^ ")" ^ str value
     | FunCall (name, args, _) ->
         name ^ "(" ^ (concat ", " args) ^ ")"
-
-    | node -> String.concat "\n" (node2lines node)

+ 4 - 0
test/context.cvc

@@ -0,0 +1,4 @@
+void foo() {
+    int a;
+    float a;
+}

+ 3 - 0
test/scope.cvc

@@ -0,0 +1,3 @@
+void foo() {
+    foo = bar;
+}

+ 19 - 13
util.ml

@@ -8,8 +8,7 @@ let fresh_var prefix =
 
 (* Default tree transformation
  * (node -> node) -> node -> node *)
-let rec transform visitor node =
-    let trav = visitor in
+let transform_children trav node =
     let trav_all nodes = List.map trav nodes in
     match node with
     | Program (decls, loc) ->
@@ -17,7 +16,7 @@ let rec transform visitor node =
     | 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_all 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) ->
@@ -30,15 +29,15 @@ let rec transform visitor node =
     | Return (value, loc) ->
         Return (trav value, loc)
     | If (cond, body, loc) ->
-        If (trav cond, trav_all body, loc)
+        If (trav cond, trav body, loc)
     | IfElse (cond, true_body, false_body, loc) ->
-        IfElse (trav cond, trav_all true_body, trav_all false_body, loc)
+        IfElse (trav cond, trav true_body, trav false_body, loc)
     | While (cond, body, loc) ->
-        While (trav cond, trav_all body, loc)
+        While (trav cond, trav body, loc)
     | DoWhile (cond, body, loc) ->
-        DoWhile (trav cond, trav_all body, loc)
+        DoWhile (trav cond, trav body, loc)
     | For (counter, start, stop, step, body, loc) ->
-        For (counter, trav start, trav stop, trav step, trav_all body, loc)
+        For (counter, trav start, trav stop, trav step, trav body, loc)
     | Expr value ->
         Expr (trav value)
 
@@ -53,8 +52,11 @@ let rec transform visitor node =
     | FunCall (name, args, loc) ->
         FunCall (name, trav_all args, loc)
 
-    | Statements (stats, loc) ->
-        Statements (trav_all stats, loc)
+    | Block (body) ->
+        Block (trav_all body)
+
+    | VarUse (var, def, depth) ->
+        VarUse (trav var, def, depth)
 
     | _ -> node
 
@@ -73,7 +75,6 @@ let rec transform visitor node =
     | While (_, _, loc)
     | DoWhile (_, _, loc)
     | For (_, _, _, _, _, loc)
-    | Statements (_, loc)
     | Allocate (_, _, loc)
     | BoolConst (_, loc)
     | IntConst (_, loc)
@@ -86,6 +87,11 @@ let rec transform visitor node =
     | Binop (_, _, _, loc)
     | Cond (_, _, _, loc)
     | TypeCast (_, _, loc)
-    | FunCall (_, _, loc) -> loc
+    | FunCall (_, _, loc)
+        -> loc
+
+    | Expr value
+    | VarUse (value, _, _)
+        -> locof value
 
-    | Expr value -> locof value
+    | Block _ -> noloc

+ 3 - 1
util.mli

@@ -2,7 +2,9 @@
 val fresh_var : string -> string
 
 (* Default transformation traversal for AST nodes *)
-val transform : (Ast.node -> Ast.node) -> Ast.node -> Ast.node
+val transform_children : (Ast.node -> Ast.node) -> Ast.node -> Ast.node
+
+(*val visit_children : (Ast.node -> unit) -> Ast.node -> unit*)
 
 (* Extract location from node *)
 val locof : Ast.node -> Ast.loc