You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
4.3 KiB

4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
  1. module M = import "data/map.ml"
  2. module S = import "data/set.ml"
  3. open import "prelude.ml"
  4. open import "./lang.ml"
  5. open import "./lib/monads.ml"
  6. type addr =
  7. | Combinator of string
  8. | Arg of int
  9. | Int of int
  10. type gm_code =
  11. | Push of addr
  12. | Update of int
  13. | Pop of int
  14. | Unwind
  15. | Mkap
  16. | Add | Sub | Mul | Div | Eval
  17. | Iszero of list gm_code * list gm_code
  18. instance show gm_code begin
  19. let show = function
  20. | Mkap -> "Mkap"
  21. | Unwind -> "Unwind"
  22. | Push (Combinator k) -> "Push " ^ k
  23. | Push (Arg i) -> "Arg " ^ show i
  24. | Push (Int i) -> "Int " ^ show i
  25. | Update n -> "Update " ^ show n
  26. | Pop n -> "Pop " ^ show n
  27. | Add -> "Add"
  28. | Mul -> "Mul"
  29. | Sub -> "Sub"
  30. | Div -> "Div"
  31. | Eval -> "Eval"
  32. | Iszero p -> "Iszero " ^ show p
  33. end
  34. type program_item =
  35. | Sc of string * int * list gm_code
  36. | Fd of fdecl
  37. let rec lambda_lift = function
  38. | Ref v -> pure (Ref v)
  39. | Lit v -> pure (Lit v)
  40. | App (f, x) -> (| app (lambda_lift f) (lambda_lift x) |)
  41. | Lam (v, x) ->
  42. let! body = lambda_lift x
  43. let! (i, defs, known_sc) = get
  44. let vars =
  45. x |> free_vars
  46. |> S.delete v
  47. |> flip S.difference known_sc
  48. |> S.members
  49. let def = ("Lam" ^ show i, vars ++ [v], body)
  50. let app = foldl (fun f -> app f # Ref) (Ref ("Lam" ^ show i)) vars
  51. put (i + 1, Decl def :: defs, known_sc)
  52. |> map (const app)
  53. | Case (sc, alts) ->
  54. alts
  55. |> map (fun (_, x) -> x)
  56. |> foldl app sc
  57. |> lambda_lift
  58. let rec eta_contract = function
  59. | Decl (n, a, e) as dec ->
  60. match a, e with
  61. | [], _ -> dec
  62. | xs, App (f, Ref v) ->
  63. if v == last xs && not (S.member v (free_vars f)) then
  64. eta_contract (Decl (n, init a, f))
  65. else
  66. dec
  67. | _, _ -> dec
  68. | Data c -> Data c
  69. | Foreign i -> Foreign i
  70. let rec lambda_lift_sc = function
  71. | Decl (n, a, e) ->
  72. match e with
  73. | Lam (v, e) -> lambda_lift_sc (Decl (n, a ++ [v], e))
  74. | _ ->
  75. let! e = lambda_lift e
  76. let! _ = modify (fun (a, b, s) -> (a, b, S.insert n s))
  77. pure (Decl (n, a, e))
  78. | Data c -> Data c |> pure
  79. | Foreign i -> Foreign i |> pure
  80. type dlist 'a <- list 'a -> list 'a
  81. let cg_prim (Fimport { var, fent }) =
  82. let prim_math_op x =
  83. [ Push (Arg 0), Eval, Push (Arg 2), Eval, x, Update 2, Pop 2, Unwind ]
  84. let prim_equality =
  85. [ Push (Arg 0), Eval (* x, arg0, arg1, arg2, arg3 *)
  86. , Push (Arg 2), Eval (* y, x, arg0, arg1, arg2, arg3 *)
  87. , Sub (* y - x, arg0, arg1, arg2, arg3 *)
  88. , Iszero ([ Push (Arg 3) ], [ Push (Arg 4) ])
  89. , Push (Int 0), Mkap, Update 4, Pop 4, Unwind ]
  90. match fent with
  91. | "add" -> Sc (var, 2, prim_math_op Add)
  92. | "sub" -> Sc (var, 2, prim_math_op Sub)
  93. | "mul" -> Sc (var, 2, prim_math_op Mul)
  94. | "div" -> Sc (var, 2, prim_math_op Div)
  95. | "equ" -> Sc (var, 4, prim_equality)
  96. | e -> error @@ "No such primitive " ^ e
  97. let rec compile (env : M.t string int) = function
  98. | Ref v ->
  99. match M.lookup v env with
  100. | Some i -> (Push (Arg i) ::)
  101. | None -> (Push (Combinator v) ::)
  102. | App (f, x) ->
  103. let f = compile env f
  104. let x = compile (map (1 +) env) x
  105. f # x # (Mkap ::)
  106. | Lam _ ->
  107. error "Can not compile lambda expression, did you forget to lift?"
  108. | Case _ ->
  109. error "Can not compile case expression, did you forget to lift?"
  110. | Lit i -> (Push (Int i) ::)
  111. let supercomb (_, args, exp) =
  112. let env = M.from_list (zip args [0..length args])
  113. let k = compile (M.from_list (zip args [0..length args])) exp
  114. k [Update (length env), Pop (length env), Unwind]
  115. let known_scs = S.from_list [ "getchar", "putchar" ]
  116. let program decs =
  117. let (decs, (_, lams, _)) =
  118. run_state (traverse (lambda_lift_sc # eta_contract) decs) (0, [], known_scs)
  119. let define nm =
  120. let! x = get
  121. if nm `S.member` x then
  122. error @@ "Redefinition of value " ^ nm
  123. else
  124. modify (S.insert nm)
  125. let go =
  126. flip traverse (lams ++ decs) @@ function
  127. | Decl ((nm, args, _) as sc) ->
  128. let! _ = define nm
  129. let code = supercomb sc
  130. Sc (nm, length args, code) |> pure
  131. | Data _ -> error "data declaration in compiler"
  132. | Foreign (Fimport { cc = Prim, var } as fi) ->
  133. let! _ = define var
  134. pure (cg_prim fi)
  135. | Foreign f -> pure (Fd f)
  136. let (out, _) = run_state go S.empty
  137. out