Skip to content

Commit fea0a31

Browse files
committed
Add declaration definition (macro)
1 parent eea51b4 commit fea0a31

File tree

5 files changed

+101
-74
lines changed

5 files changed

+101
-74
lines changed

bin/sgen.ml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ let parse_and_eval input_file =
99
in
1010
Sedlexing.set_position lexbuf (start_pos input_file);
1111
let expr = Sgen_parsing.parse_with_error lexbuf in
12-
let expanded = List.map ~f:Expr.expand_macro expr in
12+
let preprocessed = Expr.preprocess expr in
1313
Stdlib.print_string
14-
(List.map ~f:Expr.to_string expanded |> String.concat ~sep:"\n");
14+
(List.map ~f:Expr.to_string preprocessed |> String.concat ~sep:"\n");
1515
Stdlib.print_newline ();
1616
Stdlib.print_string "----------------";
1717
Stdlib.flush Stdlib.stdout;
18-
let p = Expr.program_of_expr expanded in
18+
let p = Expr.program_of_expr preprocessed in
1919
Stdlib.print_string "\n";
2020
let _ = Stellogen.Sgen_eval.eval_program p in
2121
()

examples/syntax.sg

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
[-a b]])
1111

1212
'full focus
13-
(show @[ [a] [b] [c] ])
13+
(:= f @[ [a] [b] [c] ])
1414

