@@ -12,20 +12,21 @@ let rec compile_expr (expr : Ast.Expr.t) : Beam.Builder.Expr.t =
1212 | Variable var -> Builder. var var
1313 | Nil -> Builder. nil
1414 | Cons (h , t ) -> Builder. cons (compile_expr h) (compile_expr t)
15- | Functor ({ arity ; _ } as f ) when arity = 0 ->
15+ | Functor ({ elements ; _ } as f ) when FT. size elements = 0 ->
1616 Builder. atom @@ Ast.Expr. extract_func_label f
1717 | Functor ({ elements; _ } as f ) ->
1818 let name = Builder. atom @@ Ast.Expr. extract_func_label f in
19- Builder. tuple (name :: List. map compile_expr elements)
19+ (* TODO: use finger trees in Builder *)
20+ Builder. tuple @@ FT. to_list (FT. cons (FT. map compile_expr elements) name)
2021 | Integer number -> Builder. int number
2122
2223let call_with_fresh (name : string ) expr =
2324 let open Beam in
2425 Ukanren. call_with_fresh @@ Builder. lambda name expr
2526
2627let compile_declaration_bodies { module_name; imports; _ }
27- (clauses : Ast.Clause.decl Location.with_location list ) =
28- if List . is_empty clauses then (
28+ (clauses : Ast.Clause.decl Location.with_location FT.t ) =
29+ if FT . is_empty clauses then (
2930 Logger. simply_unreachable " Predicates must have at least one body" ;
3031 exit 1 )
3132 else
@@ -36,8 +37,8 @@ let compile_declaration_bodies { module_name; imports; _ }
3637 let find_variables call = Preprocessor. find_variables (Functor call) in
3738 let vars =
3839 content.body
39- |> List . map (Fun. compose find_variables Location. strip_loc)
40- |> List . fold_left Set. union Set. empty
40+ |> FT . map (Fun. compose find_variables Location. strip_loc)
41+ |> FT . fold_left Set. union Set. empty
4142 |> Set. filter (fun name ->
4243 Str. string_match (Str. regexp " ^[A-Z]" ) name 0 )
4344 in
@@ -46,50 +47,54 @@ let compile_declaration_bodies { module_name; imports; _ }
4647 (* TODO: We should use locations when calling Beam helpers. They don't use
4748 locations yet, hence they are not being sent as arguments *)
4849 let make_function { content = call ; loc } =
49- let { Ast.Expr. name; elements; arity } = call in
50- let args = List. map compile_expr elements in
51- match (name, arity) with
52- | ([ { content = "karuta" ; _ } ], { content = "eq" ; _ } ), 2 -> (
53- match args with
54- | expr1 :: expr2 :: _ -> Ukanren. eq expr1 expr2
55- | _ ->
56- Logger. unreachable loc
57- " Mismatch between arity and length of elements in builtin \
58- 'eq'" ;
59- exit 1 )
60- | ([ { content = "karuta" ; _ } ], { content = "nat" ; _ } ), 1 -> (
61- match args with
62- | expr1 :: _ -> Ukanren. nat expr1
63- | _ ->
64- Logger. unreachable loc
65- " Mismatch between arity and length of elements in builtin \
66- 'nat'" ;
67- exit 1 )
68- | ([] , _ ), _ ->
69- Builder. call
70- (Builder. atom @@ Ast.Expr. extract_func_label call)
71- args
72- | ((head :: _ as path ), { content = fun_name ; _ } ), _ ->
73- Builder. call_with_module
74- (Builder. atom
75- @@ flat_module_name
76- (let suffix = List. map Location. strip_loc path in
77- if BatSet.String. mem head.content imports then suffix
78- else module_name :: suffix))
79- (Builder. atom fun_name) args
50+ let { Ast.Expr. name; elements } = call in
51+ let arity = FT. size elements in
52+ let args = FT. map compile_expr elements in
53+ if Ast.Expr. match_func call [ " karuta" ; " eq" ] && arity = 2 then (
54+ match FT. to_list args with
55+ | [ expr1; expr2 ] -> Ukanren. eq expr1 expr2
56+ | _ ->
57+ Logger. unreachable loc
58+ " Mismatch between arity and length of elements in builtin \
59+ 'eq'" ;
60+ exit 1 )
61+ else if Ast.Expr. match_func call [ " karuta" ; " nat" ] && arity = 1 then (
62+ match FT. to_list args with
63+ | [ expr1 ] -> Ukanren. nat expr1
64+ | _ ->
65+ Logger. unreachable loc
66+ " Mismatch between arity and length of elements in builtin \
67+ 'nat'" ;
68+ exit 1 )
69+ else
70+ let path, { content = fun_name; _ } = name in
71+ match FT. head path with
72+ | None ->
73+ Builder. call (Builder. atom @@ Ast.Expr. extract_func_label call)
74+ @@ FT. to_list args
75+ | Some head ->
76+ Builder. call_with_module
77+ (Builder. atom
78+ @@ flat_module_name
79+ (let suffix =
80+ FT. to_list @@ FT. map Location. strip_loc path
81+ in
82+ if BatSet.String. mem head.content imports then suffix
83+ else module_name :: suffix))
84+ (Builder. atom fun_name) (FT. to_list args)
8085 in
8186
82- content.body |> List . map make_function |> Ukanren. conj
87+ content.body |> FT . map make_function |> FT. to_list |> Ukanren. conj
8388 in
8489 Set. fold call_with_fresh vars body
8590 in
86- clauses |> List . map compile_single_body |> Ukanren. disj
91+ clauses |> FT . map compile_single_body |> FT. to_list |> Ukanren. disj
8792
8893let compile_multi
8994 (({ name; arity } , first_clause , remaining_clauses ) :
9095 Ast. head
9196 * Ast.Clause. decl Location. with_location
92- * Ast.Clause. decl Location. with_location list )
97+ * Ast.Clause. decl Location. with_location FT. t )
9398 ({ env; _ } as compiler : unit t ) : unit t =
9499 let declaration =
95100 let args =
@@ -98,7 +103,8 @@ let compile_multi
98103 in
99104 Beam.Builder. single_function_declaration name
100105 (List. map (fun v -> Beam.Builder.Pattern. Variable v) args)
101- @@ compile_declaration_bodies compiler (first_clause :: remaining_clauses)
106+ @@ compile_declaration_bodies compiler
107+ (FT. cons remaining_clauses first_clause)
102108 in
103109 let export = Beam.Builder.Attribute. export [ (name, arity) ] in
104110 {
0 commit comments