index.ml 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. open Types
  2. open Util
  3. (* Tag declarations with stack frame indices *)
  4. let tag_index program =
  5. let nglobs = ref 0 in
  6. let nimport = ref 0 in
  7. let consts = Hashtbl.create 32 in
  8. let rec trav_localfuns trav = function
  9. | LocalFuns body -> LocalFuns (List.map trav body)
  10. | node -> traverse_unit (trav_localfuns trav) node
  11. in
  12. let rec tag stacklen callstack node =
  13. let trav = tag stacklen callstack in
  14. match node with
  15. | GlobalDef _ ->
  16. let index = !nglobs in
  17. nglobs := !nglobs + 1;
  18. annotate (Index index) (traverse_unit trav node)
  19. | FunDef (export, rtype, name, params, body, ann) ->
  20. (* label name for local function is "__<parent_label>_<name>" *)
  21. let callstack = name :: callstack in
  22. let prefix = if List.length callstack > 1 then "__" else "" in
  23. let label = prefix ^ String.concat "_" (List.rev callstack) in
  24. let stacklen = ref 0 in
  25. let trav = tag stacklen callstack in
  26. (* Traverse own function body first *)
  27. let params = List.map trav params in
  28. let body = trav body in
  29. let ann = Index (!stacklen - List.length params) :: ann in
  30. (* Traverse local functions after the function body *)
  31. let body = trav_localfuns trav body in
  32. FunDef (export, rtype, name, params, body, LabelName label :: ann)
  33. | LocalFuns _ -> node
  34. | VarDec _ | Param _ | Dim _ ->
  35. let index = !stacklen in
  36. stacklen := !stacklen + 1;
  37. annotate (Index index) (traverse_unit trav node)
  38. | FunDec (_, name, _, _) ->
  39. let index = !nimport in
  40. nimport := !nimport + 1;
  41. annotate (LabelName name) (annotate (Index index) node)
  42. | Const (value, _) when not (is_immediate_const value) ->
  43. let index =
  44. if Hashtbl.mem consts value then
  45. Hashtbl.find consts value
  46. else
  47. let index = Hashtbl.length consts in
  48. Hashtbl.add consts value index;
  49. index
  50. in
  51. annotate (Index index) node
  52. | _ -> traverse_unit trav node
  53. in tag (ref 0) [] program
  54. (* Undo context analysis *)
  55. let rec strip_context = function
  56. | VarUse (dec, dims, ann) ->
  57. Var (nameof dec, optmap strip_context dims, ann)
  58. | VarLet (dec, dims, value, ann) ->
  59. Assign (nameof dec, optmap strip_context dims, strip_context value, ann)
  60. | FunUse (dec, args, ann) ->
  61. FunCall (nameof dec, List.map strip_context args, ann)
  62. | node -> traverse_unit strip_context node
  63. let phase = function
  64. | Ast node ->
  65. let tagged = tag_index (strip_context node) in
  66. Ast (Context.analyse_context tagged)
  67. | _ -> raise (InvalidInput "index analysis")