ref: 4853f4341f2d0fa254630faf24e8a0eed55d8b63
parent: a818d0d894cbc356744023dc3d8093b124e80923
author: smazga <[email protected]>
date: Tue Aug 11 17:16:30 EDT 2020
some macro stuff
--- a/core.ml
+++ b/core.ml
@@ -1,6 +1,7 @@
module T = Types.Types
let base = Env.make None
+let kw_macro = T.String "macro"
let number_compare t f =
Types.proc (function
@@ -26,6 +27,12 @@
let init env =
Env.set
env
+ (Types.symbol "raise")
+ (Types.proc (function
+ | [ ast ] -> raise (Types.M9exn ast)
+ | _ -> T.Nil));
+ Env.set
+ env
(Types.symbol "*arguments*")
(Types.list
(if Array.length Sys.argv > 1
@@ -39,6 +46,17 @@
Env.set env (Types.symbol "<=") (simple_compare mk_bool ( <= ));
Env.set env (Types.symbol ">") (simple_compare mk_bool ( > ));
Env.set env (Types.symbol ">=") (simple_compare mk_bool ( >= ));
+ Env.set
+ env
+ (Types.symbol "proc?")
+ (Types.proc (function
+ | [ T.Proc { T.meta = T.Map { T.value = meta } } ] ->
+ mk_bool
+ (not
+ (Types.M9map.mem kw_macro meta
+ && Types.to_bool (Types.M9map.find kw_macro meta)))
+ | [ T.Proc _ ] -> T.Bool true
+ | _ -> T.Bool false));
Env.set
env
(Types.symbol "number?")
--- a/m9.ml
+++ b/m9.ml
@@ -31,6 +31,35 @@
| ast -> Types.list [ Types.symbol "quote"; ast ]
;;
+let is_macro_call ast env =
+ match ast with
+ | T.List { T.value = s :: args } ->
+ (match
+ try Env.get env s with
+ | _ -> T.Nil
+ with
+ | T.Proc { T.meta = T.Map { T.value = meta } } ->
+ Types.M9map.mem Core.kw_macro meta
+ && Types.to_bool (Types.M9map.find Core.kw_macro meta)
+ | _ -> false)
+ | _ -> false
+;;
+
+let rec macroexpand ast env =
+ if is_macro_call ast env
+ then (
+ match ast with
+ | T.List { T.value = s :: args } ->
+ (match
+ try Env.get env s with
+ | _ -> T.Nil
+ with
+ | T.Proc { T.value = f } -> macroexpand (f args) env
+ | _ -> ast)
+ | _ -> ast)
+ else ast
+;;
+
let rec eval_ast ast env =
match ast with
| T.Symbol s -> Env.get env ast
--- a/printer.ml
+++ b/printer.ml
@@ -17,7 +17,8 @@
| T.Bool false -> "#f"
| T.Char c -> "#\\" ^ Char.escaped c
| T.Nil -> "nil"
- | T.Comment -> "" (* TODO: this leaves a space in the output for block comments *)
+ | T.Map _ | T.Comment ->
+ "" (* TODO: this leaves a space in the output for block comments *)
(* | T.Pair ({ T.value = one }, { T.value = two }) -> "(" ^ (print one readable) ^ " . " ^ (print two readable) ^ ")" *)
| T.Proc p -> "#<proc>"
| T.Symbol { T.value = s } -> s
--- a/types.ml
+++ b/types.ml
@@ -6,6 +6,8 @@
and t =
| List of t list with_meta
+ | Vector of t list with_meta
+ | Map of t M9map.t with_meta
| Bool of bool
| Char of char
| Nil
@@ -18,7 +20,6 @@
| Number of float with_meta
| Port of bool (* not sure how to represent this *)
| String of string
- | Vector of t list with_meta
| Record of t with_meta
end =
Types
@@ -33,8 +34,18 @@
let compare = Stdlib.compare
end
+and M9map : (Map.S with type key = Value.t) = Map.Make (Value)
+
+let to_bool x =
+ match x with
+ | Types.Nil | Types.Bool false -> false
+ | _ -> true
+;;
+
type m9type = Value.t
+exception M9exn of Types.t
+
let to_bool x =
match x with
| Types.Nil | Types.Bool false -> false
@@ -47,6 +58,7 @@
;;
let list x = Types.List { Types.value = x; meta = Types.Nil }
+let map x = Types.Map { Types.value = x; meta = Types.Nil }
(* let pair x xs = Types.Pair ({ Types.value = x; meta = Types.Nil }, Types.List { Types.value = xs; meta = Types.Nil }) *)
let proc x = Types.Proc { Types.value = x; meta = Types.Nil }