From 414ae0a66ba8c5656bfb9175128c7f02f155f54f Mon Sep 17 00:00:00 2001 From: engboris Date: Sun, 12 Oct 2025 14:57:40 +0200 Subject: [PATCH 1/3] Fix datatype of expr with locations --- bin/sgen.ml | 2 +- src/expr.ml | 204 +++++++++++++++++++++++------------------------ src/sgen_eval.ml | 4 +- 3 files changed, 101 insertions(+), 109 deletions(-) diff --git a/bin/sgen.ml b/bin/sgen.ml index 6d46de2..decc737 100644 --- a/bin/sgen.ml +++ b/bin/sgen.ml @@ -104,7 +104,7 @@ let watch input_file timeout = let preprocess_only input_file = let expr = parse input_file in let preprocessed = Expr.preprocess expr in - preprocessed |> List.map ~f:Expr.to_string |> String.concat ~sep:"\n" + preprocessed |> List.map ~f:(fun e -> Expr.to_string e.Expr.content) |> String.concat ~sep:"\n" |> Stdlib.print_endline let input_file_arg = diff --git a/src/expr.ml b/src/expr.ml index 9f49343..a0ce75b 100644 --- a/src/expr.ml +++ b/src/expr.ml @@ -7,6 +7,12 @@ let ( let* ) x f = Result.bind x ~f type ident = string +(* Generic type for attaching source locations *) +type 'a loc = { + content : 'a; + loc : source_location option; +} + module Raw = struct type t = | Symbol of string @@ -26,15 +32,13 @@ end type expr = | Symbol of string | Var of ident - | List of expr list - | WithPos of expr * source_location + | List of (expr loc) list let rec equal_expr e1 e2 = match (e1, e2) with | Symbol s1, Symbol s2 -> String.equal s1 s2 | Var v1, Var v2 -> String.equal v1 v2 - | List l1, List l2 -> List.equal equal_expr l1 l2 - | WithPos (e1', _), e2' | e1', WithPos (e2', _) -> equal_expr e1' e2' + | List l1, List l2 -> List.equal (fun a b -> equal_expr a.content b.content) l1 l2 | _ -> false let primitive = String.append "%" @@ -65,58 +69,61 @@ let rec to_string : expr -> string = function | Symbol s -> s | Var x -> x | List es -> - Printf.sprintf "(%s)" (List.map ~f:to_string es |> String.concat ~sep:" ") - | WithPos (e, _) -> to_string e - -let rec expand_macro : Raw.t -> expr = function - | Raw.Symbol s -> Symbol s - | Raw.Var x -> Var x - | Raw.String s -> List [ Symbol string_op; Symbol s ] - | Raw.Call e' -> List [ Symbol call_op; expand_macro e' ] - | Raw.Focus e' -> List [ Symbol focus_op; expand_macro e' ] - | Raw.Group es -> List (Symbol group_op :: List.map ~f:expand_macro es) - | Raw.List es -> List (List.map ~f:expand_macro es) + Printf.sprintf "(%s)" (List.map ~f:(fun e -> to_string e.content) es |> String.concat ~sep:" ") + +let rec expand_macro : Raw.t -> expr loc = function + | Raw.Symbol s -> { content = Symbol s; loc = None } + | Raw.Var x -> { content = Var x; loc = None } + | Raw.String s -> { content = List [ { content = Symbol string_op; loc = None }; { content = Symbol s; loc = None } ]; loc = None } + | Raw.Call e' -> + let e = expand_macro e' in + { content = List [ { content = Symbol call_op; loc = None }; e ]; loc = None } + | Raw.Focus e' -> + let e = expand_macro e' in + { content = List [ { content = Symbol focus_op; loc = None }; e ]; loc = None } + | Raw.Group es -> + { content = List ({ content = Symbol group_op; loc = None } :: List.map ~f:expand_macro es); loc = None } + | Raw.List es -> + { content = List (List.map ~f:expand_macro es); loc = None } | Raw.Cons es -> expand_macro (Raw.ConsWithBase (es, Symbol nil_op)) | Raw.ConsWithBase (es, base) -> List.fold_left es ~init:(expand_macro base) ~f:(fun acc e -> - List [ Symbol cons_op; expand_macro e; acc ] ) + { content = List [ { content = Symbol cons_op; loc = None }; expand_macro e; acc ]; loc = None } ) | Raw.ConsWithParams (es, ps) -> - List [ Symbol params_op; expand_macro (Cons es); expand_macro (List ps) ] - | Raw.Stack [] -> List [] + { content = List [ { content = Symbol params_op; loc = None }; expand_macro (Cons es); expand_macro (List ps) ]; loc = None } + | Raw.Stack [] -> { content = List []; loc = None } | Raw.Stack (h :: t) -> List.fold_left t ~init:(expand_macro h) ~f:(fun acc e -> - List [ expand_macro e; acc ] ) + { content = List [ expand_macro e; acc ]; loc = None } ) | Raw.Positioned (e, start_pos, _) -> - let loc = + let source_loc = { filename = start_pos.Lexing.pos_fname ; line = start_pos.Lexing.pos_lnum ; column = start_pos.Lexing.pos_cnum - start_pos.Lexing.pos_bol + 1 } in - WithPos (expand_macro e, loc) + let expanded = expand_macro e in + { expanded with loc = Some source_loc } -let rec replace_id (var_from : ident) replacement expr = - match expr with - | Var x when String.equal x var_from -> replacement +let rec replace_id (var_from : ident) replacement (expr : expr loc) : expr loc = + match expr.content with + | Var x when String.equal x var_from -> { replacement with loc = expr.loc } | Symbol _ | Var _ -> expr - | List exprs -> List (List.map exprs ~f:(replace_id var_from replacement)) - | WithPos (e, loc) -> WithPos (replace_id var_from replacement e, loc) + | List exprs -> { content = List (List.map exprs ~f:(replace_id var_from replacement)); loc = expr.loc } -let unfold_decl_def (macro_env : (string * (string list * expr list)) list) +let unfold_decl_def (macro_env : (string * (string list * (expr loc) list)) list) exprs = - let rec process_expr (env, acc) = function - | WithPos (e, loc) -> - let env', result = process_expr (env, []) e in - (env', List.map result ~f:(fun r -> WithPos (r, loc)) @ acc) - | List (Symbol "new-declaration" :: List (Symbol macro_name :: args) :: body) + let rec process_expr (env, acc) (expr : expr loc) = + match expr.content with + | List ({ content = Symbol "new-declaration"; _ } :: { content = List ({ content = Symbol macro_name; _ } :: args); _ } :: body) -> let var_args = - List.map args ~f:(function + List.map args ~f:(fun arg -> match arg.content with | Var x -> x | _ -> failwith "error: syntax declaration must contain variables" ) in ((macro_name, (var_args, body)) :: env, acc) - | List (Symbol macro_name :: call_args) as expr -> ( + | List ({ content = Symbol macro_name; _ } :: call_args) -> ( match List.Assoc.find env macro_name ~equal:String.equal with | Some (formal_params, body) -> if List.length formal_params <> List.length call_args then @@ -126,16 +133,16 @@ let unfold_decl_def (macro_env : (string * (string list * expr list)) list) (List.length formal_params) (List.length call_args) ) else - let apply_substitution expr = - List.fold_left (List.zip_exn formal_params call_args) ~init:expr + let apply_substitution e = + List.fold_left (List.zip_exn formal_params call_args) ~init:e ~f:(fun acc (param, arg) -> replace_id param arg acc ) in let expanded = List.map body ~f:apply_substitution |> List.rev in (env, expanded @ acc) | None -> (env, expr :: acc) ) - | expr -> (env, expr :: acc) + | _ -> (env, expr :: acc) in - List.fold_left exprs ~init:(macro_env, []) ~f:process_expr |> snd |> List.rev + List.fold_left exprs ~init:(macro_env, []) ~f:(fun (env, acc) e -> process_expr (env, acc) e) |> snd |> List.rev (* --------------------------------------- Constellation of Expr @@ -152,26 +159,24 @@ let rec ray_of_expr : expr -> (ray, expr_err) Result.t = function | Var "_" -> to_var ("_" ^ fresh_placeholder ()) |> Result.return | Var s -> to_var s |> Result.return | List [] -> Error EmptyRay - | List (Symbol h :: t) -> - let* args = List.map ~f:ray_of_expr t |> Result.all in + | List ({ content = Symbol h; _ } :: t) -> + let* args = List.map ~f:(fun e -> ray_of_expr e.content) t |> Result.all in to_func (symbol_of_str h, args) |> Result.return | List (_ :: _) as e -> Error (NonConstantRayHeader (to_string e)) - | WithPos (e, _) -> ray_of_expr e let bans_of_expr ban_exprs : (ban list, expr_err) Result.t = let rec ban_of_expr = function - | List [ Symbol op; expr1; expr2 ] when String.equal op ineq_op -> - let* ray1 = ray_of_expr expr1 in - let* ray2 = ray_of_expr expr2 in + | List [ { content = Symbol op; _ }; expr1; expr2 ] when String.equal op ineq_op -> + let* ray1 = ray_of_expr expr1.content in + let* ray2 = ray_of_expr expr2.content in Ineq (ray1, ray2) |> Result.return - | List [ Symbol op; expr1; expr2 ] when String.equal op incomp_op -> - let* ray1 = ray_of_expr expr1 in - let* ray2 = ray_of_expr expr2 in + | List [ { content = Symbol op; _ }; expr1; expr2 ] when String.equal op incomp_op -> + let* ray1 = ray_of_expr expr1.content in + let* ray2 = ray_of_expr expr2.content in Incomp (ray1, ray2) |> Result.return - | WithPos (e, _) -> ban_of_expr e | invalid_expr -> Error (InvalidBan (to_string invalid_expr)) in - List.map ban_exprs ~f:ban_of_expr |> Result.all + List.map ban_exprs ~f:(fun e -> ban_of_expr e.content) |> Result.all let rec raylist_of_expr expr : (ray list, expr_err) Result.t = match expr with @@ -179,22 +184,20 @@ let rec raylist_of_expr expr : (ray list, expr_err) Result.t = | Symbol _ | Var _ -> let* ray = ray_of_expr expr in Ok [ ray ] - | List [ Symbol op; head; tail ] when String.equal op cons_op -> - let* head_ray = ray_of_expr head in - let* tail_rays = raylist_of_expr tail in + | List [ { content = Symbol op; _ }; head; tail ] when String.equal op cons_op -> + let* head_ray = ray_of_expr head.content in + let* tail_rays = raylist_of_expr tail.content in Ok (head_ray :: tail_rays) - | WithPos (e, _) -> raylist_of_expr e | invalid -> Error (InvalidRaylist (to_string invalid)) let rec star_of_expr : expr -> (Marked.star, expr_err) Result.t = function - | List [ Symbol k; s ] when equal_string k focus_op -> - let* ss = star_of_expr s in + | List [ { content = Symbol k; _ }; s ] when equal_string k focus_op -> + let* ss = star_of_expr s.content in ss |> Marked.remove |> Marked.make_state |> Result.return - | List [ Symbol k; s; List ps ] when equal_string k params_op -> - let* content = raylist_of_expr s in + | List [ { content = Symbol k; _ }; s; { content = List ps; _ } ] when equal_string k params_op -> + let* content = raylist_of_expr s.content in let* bans = bans_of_expr ps in Marked.Action { content; bans } |> Result.return - | WithPos (e, _) -> star_of_expr e | e -> let* content = raylist_of_expr e in Marked.Action { content; bans = [] } |> Result.return @@ -207,14 +210,13 @@ let rec constellation_of_expr : | Var x -> [ Marked.Action { content = [ var (x, None) ]; bans = [] } ] |> Result.return - | List [ Symbol s; h; t ] when equal_string s cons_op -> - let* sh = star_of_expr h in - let* ct = constellation_of_expr t in + | List [ { content = Symbol s; _ }; h; t ] when equal_string s cons_op -> + let* sh = star_of_expr h.content in + let* ct = constellation_of_expr t.content in Ok (sh :: ct) | List g -> let* rg = ray_of_expr (List g) in [ Marked.Action { content = [ rg ]; bans = [] } ] |> Result.return - | WithPos (e, _) -> constellation_of_expr e (* --------------------------------------- Stellogen expr of Expr @@ -227,34 +229,33 @@ let rec sgen_expr_of_expr expr : (sgen_expr, expr_err) Result.t = | Var _ | Symbol _ -> let* ray = ray_of_expr expr in Raw [ Action { content = [ ray ]; bans = [] } ] |> Result.return - | List (Symbol op :: _) when String.equal op params_op -> + | List ({ content = Symbol op; _ } :: _) when String.equal op params_op -> let* star = star_of_expr expr in Raw [ star ] |> Result.return - | List (Symbol op :: _) when String.equal op cons_op -> + | List ({ content = Symbol op; _ } :: _) when String.equal op cons_op -> let* star = star_of_expr expr in Raw [ star ] |> Result.return - | List [ Symbol op; arg ] when String.equal op call_op -> - let* ray = ray_of_expr arg in + | List [ { content = Symbol op; _ }; arg ] when String.equal op call_op -> + let* ray = ray_of_expr arg.content in Call ray |> Result.return - | List [ Symbol op; arg ] when String.equal op focus_op -> - let* sgen_expr = sgen_expr_of_expr arg in + | List [ { content = Symbol op; _ }; arg ] when String.equal op focus_op -> + let* sgen_expr = sgen_expr_of_expr arg.content in Focus sgen_expr |> Result.return - | List (Symbol op :: args) when String.equal op group_op -> - let* sgen_exprs = List.map args ~f:sgen_expr_of_expr |> Result.all in + | List ({ content = Symbol op; _ } :: args) when String.equal op group_op -> + let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in Group sgen_exprs |> Result.return - | List (Symbol "process" :: args) -> - let* sgen_exprs = List.map args ~f:sgen_expr_of_expr |> Result.all in + | List ({ content = Symbol "process"; _ } :: args) -> + let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in Process sgen_exprs |> Result.return - | List (Symbol "interact" :: args) -> - let* sgen_exprs = List.map args ~f:sgen_expr_of_expr |> Result.all in + | List ({ content = Symbol "interact"; _ } :: args) -> + let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in Exec (false, Group sgen_exprs) |> Result.return - | List (Symbol "fire" :: args) -> - let* sgen_exprs = List.map args ~f:sgen_expr_of_expr |> Result.all in + | List ({ content = Symbol "fire"; _ } :: args) -> + let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in Exec (true, Group sgen_exprs) |> Result.return - | List [ Symbol "eval"; arg ] -> - let* sgen_expr = sgen_expr_of_expr arg in + | List [ { content = Symbol "eval"; _ }; arg ] -> + let* sgen_expr = sgen_expr_of_expr arg.content in Eval sgen_expr |> Result.return - | WithPos (e, _) -> sgen_expr_of_expr e | List _ as list_expr -> let* constellation = constellation_of_expr list_expr in Raw constellation |> Result.return @@ -263,37 +264,28 @@ let rec sgen_expr_of_expr expr : (sgen_expr, expr_err) Result.t = Stellogen program of Expr --------------------------------------- *) -let rec decl_of_expr : expr -> (declaration, expr_err) Result.t = function - | WithPos (List [ Symbol op; expr1; expr2 ], loc) +let rec decl_of_expr (expr : expr loc) : (declaration, expr_err) Result.t = + match expr.content with + | List [ { content = Symbol op; _ }; expr1; expr2 ] when String.equal op expect_op -> - let* sgen_expr1 = sgen_expr_of_expr expr1 in - let* sgen_expr2 = sgen_expr_of_expr expr2 in - Expect (sgen_expr1, sgen_expr2, const "default", Some loc) |> Result.return - | WithPos (List [ Symbol op; expr1; expr2; message ], loc) + let* sgen_expr1 = sgen_expr_of_expr expr1.content in + let* sgen_expr2 = sgen_expr_of_expr expr2.content in + Expect (sgen_expr1, sgen_expr2, const "default", expr.loc) |> Result.return + | List [ { content = Symbol op; _ }; expr1; expr2; message ] when String.equal op expect_op -> - let* sgen_expr1 = sgen_expr_of_expr expr1 in - let* sgen_expr2 = sgen_expr_of_expr expr2 in - let* message_ray = ray_of_expr message in - Expect (sgen_expr1, sgen_expr2, message_ray, Some loc) |> Result.return - | WithPos (e, _) -> decl_of_expr e - | List [ Symbol op; identifier; value ] when String.equal op def_op -> - let* id_ray = ray_of_expr identifier in - let* value_expr = sgen_expr_of_expr value in + let* sgen_expr1 = sgen_expr_of_expr expr1.content in + let* sgen_expr2 = sgen_expr_of_expr expr2.content in + let* message_ray = ray_of_expr message.content in + Expect (sgen_expr1, sgen_expr2, message_ray, expr.loc) |> Result.return + | List [ { content = Symbol op; _ }; identifier; value ] when String.equal op def_op -> + let* id_ray = ray_of_expr identifier.content in + let* value_expr = sgen_expr_of_expr value.content in Def (id_ray, value_expr) |> Result.return - | List [ Symbol "show"; arg ] -> - let* sgen_expr = sgen_expr_of_expr arg in + | List [ { content = Symbol "show"; _ }; arg ] -> + let* sgen_expr = sgen_expr_of_expr arg.content in Show sgen_expr |> Result.return - | List [ Symbol op; expr1; expr2 ] when String.equal op expect_op -> - let* sgen_expr1 = sgen_expr_of_expr expr1 in - let* sgen_expr2 = sgen_expr_of_expr expr2 in - Expect (sgen_expr1, sgen_expr2, const "default", None) |> Result.return - | List [ Symbol op; expr1; expr2; message ] when String.equal op expect_op -> - let* sgen_expr1 = sgen_expr_of_expr expr1 in - let* sgen_expr2 = sgen_expr_of_expr expr2 in - let* message_ray = ray_of_expr message in - Expect (sgen_expr1, sgen_expr2, message_ray, None) |> Result.return - | List [ Symbol "use"; path ] -> - let* path_ray = ray_of_expr path in + | List [ { content = Symbol "use"; _ }; path ] -> + let* path_ray = ray_of_expr path.content in Use path_ray |> Result.return | invalid -> Error (InvalidDeclaration (to_string invalid)) diff --git a/src/sgen_eval.ml b/src/sgen_eval.ml index 71605a8..beb1e89 100644 --- a/src/sgen_eval.ml +++ b/src/sgen_eval.ml @@ -222,12 +222,12 @@ let rec eval_sgen_expr (env : env) : ^ string_of_constellation (Marked.remove_all e) ^ " is not a ray." ) ) -and expr_of_ray = function +and expr_of_ray : ray -> Expr.expr = function | Var (x, None) -> Expr.Var x | Var (x, Some i) -> Expr.Var (x ^ Int.to_string i) | Func (pf, []) -> Symbol (string_of_polsym pf) | Func (pf, args) -> - Expr.List (Symbol (string_of_polsym pf) :: List.map ~f:expr_of_ray args) + Expr.List ({ Expr.content = Symbol (string_of_polsym pf); loc = None } :: List.map ~f:(fun r -> { Expr.content = expr_of_ray r; loc = None }) args) let rec eval_decl env : declaration -> (env, err) Result.t = function | Def (identifier, expr) -> Ok { objs = add_obj env identifier expr } From d47bd2cd1aace39995aa5a60f702c63255b0125f Mon Sep 17 00:00:00 2001 From: engboris Date: Sun, 12 Oct 2025 14:58:18 +0200 Subject: [PATCH 2/3] Format --- bin/sgen.ml | 5 ++- src/expr.ml | 108 ++++++++++++++++++++++++++++++++++------------- src/sgen_eval.ml | 6 ++- 3 files changed, 86 insertions(+), 33 deletions(-) diff --git a/bin/sgen.ml b/bin/sgen.ml index decc737..8902ac4 100644 --- a/bin/sgen.ml +++ b/bin/sgen.ml @@ -104,8 +104,9 @@ let watch input_file timeout = let preprocess_only input_file = let expr = parse input_file in let preprocessed = Expr.preprocess expr in - preprocessed |> List.map ~f:(fun e -> Expr.to_string e.Expr.content) |> String.concat ~sep:"\n" - |> Stdlib.print_endline + preprocessed + |> List.map ~f:(fun e -> Expr.to_string e.Expr.content) + |> String.concat ~sep:"\n" |> Stdlib.print_endline let input_file_arg = let doc = "Input file to process." in diff --git a/src/expr.ml b/src/expr.ml index a0ce75b..bd180c5 100644 --- a/src/expr.ml +++ b/src/expr.ml @@ -8,10 +8,10 @@ let ( let* ) x f = Result.bind x ~f type ident = string (* Generic type for attaching source locations *) -type 'a loc = { - content : 'a; - loc : source_location option; -} +type 'a loc = + { content : 'a + ; loc : source_location option + } module Raw = struct type t = @@ -32,13 +32,14 @@ end type expr = | Symbol of string | Var of ident - | List of (expr loc) list + | List of expr loc list let rec equal_expr e1 e2 = match (e1, e2) with | Symbol s1, Symbol s2 -> String.equal s1 s2 | Var v1, Var v2 -> String.equal v1 v2 - | List l1, List l2 -> List.equal (fun a b -> equal_expr a.content b.content) l1 l2 + | List l1, List l2 -> + List.equal (fun a b -> equal_expr a.content b.content) l1 l2 | _ -> false let primitive = String.append "%" @@ -69,28 +70,54 @@ let rec to_string : expr -> string = function | Symbol s -> s | Var x -> x | List es -> - Printf.sprintf "(%s)" (List.map ~f:(fun e -> to_string e.content) es |> String.concat ~sep:" ") + Printf.sprintf "(%s)" + (List.map ~f:(fun e -> to_string e.content) es |> String.concat ~sep:" ") let rec expand_macro : Raw.t -> expr loc = function | Raw.Symbol s -> { content = Symbol s; loc = None } | Raw.Var x -> { content = Var x; loc = None } - | Raw.String s -> { content = List [ { content = Symbol string_op; loc = None }; { content = Symbol s; loc = None } ]; loc = None } + | Raw.String s -> + { content = + List + [ { content = Symbol string_op; loc = None } + ; { content = Symbol s; loc = None } + ] + ; loc = None + } | Raw.Call e' -> let e = expand_macro e' in - { content = List [ { content = Symbol call_op; loc = None }; e ]; loc = None } + { content = List [ { content = Symbol call_op; loc = None }; e ] + ; loc = None + } | Raw.Focus e' -> let e = expand_macro e' in - { content = List [ { content = Symbol focus_op; loc = None }; e ]; loc = None } + { content = List [ { content = Symbol focus_op; loc = None }; e ] + ; loc = None + } | Raw.Group es -> - { content = List ({ content = Symbol group_op; loc = None } :: List.map ~f:expand_macro es); loc = None } - | Raw.List es -> - { content = List (List.map ~f:expand_macro es); loc = None } + { content = + List + ( { content = Symbol group_op; loc = None } + :: List.map ~f:expand_macro es ) + ; loc = None + } + | Raw.List es -> { content = List (List.map ~f:expand_macro es); loc = None } | Raw.Cons es -> expand_macro (Raw.ConsWithBase (es, Symbol nil_op)) | Raw.ConsWithBase (es, base) -> List.fold_left es ~init:(expand_macro base) ~f:(fun acc e -> - { content = List [ { content = Symbol cons_op; loc = None }; expand_macro e; acc ]; loc = None } ) + { content = + List [ { content = Symbol cons_op; loc = None }; expand_macro e; acc ] + ; loc = None + } ) | Raw.ConsWithParams (es, ps) -> - { content = List [ { content = Symbol params_op; loc = None }; expand_macro (Cons es); expand_macro (List ps) ]; loc = None } + { content = + List + [ { content = Symbol params_op; loc = None } + ; expand_macro (Cons es) + ; expand_macro (List ps) + ] + ; loc = None + } | Raw.Stack [] -> { content = List []; loc = None } | Raw.Stack (h :: t) -> List.fold_left t ~init:(expand_macro h) ~f:(fun acc e -> @@ -109,16 +136,22 @@ let rec replace_id (var_from : ident) replacement (expr : expr loc) : expr loc = match expr.content with | Var x when String.equal x var_from -> { replacement with loc = expr.loc } | Symbol _ | Var _ -> expr - | List exprs -> { content = List (List.map exprs ~f:(replace_id var_from replacement)); loc = expr.loc } + | List exprs -> + { content = List (List.map exprs ~f:(replace_id var_from replacement)) + ; loc = expr.loc + } -let unfold_decl_def (macro_env : (string * (string list * (expr loc) list)) list) +let unfold_decl_def (macro_env : (string * (string list * expr loc list)) list) exprs = let rec process_expr (env, acc) (expr : expr loc) = match expr.content with - | List ({ content = Symbol "new-declaration"; _ } :: { content = List ({ content = Symbol macro_name; _ } :: args); _ } :: body) - -> + | List + ( { content = Symbol "new-declaration"; _ } + :: { content = List ({ content = Symbol macro_name; _ } :: args); _ } + :: body ) -> let var_args = - List.map args ~f:(fun arg -> match arg.content with + List.map args ~f:(fun arg -> + match arg.content with | Var x -> x | _ -> failwith "error: syntax declaration must contain variables" ) in @@ -142,7 +175,9 @@ let unfold_decl_def (macro_env : (string * (string list * (expr loc) list)) list | None -> (env, expr :: acc) ) | _ -> (env, expr :: acc) in - List.fold_left exprs ~init:(macro_env, []) ~f:(fun (env, acc) e -> process_expr (env, acc) e) |> snd |> List.rev + List.fold_left exprs ~init:(macro_env, []) ~f:(fun (env, acc) e -> + process_expr (env, acc) e ) + |> snd |> List.rev (* --------------------------------------- Constellation of Expr @@ -166,11 +201,13 @@ let rec ray_of_expr : expr -> (ray, expr_err) Result.t = function let bans_of_expr ban_exprs : (ban list, expr_err) Result.t = let rec ban_of_expr = function - | List [ { content = Symbol op; _ }; expr1; expr2 ] when String.equal op ineq_op -> + | List [ { content = Symbol op; _ }; expr1; expr2 ] + when String.equal op ineq_op -> let* ray1 = ray_of_expr expr1.content in let* ray2 = ray_of_expr expr2.content in Ineq (ray1, ray2) |> Result.return - | List [ { content = Symbol op; _ }; expr1; expr2 ] when String.equal op incomp_op -> + | List [ { content = Symbol op; _ }; expr1; expr2 ] + when String.equal op incomp_op -> let* ray1 = ray_of_expr expr1.content in let* ray2 = ray_of_expr expr2.content in Incomp (ray1, ray2) |> Result.return @@ -184,7 +221,8 @@ let rec raylist_of_expr expr : (ray list, expr_err) Result.t = | Symbol _ | Var _ -> let* ray = ray_of_expr expr in Ok [ ray ] - | List [ { content = Symbol op; _ }; head; tail ] when String.equal op cons_op -> + | List [ { content = Symbol op; _ }; head; tail ] when String.equal op cons_op + -> let* head_ray = ray_of_expr head.content in let* tail_rays = raylist_of_expr tail.content in Ok (head_ray :: tail_rays) @@ -194,7 +232,8 @@ let rec star_of_expr : expr -> (Marked.star, expr_err) Result.t = function | List [ { content = Symbol k; _ }; s ] when equal_string k focus_op -> let* ss = star_of_expr s.content in ss |> Marked.remove |> Marked.make_state |> Result.return - | List [ { content = Symbol k; _ }; s; { content = List ps; _ } ] when equal_string k params_op -> + | List [ { content = Symbol k; _ }; s; { content = List ps; _ } ] + when equal_string k params_op -> let* content = raylist_of_expr s.content in let* bans = bans_of_expr ps in Marked.Action { content; bans } |> Result.return @@ -242,16 +281,24 @@ let rec sgen_expr_of_expr expr : (sgen_expr, expr_err) Result.t = let* sgen_expr = sgen_expr_of_expr arg.content in Focus sgen_expr |> Result.return | List ({ content = Symbol op; _ } :: args) when String.equal op group_op -> - let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in + let* sgen_exprs = + List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all + in Group sgen_exprs |> Result.return | List ({ content = Symbol "process"; _ } :: args) -> - let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in + let* sgen_exprs = + List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all + in Process sgen_exprs |> Result.return | List ({ content = Symbol "interact"; _ } :: args) -> - let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in + let* sgen_exprs = + List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all + in Exec (false, Group sgen_exprs) |> Result.return | List ({ content = Symbol "fire"; _ } :: args) -> - let* sgen_exprs = List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all in + let* sgen_exprs = + List.map args ~f:(fun e -> sgen_expr_of_expr e.content) |> Result.all + in Exec (true, Group sgen_exprs) |> Result.return | List [ { content = Symbol "eval"; _ }; arg ] -> let* sgen_expr = sgen_expr_of_expr arg.content in @@ -277,7 +324,8 @@ let rec decl_of_expr (expr : expr loc) : (declaration, expr_err) Result.t = let* sgen_expr2 = sgen_expr_of_expr expr2.content in let* message_ray = ray_of_expr message.content in Expect (sgen_expr1, sgen_expr2, message_ray, expr.loc) |> Result.return - | List [ { content = Symbol op; _ }; identifier; value ] when String.equal op def_op -> + | List [ { content = Symbol op; _ }; identifier; value ] + when String.equal op def_op -> let* id_ray = ray_of_expr identifier.content in let* value_expr = sgen_expr_of_expr value.content in Def (id_ray, value_expr) |> Result.return diff --git a/src/sgen_eval.ml b/src/sgen_eval.ml index beb1e89..00118e3 100644 --- a/src/sgen_eval.ml +++ b/src/sgen_eval.ml @@ -227,7 +227,11 @@ and expr_of_ray : ray -> Expr.expr = function | Var (x, Some i) -> Expr.Var (x ^ Int.to_string i) | Func (pf, []) -> Symbol (string_of_polsym pf) | Func (pf, args) -> - Expr.List ({ Expr.content = Symbol (string_of_polsym pf); loc = None } :: List.map ~f:(fun r -> { Expr.content = expr_of_ray r; loc = None }) args) + Expr.List + ( { Expr.content = Symbol (string_of_polsym pf); loc = None } + :: List.map + ~f:(fun r -> { Expr.content = expr_of_ray r; loc = None }) + args ) let rec eval_decl env : declaration -> (env, err) Result.t = function | Def (identifier, expr) -> Ok { objs = add_obj env identifier expr } From 90ff93ea56f809976a583293e55a32d26fc5ca20 Mon Sep 17 00:00:00 2001 From: engboris Date: Sun, 12 Oct 2025 15:03:38 +0200 Subject: [PATCH 3/3] Update CLAUDE.md --- CLAUDE.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CLAUDE.md b/CLAUDE.md index 2388524..8224beb 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -231,6 +231,7 @@ dune test 2. Understand term unification before touching `unification.ml` 3. AST changes require updates to parser, evaluator, and pretty-printer 4. Test with existing examples in `examples/` after changes +5. **Always run `dune fmt` after finishing code modifications** to ensure consistent formatting ### Important concepts for contributors: - **Polarity** drives interaction - positive/negative rays fuse