context_analysis.ml 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. open Printf
  2. open Ast
  3. open Util
  4. module StrMap = Map.Make (String)
  5. let analyse_context args node =
  6. let scope = ref StrMap.empty in
  7. let add_to_scope name decl depth desc =
  8. if StrMap.mem name !scope then (
  9. let msg = sprintf "Error: cannot redeclare %s \"%s\"" desc name in
  10. prerr_loc_msg (locof !decl) msg args.verbose;
  11. let (orig, _) = StrMap.find name !scope in
  12. prerr_loc_msg (locof !orig) "Previously declared here:" args.verbose;
  13. raise EmptyError
  14. ) else
  15. scope := StrMap.add name (decl, depth) !scope
  16. in
  17. let rec analyse depth node = match node with
  18. (* Add node reference for this varname to vars map *)
  19. | VarDec (ctype, name, init, loc) ->
  20. let node = match init with
  21. | Some value ->
  22. let value = analyse depth value in
  23. VarDec (ctype, name, Some value, loc)
  24. | None -> node
  25. in
  26. add_to_scope name (ref node) depth "variable";
  27. node
  28. (* For a variable, look for its declaration in the current scope and
  29. * save a reference with the relative nesting depth *)
  30. | Var (name, _) ->
  31. if StrMap.mem name !scope then
  32. let (decl, decl_depth) = StrMap.find name !scope in
  33. VarUse (node, decl, depth - decl_depth)
  34. else
  35. raise (NodeError (node, (sprintf "undefined variable \"%s\"" name)))
  36. (* Increase nesting level when entering function *)
  37. | FunDef (export, ret_type, name, params, body, loc) ->
  38. add_to_scope name (ref node) depth "function";
  39. let params = List.map (analyse (depth + 1)) params in
  40. let body = analyse (depth + 1) body in
  41. FunDef (export, ret_type, name, params, body, loc)
  42. | Param (ArrayDec (_, dims) as atype, name, _) as node ->
  43. let add dim = add_to_scope dim (ref (Type atype)) depth "variable" in
  44. List.iter add dims;
  45. add_to_scope name (ref node) depth "variable";
  46. node
  47. | Param (_, name, _) ->
  48. add_to_scope name (ref node) depth "variable";
  49. node
  50. | node -> transform_children (analyse depth) node
  51. in
  52. analyse 0 node
  53. let rec phase input =
  54. prerr_endline "- Context analysis";
  55. match input with
  56. | Ast (node, args) ->
  57. Ast (analyse_context args node, args)
  58. | _ -> raise (InvalidInput "context analysis")