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")