Compare commits
2 Commits
c4f09d6ca8
...
0a342f4164
Author | SHA1 | Date | |
---|---|---|---|
0a342f4164 | |||
63aada8b50 |
7
.gitignore
vendored
Normal file
7
.gitignore
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
core
|
||||||
|
*.cmx
|
||||||
|
*.cml
|
||||||
|
*.cmi
|
||||||
|
*.cmo
|
||||||
|
*.o
|
||||||
|
a.out
|
@@ -6,8 +6,8 @@
|
|||||||
(:macro seq (hd .. tl)
|
(:macro seq (hd .. tl)
|
||||||
(:seq hd) (:seq tl))
|
(:seq hd) (:seq tl))
|
||||||
|
|
||||||
(:macro @ ('k)
|
(:macro @ (k)
|
||||||
(:t 'k ":"))
|
(:t k ":"))
|
||||||
|
|
||||||
(:macro @ (k v)
|
(:macro @ (k v)
|
||||||
(:t k ": " v))
|
(:t k ": " v))
|
||||||
|
140
sexpr.ml
140
sexpr.ml
@@ -24,7 +24,7 @@ module Testing = struct
|
|||||||
Printf.printf "Pass\n%!";
|
Printf.printf "Pass\n%!";
|
||||||
Pass
|
Pass
|
||||||
with e ->
|
with e ->
|
||||||
Printf.printf "FAIL\n";
|
Printf.printf "FAIL\n%!";
|
||||||
if test_only <> [] then begin
|
if test_only <> [] then begin
|
||||||
let msg = Printexc.to_string e
|
let msg = Printexc.to_string e
|
||||||
and stack = Printexc.get_backtrace () in
|
and stack = Printexc.get_backtrace () in
|
||||||
@@ -440,13 +440,13 @@ module SExpr = struct
|
|||||||
let li1 s =
|
let li1 s =
|
||||||
Cons(s, Nil)
|
Cons(s, Nil)
|
||||||
|
|
||||||
exception Not_Sexpr_List
|
exception Not_SExpr_List
|
||||||
|
|
||||||
let rec append tl hd =
|
let rec append tl hd =
|
||||||
match hd with
|
match hd with
|
||||||
Nil -> tl
|
Nil -> tl
|
||||||
| Cons(x, rem) -> Cons(x, append tl rem)
|
| Cons(x, rem) -> Cons(x, append tl rem)
|
||||||
| _ -> raise Not_Sexpr_List
|
| _ -> raise Not_SExpr_List
|
||||||
|
|
||||||
let () = test "SExpr.append" @@ begin fun () ->
|
let () = test "SExpr.append" @@ begin fun () ->
|
||||||
let a = Cons(Int 1, Cons(Int 2, Cons(Int 3, Nil)))
|
let a = Cons(Int 1, Cons(Int 2, Cons(Int 3, Nil)))
|
||||||
@@ -471,7 +471,7 @@ module SExpr = struct
|
|||||||
match li with
|
match li with
|
||||||
Nil -> Nil
|
Nil -> Nil
|
||||||
| Cons(x, rem) -> append (flat_map fn rem) (fn x)
|
| Cons(x, rem) -> append (flat_map fn rem) (fn x)
|
||||||
| _ -> raise Not_Sexpr_List
|
| _ -> raise Not_SExpr_List
|
||||||
|
|
||||||
let () = test "SExpr.flat_map.0" @@ begin fun () ->
|
let () = test "SExpr.flat_map.0" @@ begin fun () ->
|
||||||
let a = Cons(Int 1, Cons(Int 2, Cons(Int 3, Nil)))
|
let a = Cons(Int 1, Cons(Int 2, Cons(Int 3, Nil)))
|
||||||
@@ -498,7 +498,7 @@ module SExpr = struct
|
|||||||
let x, acc = fn acc x in
|
let x, acc = fn acc x in
|
||||||
let vv, acc = aggr_flat_map fn acc rem in
|
let vv, acc = aggr_flat_map fn acc rem in
|
||||||
append vv x, acc
|
append vv x, acc
|
||||||
| _ -> raise Not_Sexpr_List
|
| _ -> raise Not_SExpr_List
|
||||||
|
|
||||||
let () = test "SExpr.aggr_flat_map.0" @@ begin fun () ->
|
let () = test "SExpr.aggr_flat_map.0" @@ begin fun () ->
|
||||||
let a = Cons(Int 1, Cons(Int 2, Nil))
|
let a = Cons(Int 1, Cons(Int 2, Nil))
|
||||||
@@ -660,13 +660,14 @@ module SExpr = struct
|
|||||||
|> until ex_end
|
|> until ex_end
|
||||||
|> map (fun li ->
|
|> map (fun li ->
|
||||||
List.fold_right (fun x acc -> Cons(x,acc)) li Nil)
|
List.fold_right (fun x acc -> Cons(x,acc)) li Nil)
|
||||||
|
|
||||||
|
let parser_tests = []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
module SExprMacroExp = struct
|
module SExprMacroExp = struct
|
||||||
exception Misformated_Macro of SExpr.t
|
exception Misformated_Macro of SExpr.t
|
||||||
exception Macro_Doesnt_App
|
exception Macro_Doesnt_App
|
||||||
exception Macro_App_TODO of ((string * SExpr.t) list) * SExpr.t
|
|
||||||
exception FIXME of SExpr.t
|
exception FIXME of SExpr.t
|
||||||
|
|
||||||
let assoc_all k li =
|
let assoc_all k li =
|
||||||
@@ -686,53 +687,46 @@ module SExprMacroExp = struct
|
|||||||
|
|
||||||
let rec eval (ctx: (string * (SExpr.t * SExpr.t)) list) s =
|
let rec eval (ctx: (string * (SExpr.t * SExpr.t)) list) s =
|
||||||
let open SExpr in
|
let open SExpr in
|
||||||
Format.printf "ctx:\n%!";
|
|
||||||
List.iter begin fun vv ->
|
|
||||||
let k,v = vv in
|
|
||||||
Format.printf "- %s = %a%a\n%!" k pp_t (fst v) pp_t (snd v)
|
|
||||||
end ctx;
|
|
||||||
let s, ctx = if is_list s then
|
let s, ctx = if is_list s then
|
||||||
aggr_flat_map eval ctx s
|
aggr_flat_map eval ctx s
|
||||||
else
|
else
|
||||||
s, ctx
|
s, ctx
|
||||||
in
|
in
|
||||||
let s, ctx = check_expands_while ctx s in
|
check_expands_while ctx s
|
||||||
s, ctx
|
|
||||||
(* expr -> list(new exprs) * bool:changed * ctx *)
|
(* expr -> list(new exprs) * bool:changed * ctx *)
|
||||||
and check_expands ctx s =
|
and check_expands ctx s =
|
||||||
let open SExpr in
|
let open SExpr in
|
||||||
Format.printf "checking: %a\n%!" pp_t s;
|
|
||||||
match s with
|
match s with
|
||||||
Cons(Id(":macro"), r) -> begin
|
Cons(Id(":macro"), r) -> begin
|
||||||
let a = match r with
|
let a = match r with
|
||||||
Cons(Id(l), Cons(a,b)) -> l, (a,b)
|
Cons(Id(l), Cons(a,b)) -> l, (a,b)
|
||||||
| _ -> raise @@ Misformated_Macro s
|
| _ -> raise @@ Misformated_Macro s
|
||||||
in
|
in
|
||||||
Format.printf "define: %s%a -> %a\n%!" (fst a) pp_t (fst (snd a)) pp_t (snd (snd a));
|
|
||||||
Nil, false, (a :: ctx)
|
Nil, false, (a :: ctx)
|
||||||
end
|
end
|
||||||
| Cons(Id(i), r) -> begin
|
| Cons(Id(i), r) when String.starts_with ~prefix:":" i ->
|
||||||
let i = if String.starts_with ~prefix:":" i then
|
let i = String.sub i 1 ((String.length i) - 1) in
|
||||||
String.sub i 1 ((String.length i) - 1)
|
check_expands_macro i ctx r s
|
||||||
else "@" in
|
| Cons(_) ->
|
||||||
Format.printf "consider expand %s%a\n%!" i pp_t r;
|
check_expands_macro "@" ctx s s
|
||||||
let rec test opt ctx =
|
|
||||||
begin match opt with
|
|
||||||
[] -> li1 s, false, ctx
|
|
||||||
| hd :: tl ->
|
|
||||||
try
|
|
||||||
expand_macro r hd, true, ctx
|
|
||||||
with Macro_Doesnt_App ->
|
|
||||||
test tl ctx
|
|
||||||
end
|
|
||||||
in
|
|
||||||
test (assoc_all i ctx) ctx
|
|
||||||
end
|
|
||||||
| s -> li1 s, false, ctx
|
| s -> li1 s, false, ctx
|
||||||
|
and check_expands_macro i ctx r s =
|
||||||
|
let open SExpr in
|
||||||
|
let rec test opt ctx =
|
||||||
|
begin match opt with
|
||||||
|
[] -> li1 s, false, ctx
|
||||||
|
| hd :: tl ->
|
||||||
|
try
|
||||||
|
expand_macro r hd, true, ctx
|
||||||
|
with Macro_Doesnt_App ->
|
||||||
|
test tl ctx
|
||||||
|
end
|
||||||
|
in
|
||||||
|
test (assoc_all i ctx) ctx
|
||||||
and check_expands_while ctx s =
|
and check_expands_while ctx s =
|
||||||
let s', c, ctx' = check_expands ctx s in
|
let s', c, ctx' = check_expands ctx s in
|
||||||
if c then
|
if c then
|
||||||
check_expands_while ctx' s'
|
SExpr.aggr_flat_map check_expands_while ctx' s'
|
||||||
else
|
else
|
||||||
s', ctx'
|
s', ctx'
|
||||||
and match_macro_arg args margs =
|
and match_macro_arg args margs =
|
||||||
@@ -740,17 +734,42 @@ module SExprMacroExp = struct
|
|||||||
match args, margs with
|
match args, margs with
|
||||||
Nil, Nil -> []
|
Nil, Nil -> []
|
||||||
| Cons(_), Cons(Id(".."), Cons(Id(rem),Nil)) -> [rem, args]
|
| Cons(_), Cons(Id(".."), Cons(Id(rem),Nil)) -> [rem, args]
|
||||||
| Cons(v,rl), Cons(Id(k), rr) -> [k,v] @ match_macro_arg rl rr
|
| Cons(v,rl), Cons(Id(k), rr) -> [k,li1 v] @ match_macro_arg rl rr
|
||||||
| _ -> raise Macro_Doesnt_App
|
| _ -> raise Macro_Doesnt_App
|
||||||
|
and expand_macro_eval expr defs =
|
||||||
|
let open SExpr in
|
||||||
|
let perfm expr =
|
||||||
|
begin match expr with
|
||||||
|
Id(i) when String.starts_with ~prefix:"'" i ->
|
||||||
|
li1 @@ Id(String.sub i 1 (String.length i - 1))
|
||||||
|
| Id(i) -> begin match List.assoc_opt i defs with
|
||||||
|
Some x -> x
|
||||||
|
| None -> li1 expr
|
||||||
|
end
|
||||||
|
| x when is_list x -> expand_macro_eval x defs
|
||||||
|
| x -> li1 x
|
||||||
|
end
|
||||||
|
in
|
||||||
|
if is_list expr then
|
||||||
|
flat_map perfm expr
|
||||||
|
else
|
||||||
|
perfm expr
|
||||||
and expand_macro args macro =
|
and expand_macro args macro =
|
||||||
let (margs, mbody) = macro in
|
let (margs, mbody) = macro in
|
||||||
let defs = match_macro_arg args margs in
|
let defs = match_macro_arg args margs in
|
||||||
raise @@ Macro_App_TODO (defs, mbody);
|
expand_macro_eval mbody defs
|
||||||
args
|
|
||||||
let do_eval s =
|
let do_eval s =
|
||||||
eval [] s
|
eval [] s
|
||||||
|> fst
|
|> fst
|
||||||
|
|
||||||
|
(* only use this for testing! *)
|
||||||
|
let sparse src =
|
||||||
|
PC.doparse
|
||||||
|
Format.err_formatter
|
||||||
|
{ source = src; path = "top" }
|
||||||
|
(SExpr.parse_top ())
|
||||||
|
|> Option.get
|
||||||
|
|
||||||
let () = test "SExprMacroExp.do_eval.unchanged_num" @@ begin fun () ->
|
let () = test "SExprMacroExp.do_eval.unchanged_num" @@ begin fun () ->
|
||||||
let open SExpr in
|
let open SExpr in
|
||||||
let a = Int 1 in
|
let a = Int 1 in
|
||||||
@@ -768,6 +787,55 @@ module SExprMacroExp = struct
|
|||||||
let a = Cons(Int 1, Cons( Cons(Int 10, Cons(Int 20, Nil)), Cons(Int 3, Nil))) in
|
let a = Cons(Int 1, Cons( Cons(Int 10, Cons(Int 20, Nil)), Cons(Int 3, Nil))) in
|
||||||
assert (do_eval a = li1 a)
|
assert (do_eval a = li1 a)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_no_body" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro one()) (:one)"
|
||||||
|
and p = "()" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_body" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro a() 1 2) (:a)"
|
||||||
|
and p = "(1 2)" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_arg" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro a(arg) 1 arg) (:a 2)"
|
||||||
|
and p = "(1 2)" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_args" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro a(arg arg2) arg2 1 arg) (:a 2 0)"
|
||||||
|
and p = "(0 1 2)" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_varargs" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro a(arg .. rem) arg 1 rem) (:a 0 2 3)"
|
||||||
|
and p = "(0 1 2 3)" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_varargs_notmatch_none" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro a(arg .. rem) arg 1 rem) (:a 0)"
|
||||||
|
and p = "((:a 0))" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
|
|
||||||
|
let () = test "SExprMacroExp.do_eval.macro_body_paren" ~depends:SExpr.parser_tests @@ begin fun () ->
|
||||||
|
let open SExpr in
|
||||||
|
let a = "(:macro a() (1)) (:a)"
|
||||||
|
and p = "((1))" in
|
||||||
|
assert (do_eval (sparse a) = sparse p)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user