diff --git a/src/js/index.html b/src/js/index.html index d6f4e0e2be..d40678e6c3 100644 --- a/src/js/index.html +++ b/src/js/index.html @@ -22,9 +22,9 @@ "@codemirror/state": "https://esm.sh/@codemirror/state@6.2.1", "@codemirror/language": "https://esm.sh/@codemirror/language@6.9.1", "@codemirror/view": "https://esm.sh/@codemirror/view@6.21.3", - "codemirror-lang-liquidsoap": "https://esm.sh/codemirror-lang-liquidsoap@0.2.5?external=@codemirror/state,@codemirror/language,@codemirror/view", + "codemirror-lang-liquidsoap": "https://esm.sh/codemirror-lang-liquidsoap@0.2.7?external=@codemirror/state,@codemirror/language,@codemirror/view", "prettier": "https://esm.sh/prettier@3.0.2/standalone.mjs", - "liquidsoap-prettier": "https://esm.sh/liquidsoap-prettier/src/index.js" + "liquidsoap-prettier": "https://esm.sh/liquidsoap-prettier@1.4.8/src/index.js" } } diff --git a/src/lang/parser.mly b/src/lang/parser.mly index 84fcc2d31b..56e8b9ce98 100644 --- a/src/lang/parser.mly +++ b/src/lang/parser.mly @@ -155,7 +155,7 @@ open Parser_helper %type pattern %type pattern_list %type pattern_list_with_spread -%type <(string * Parsed_term.t) list> record +%type record %type record_pattern %type record_ty %type s @@ -226,13 +226,12 @@ expr: | ENCODER encoder_opt { mk_encoder ~pos:$loc $1 $2 } | LPAR RPAR { mk ~pos:$loc (`Tuple []) } | LPAR inner_tuple RPAR { mk ~pos:$loc (`Tuple $2) } + | expr DOT LCUR record RCUR { mk ~pos:$loc (`Methods (Some $1, $4)) } | expr DOT LCUR record optional_comma RCUR - { mk ~pos:$loc (`Methods { base = `Term $1; methods = $4 }) } - | LCUR DOTDOTDOT expr RCUR { mk ~pos:$loc (`Methods { base = `Spread $3; methods = [] }) } - | LCUR record COMMA DOTDOTDOT expr RCUR - { mk ~pos:$loc (`Methods { base = `Spread $5; methods = $2 }) } - | LCUR record optional_comma RCUR { mk ~pos:$loc (`Methods { base = `None; methods = $2 }) } - | LCUR RCUR { mk ~pos:$loc (`Methods {base = `None; methods = []}) } + { mk ~pos:$loc (`Methods (Some $1, $4)) } + | LCUR record RCUR { mk ~pos:$loc (`Methods (None, $2)) } + | LCUR record optional_comma RCUR { mk ~pos:$loc (`Methods (None, $2)) } + | LCUR RCUR { mk ~pos:$loc (`Methods (None, [])) } | expr QUESTION_DOT invoke { mk ~pos:$loc (`Invoke { invoked = $1; meth = $3; optional = true }) } | expr DOT invoke { mk ~pos:$loc (`Invoke { invoked = $1; meth = $3; optional = false }) } | VARLPAR app_list RPAR { mk ~pos:$loc (`App (mk ~pos:$loc($1) (`Var $1), $2)) } @@ -583,12 +582,13 @@ plain_encoder_params: | LPAR encoder_params RPAR { $2 } optional_comma: - | {} | COMMA {} record: - | VAR GETS expr { [($1, $3)] } - | record COMMA VAR GETS expr { $1@[($3,$5)] } + | VAR GETS expr { [`Method ($1, $3)] } + | DOTDOTDOT expr { [`Ellipsis $2] } + | record COMMA VAR GETS expr { $1@[`Method ($3,$5)] } + | record COMMA DOTDOTDOT expr { $1@[`Ellipsis $4] } string_interpolation: | BEGIN_INTERPOLATION string_interpolation_elems END_INTERPOLATION { $1, $2 } diff --git a/src/lang/term/parsed_term.ml b/src/lang/term/parsed_term.ml index 8bd6abe628..ef4b7a2146 100644 --- a/src/lang/term/parsed_term.ml +++ b/src/lang/term/parsed_term.ml @@ -168,7 +168,7 @@ and parsed_ast = | `Not of t | `Get of t | `Set of t * t - | `Methods of methods + | `Methods of t option * methods list | `Negative of t | `Append of t * t | `Assoc of t * t @@ -193,11 +193,7 @@ and t = { mutable comments : (Pos.t * comment) list; } -and methods = { - base : [ `None | `Spread of t | `Term of t ]; - methods : (string * t) list; -} - +and methods = [ `Ellipsis of t | `Method of string * t ] and string_interpolation = [ `String of string | `Term of t ] and encoder_params = @@ -304,11 +300,11 @@ let rec iter_term fn ({ term } as tm) = iter_term fn tm' | `Parenthesis tm -> iter_term fn tm | `Block tm -> iter_term fn tm - | `Methods { base; methods } -> - (match base with - | `None -> () - | `Spread tm | `Term tm -> iter_term fn tm); - List.iter (fun (_, tm) -> iter_term fn tm) methods + | `Methods (base, methods) -> + (match base with None -> () | Some tm -> iter_term fn tm); + List.iter + (function `Method (_, tm) | `Ellipsis tm -> iter_term fn tm) + methods | `Int _ -> () | `Float _ -> () | `String _ -> () diff --git a/src/lang/term/term_reducer.ml b/src/lang/term/term_reducer.ml index 85623a06d7..e2455ec4a2 100644 --- a/src/lang/term/term_reducer.ml +++ b/src/lang/term/term_reducer.ml @@ -835,46 +835,46 @@ and to_term (tm : Parsed_term.t) : Term.t = | `Seq (({ term = `If_version _ } as t), t') -> concat_term (to_term t) (to_term t') | `Parenthesis tm | `Block tm -> to_term tm - | `Methods { base; methods } -> - let term, base_methods = - match base with - | `None -> (`Tuple [], Methods.empty) - | `Term tm -> - let { term; methods } = to_term tm in - (term, methods) - | `Spread tm -> - let term = to_term tm in - (* let _ = tm in let replaces _ = () in _ *) - let { term; methods } = + | `Methods (base, methods) -> + (* let _ = src in + let replaces _ = dst in + _ *) + let replace_methods ~src dst = + mk ~pos:tm.pos + (`Let + { + doc = None; + replace = false; + pat = `PVar ["_"]; + gen = []; + def = src; + body = mk ~pos:tm.pos (`Let { doc = None; - replace = false; + replace = true; pat = `PVar ["_"]; gen = []; - def = term; - body = - mk ~pos:tm.pos - (`Let - { - doc = None; - replace = true; - pat = `PVar ["_"]; - gen = []; - def = mk ~pos:tm.pos (`Tuple []); - body = mk ~pos:tm.pos (`Var "_"); - }); - }) - in - (term, methods) + def = dst; + body = mk ~pos:tm.pos (`Var "_"); + }); + }) in - let methods = - List.fold_left - (fun methods (k, v) -> Methods.add k (to_term v) methods) - base_methods methods + let term = + match base with + | None -> mk ~pos:tm.pos (`Tuple []) + | Some tm -> to_term tm in - { t = Type.var ~pos:tm.pos (); term; methods } + List.fold_left + (fun term -> function + | `Ellipsis src -> replace_methods ~src:(to_term src) term + | `Method (name, tm) -> + { + term with + methods = Methods.add name (to_term tm) term.methods; + }) + term methods | term -> let comments = List.filter_map diff --git a/src/tooling/parsed_json.ml b/src/tooling/parsed_json.ml index 7d14757904..0efc3178f4 100644 --- a/src/tooling/parsed_json.ml +++ b/src/tooling/parsed_json.ml @@ -479,13 +479,9 @@ let rec to_ast_json ~to_json = function ("optional", `Bool optional); ("meth", `Assoc (json_of_invoke_meth ~to_json meth)); ] - | `Methods { base; methods } -> + | `Methods (base, methods) -> let base, base_methods = - match base with - | `None -> (`Null, []) - | `Term t -> (to_json t, []) - | `Spread t -> - (`Null, [`Assoc (ast_node ~typ:"ellipsis" [("value", to_json t)])]) + match base with None -> (`Null, []) | Some t -> (to_json t, []) in ast_node ~typ:"methods" [ @@ -493,10 +489,13 @@ let rec to_ast_json ~to_json = function ( "methods", `Tuple (List.map - (fun (k, v) -> - `Assoc - (ast_node ~typ:"method" - [("name", `String k); ("value", to_json v)])) + (function + | `Ellipsis v -> + `Assoc (ast_node ~typ:"ellipsis" [("value", to_json v)]) + | `Method (k, v) -> + `Assoc + (ast_node ~typ:"method" + [("name", `String k); ("value", to_json v)])) methods @ base_methods) ); ] diff --git a/tests/language/record.liq b/tests/language/record.liq index 5a43ff6222..e6f08ce83d 100644 --- a/tests/language/record.liq +++ b/tests/language/record.liq @@ -275,6 +275,14 @@ def f() = y = x.{foo=123} - 3 test.equals("#{y}", "#{-2}") + x = {foo=123} + y = {gni="aabb"} + test.equals({...x, ...y}, {foo=123, gni="aabb"}) + test.equals({...x, gna=3.14, ...y}, {foo=123, bla=3.14, gni="aabb"}) + test.equals( + {...x, gna=3.14, ...y, foo="bar"}, {foo="bar", bla=3.14, gni="aabb"} + ) + test.pass() end