index.ml 2.7 KB

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