1515
'identifier
1616
(:= x #a)
@@ -19,7 +19,7 @@
1919
(:= x (union #a #b))
2020

2121
'string literals
22-
(:= s ["hello world"])
22+
(:= s "hello world")
2323

2424
'cons
2525
' [0 1 e] == %cons(0 (%cons 1 %nil))
@@ -32,11 +32,11 @@
3232
'execution
3333
(:= x [(+f X) X])
3434
(:= y (-f a))
35-
(:= ex (exec (union #x #y))) 'non-linear
36-
(:= ex (linexec (union #x #y))) 'linear
35+
(:= ex (linexec (union @#x #y))) 'linear
36+
(:= ex (exec (union @#x #y))) 'non-linear
3737

3838
'show constellation
39-
<show exec (union @#x #y)>
39+
(show #ex)
4040
(show [ [a] [b] [c] ])
4141
(show #s)
4242

@@ -103,14 +103,16 @@
103103
(== x 0)
104104
'(== x 1)
105105

106-
'manual type checking
107-
(:= 0 (+nat 0))
108-
(:= test @(exec (union @#0 #nat)))
109-
(== test ok)
110-
106+
'type checking
111107
(:= 2 <+nat s s 0>)
112-
(:= test @(exec (union @#0 #nat)))
108+
(:= test @(exec (union @#2 #nat)))
113109
(== test ok)
114110

115111
'import file
116112
'(use "examples/automata.sg")
113+
114+
'declaration definition
115+
(new-declaration (:: tested test)
116+
(:= test @(exec (union @#tested #test)))
117+
(== test ok))
118+
(:: 2 nat)

nvim/syntax/stellogen.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
syn clear
22

3-
syn keyword sgKeyword kill clean eval show use exec spec linexec trace process run union
3+
syn keyword sgKeyword define syntax kill clean eval show use exec spec linexec trace process run union
44
syn match sgComment "\s*'[^'].*$"
55
syn match sgId "#\%(\l\|\d\)\w*"
66
syn region sgComment start="'''" end="'''" contains=NONE

src/expr.ml

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,43 @@ let rec expand_macro : Raw.t -> expr = function
7272
List.fold_left t ~init:(expand_macro h) ~f:(fun acc e ->
7373
List [ expand_macro e; acc ] )
7474

75+
let rec equal_expr x y =
76+
match (x, y) with
77+
| Var x1, Var x2 | Symbol x1, Symbol x2 -> equal_string x1 x2
78+
| Unquote e1, Unquote e2 -> equal_expr e1 e2
79+
| List es1, List es2 -> begin
80+
try List.for_all2_exn es1 es2 ~f:equal_expr with _ -> false
81+
end
82+
| _ -> false
83+
84+
let rec replace_id xfrom xto = function
85+
| Symbol s -> Symbol s
86+
| Var x -> Var x
87+
| Unquote e when equal_expr e xfrom -> xto
88+
| Unquote e -> Unquote e
89+
| List es -> List (List.map ~f:(replace_id xfrom xto) es)
90+
91+
let unfold_decl_def (env : (string * (expr list * expr list)) list) es :
92+
expr list =
93+
List.fold_left es ~init:(env, []) ~f:(fun (env, acc) -> function
94+
| List (Symbol "new-declaration" :: List (Symbol k :: args) :: content) ->
95+
((k, (args, content)) :: env, acc)
96+
| List (Symbol k :: args)
97+
when List.Assoc.find ~equal:equal_string env k |> Option.is_some ->
98+
let syntax_args, content =
99+
List.Assoc.find_exn ~equal:equal_string env k
100+
in
101+
if List.length syntax_args <> List.length args then
102+
failwith ("Error: not enough args given in macro call " ^ k)
103+
else
104+
let replace_ids e =
105+
List.fold_left (List.zip_exn syntax_args args) ~init:e
106+
~f:(fun acc (xfrom, xto) -> replace_id xfrom (Unquote xto) acc )
107+
in
108+
(env, (List.map ~f:replace_ids content |> List.rev) @ acc)
109+
| e -> (env, e :: acc) )
110+
|> snd |> List.rev
111+
75112
(* ---------------------------------------
76113
Constellation of Expr
77114
--------------------------------------- *)
@@ -155,57 +192,45 @@ let rec sgen_expr_of_expr (e : expr) : sgen_expr =
155192
| List [ Symbol k; g ] when equal_string k focus_op ->
156193
Focus (sgen_expr_of_expr g)
157194
(* union *)
158-
| List (Symbol k :: gs) when equal_string k "union" ->
159-
Union (List.map ~f:sgen_expr_of_expr gs)
195+
| List (Symbol "union" :: gs) -> Union (List.map ~f:sgen_expr_of_expr gs)
160196
(* process *)
161-
| List (Symbol k :: gs) when equal_string k "process" ->
162-
Process (List.map ~f:sgen_expr_of_expr gs)
197+
| List (Symbol "process" :: gs) -> Process (List.map ~f:sgen_expr_of_expr gs)
163198
(* kill *)
164-
| List [ Symbol k; g ] when equal_string k "kill" ->
165-
Kill (sgen_expr_of_expr g)
199+
| List [ Symbol "kill"; g ] -> Kill (sgen_expr_of_expr g)
166200
(* clean *)
167-
| List [ Symbol k; g ] when equal_string k "clean" ->
168-
Clean (sgen_expr_of_expr g)
201+
| List [ Symbol "clean"; g ] -> Clean (sgen_expr_of_expr g)
169202
(* exec *)
170-
| List [ Symbol k; g ] when equal_string k "exec" ->
171-
Exec (false, sgen_expr_of_expr g)
203+
| List [ Symbol "exec"; g ] -> Exec (false, sgen_expr_of_expr g)
172204
(* linear exec *)
173-
| List [ Symbol k; g ] when equal_string k "linexec" ->
174-
Exec (true, sgen_expr_of_expr g)
205+
| List [ Symbol "linexec"; g ] -> Exec (true, sgen_expr_of_expr g)
175206
(* eval *)
176-
| List [ Symbol k; g ] when equal_string k "eval" ->
177-
Eval (sgen_expr_of_expr g)
207+
| List [ Symbol "eval"; g ] -> Eval (sgen_expr_of_expr g)
178208
(* KEEP LAST -- raw constellation *)
179209
| List g -> Raw (constellation_of_expr (List g))
180210

181211
(* ---------------------------------------
182212
Stellogen program of Expr
183213
--------------------------------------- *)
184214

185-
(* let typedecl_of_expr : expr -> type_declaration = function
186-
| Symbol k when equal_string k nil_op -> []
187-
| List [ Symbol k; h; t ] when equal_string k cons_op ->
188-
*)
189-
190215
let decl_of_expr : expr -> declaration = function
191216
(* definition := *)
192217
| List [ Symbol k; x; g ] when equal_string k def_op ->
193218
Def (ray_of_expr x, sgen_expr_of_expr g)
194-
| List [ Symbol k; x; g ] when equal_string k "spec" ->
195-
Def (ray_of_expr x, sgen_expr_of_expr g)
219+
| List [ Symbol "spec"; x; g ] -> Def (ray_of_expr x, sgen_expr_of_expr g)
220+
| List [ Symbol "exec"; x; g ] -> Def (ray_of_expr x, sgen_expr_of_expr g)
196221
(* show *)
197-
| List [ Symbol k; g ] when equal_string k "show" ->
198-
Show (sgen_expr_of_expr g)
222+
| List [ Symbol "show"; g ] -> Show (sgen_expr_of_expr g)
199223
(* trace *)
200-
| List [ Symbol k; g ] when equal_string k "trace" ->
201-
Trace (sgen_expr_of_expr g)
224+
| List [ Symbol "trace"; g ] -> Trace (sgen_expr_of_expr g)
202225
(* expect *)
203226
| List [ Symbol k; x; g ] when equal_string k expect_op ->
204227
Expect (ray_of_expr x, sgen_expr_of_expr g, const "default")
205228
| List [ Symbol k; x; g; m ] when equal_string k expect_op ->
206229
Expect (ray_of_expr x, sgen_expr_of_expr g, ray_of_expr m)
207230
(* use *)
208231
| List [ Symbol k; r ] when equal_string k "use" -> Use (ray_of_expr r)
209-
| _ -> failwith "error: invalid declaration"
232+
| e -> failwith ("error: invalid declaration ^ " ^ to_string e)
210233

211234
let program_of_expr = List.map ~f:decl_of_expr
235+
236+
let preprocess e = e |> List.map ~f:expand_macro |> unfold_decl_def []

src/sgen_eval.ml

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,36 @@ let add_obj env x e = List.Assoc.add ~equal:equal_ray env.objs x e
99

1010
let get_obj env x = List.Assoc.find ~equal:equal_ray env.objs x
1111

12+
let rec replace_id (xfrom : ident) (xto : sgen_expr) e :
13+
(sgen_expr, err) Result.t =
14+
match e with
15+
| Id x when equal_ray x xfrom -> Ok xto
16+
| Exec (b, e) ->
17+
let* g = replace_id xfrom xto e in
18+
Exec (b, g) |> Result.return
19+
| Kill e ->
20+
let* g = replace_id xfrom xto e in
21+
Kill g |> Result.return
22+
| Clean e ->
23+
let* g = replace_id xfrom xto e in
24+
Clean g |> Result.return
25+
| Union es ->
26+
let* gs = List.map ~f:(replace_id xfrom xto) es |> Result.all in
27+
Union gs |> Result.return
28+
| Focus e ->
29+
let* g = replace_id xfrom xto e in
30+
Focus g |> Result.return
31+
| Subst (e, subst) ->
32+
let* g = replace_id xfrom xto e in
33+
Subst (g, subst) |> Result.return
34+
| Process gs ->
35+
let* procs = List.map ~f:(replace_id xfrom xto) gs |> Result.all in
36+
Process procs |> Result.return
37+
| Eval e ->
38+
let* g = replace_id xfrom xto e in
39+
Eval g |> Result.return
40+
| Raw _ | Id _ -> e |> Result.return
41+
1242
let rec map_sgen_expr env ~f : sgen_expr -> (sgen_expr, err) Result.t = function
1343
| Raw g -> Raw (f g) |> Result.return
1444
| Id x -> begin
@@ -54,36 +84,6 @@ let rec map_sgen_expr env ~f : sgen_expr -> (sgen_expr, err) Result.t = function
5484
let* map_e = map_sgen_expr env ~f e in
5585
Eval map_e |> Result.return
5686

57-
let rec replace_id env (_from : ident) (_to : sgen_expr) e :
58-
(sgen_expr, err) Result.t =
59-
match e with
60-
| Id x when equal_ray x _from -> Ok _to
61-
| Exec (b, e) ->
62-
let* g = replace_id env _from _to e in
63-
Exec (b, g) |> Result.return
64-
| Kill e ->
65-
let* g = replace_id env _from _to e in
66-
Kill g |> Result.return
67-
| Clean e ->
68-
let* g = replace_id env _from _to e in
69-
Clean g |> Result.return
70-
| Union es ->
71-
let* gs = List.map ~f:(replace_id env _from _to) es |> Result.all in
72-
Union gs |> Result.return
73-
| Focus e ->
74-
let* g = replace_id env _from _to e in
75-
Focus g |> Result.return
76-
| Subst (e, subst) ->
77-
let* g = replace_id env _from _to e in
78-
Subst (g, subst) |> Result.return
79-
| Process gs ->
80-
let* procs = List.map ~f:(replace_id env _from _to) gs |> Result.all in
81-
Process procs |> Result.return
82-
| Eval e ->
83-
let* g = replace_id env _from _to e in
84-
Eval g |> Result.return
85-
| Raw _ | Id _ -> e |> Result.return
86-
8787
let subst_vars env _from _to =
8888
map_sgen_expr env ~f:(subst_all_vars [ (_from, _to) ])
8989

@@ -172,7 +172,7 @@ let rec eval_sgen_expr (env : env) :
172172
let* subst = subst_funcs env pf1 pf2 e in
173173
eval_sgen_expr env subst
174174
| Subst (e, SGal (x, _to)) ->
175-
let* fill = replace_id env x _to e in
175+
let* fill = replace_id x _to e in
176176
eval_sgen_expr env fill
177177
| Eval e -> (
178178
let* eval_e = eval_sgen_expr env e in
@@ -240,8 +240,8 @@ let rec eval_decl env : declaration -> (env, err) Result.t = function
240240
in
241241
Sedlexing.set_position lexbuf (start_pos formatted_filename);
242242
let expr = Sgen_parsing.parse_with_error lexbuf in
243-
let expanded = List.map ~f:Expr.expand_macro expr in
244-
let p = Expr.program_of_expr expanded in
243+
let preprocessed = Expr.preprocess expr in
244+
let p = Expr.program_of_expr preprocessed in
245245
let* env = eval_program p in
246246
Ok env
247247

0 commit comments

Comments
 (0)