Repository: tweag/nickel
Pull request #327 (2021-03-11 17:13:09)

[Syntax]Use comma instead of semicolon
As proposed in https://github.com/tweag/nickel/issues/207#issuecomment-735368080 (and probably elsewhere in discussions), use comma instead of semicolon as a separator in records as well (as lists), in order to be consistent with usage (in particular JSON), and uniform in Nickel itself.

There is a one-line meaningful change in `src/grammar.lalrpop` and in `src/parser/lexer.rs`. The rest is just a mechanical search and replace to update the stdlib and tests.


Patch:
diff --git a/src/eval.rs b/src/eval.rs
index ced6d92e..564e7e72 100644
--- a/src/eval.rs
+++ b/src/eval.rs
@@ -1090,7 +1090,7 @@ mod tests {
     fn imports() {
         let mut resolver = SimpleResolver::new();
         resolver.add_source(String::from("two"), String::from("1 + 1"));
-        resolver.add_source(String::from("lib"), String::from("{ f = true }"));
+        resolver.add_source(String::from("lib"), String::from("{f = true}"));
         resolver.add_source(String::from("bad"), String::from("^$*/.23ab 0°@"));
         resolver.add_source(
             String::from("nested"),
@@ -1098,7 +1098,7 @@ mod tests {
         );
         resolver.add_source(
             String::from("cycle"),
-            String::from("let x = import \"cycle_b\" in {a = 1; b = x.a}"),
+            String::from("let x = import \"cycle_b\" in {a = 1, b = x.a}"),
         );
         resolver.add_source(
             String::from("cycle_b"),
@@ -1306,11 +1306,11 @@ mod tests {
                 .unwrap()
         );
 
-        let t = parse("switch {x => [1, glob1], y => loc2, z => {id = true; other = glob3},} loc1")
+        let t = parse("switch {x => [1, glob1], y => loc2, z => {id = true, other = glob3}} loc1")
             .unwrap();
         assert_eq!(
             subst(t, &global_env, &env),
-            parse("switch {x => [1, 1], y => (if false then 1 else \"Glob2\"), z => {id = true; other = false},} true").unwrap()
+            parse("switch {x => [1, 1], y => (if false then 1 else \"Glob2\"), z => {id = true, other = false}} true").unwrap()
         );
     }
 }
diff --git a/src/grammar.lalrpop b/src/grammar.lalrpop
index 84b7f091..293601f8 100644
--- a/src/grammar.lalrpop
+++ b/src/grammar.lalrpop
@@ -188,7 +188,7 @@ Atom: RichTerm = {
     <StrChunks>,
     Ident => RichTerm::from(Term::Var(<>)),
     "`" <Ident> => RichTerm::from(Term::Enum(<>)),
-    "{" <fields: (<RecordField> ";")*> <last: RecordField?> "}" => {
+    "{" <fields: (<RecordField> ",")*> <last: RecordField?> "}" => {
         let fields = fields.into_iter().chain(last.into_iter());
         RichTerm::from(build_record(fields))
     },
@@ -564,7 +564,6 @@ extern {
         "$" => Token::Normal(NormalToken::Dollar),
         "=" => Token::Normal(NormalToken::Equals),
         "!=" => Token::Normal(NormalToken::NotEquals),
-        ";" => Token::Normal(NormalToken::SemiCol),
         "&" => Token::Normal(NormalToken::Ampersand),
         "." => Token::Normal(NormalToken::Dot),
         "$[" => Token::Normal(NormalToken::DollarBracket),
diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs
index 45c1b5ff..ed1dac22 100644
--- a/src/parser/lexer.rs
+++ b/src/parser/lexer.rs
@@ -86,8 +86,6 @@ pub enum NormalToken<'input> {
     Equals,
     #[token("!=")]
     NotEquals,
-    #[token(";")]
-    SemiCol,
     #[token("&")]
     Ampersand,
     #[token(".")]
diff --git a/src/program.rs b/src/program.rs
index a93a0bfa..7103646d 100644
--- a/src/program.rs
+++ b/src/program.rs
@@ -264,8 +264,7 @@ mod tests {
         assert_eq!(t, *expd.term);
 
         let t = clean_pos(
-            eval_full("let x = 1 in let y = 1 + x in let z = { foo = {bar = { baz  = y } } } in z")
-                .unwrap(),
+            eval_full("let x = 1 in let y = 1 + x in let z = {foo.bar.baz = y} in z").unwrap(),
         );
         // Records are parsed as RecRecords, so we need to build one by hand
         let expd = mk_record!((
@@ -278,6 +277,6 @@ mod tests {
         // Check that substitution do not replace bound variables. Before the fixing commit, this
         // example would go into an infinite loop, and stack overflow. If it does, this just means
         // that this test fails.
-        eval_full("{y = fun x => x; x = fun y => y}").unwrap();
+        eval_full("{y = fun x => x, x = fun y => y}").unwrap();
     }
 }
diff --git a/src/serialize.rs b/src/serialize.rs
index c74176a2..7a1e8d57 100644
--- a/src/serialize.rs
+++ b/src/serialize.rs
@@ -334,7 +334,7 @@ mod tests {
     #[test]
     fn records() {
         assert_json_eq!(
-            "{a = 1; b = 2+2; c = 3; d = null}",
+            "{a = 1, b = 2+2, c = 3, d = null}",
             json!({"a": 1, "b": 4, "c": 3, "d": null})
         );
 
@@ -344,15 +344,15 @@ mod tests {
         );
 
         assert_json_eq!(
-            "{foo = let z = 0.5 + 0.5 in z; bar = [\"str\", true || false]; baz = {subfoo = !false} & {subbar = 1 - 1}}",
+            "{foo = let z = 0.5 + 0.5 in z, bar = [\"str\", true || false], baz = {subfoo = !false} & {subbar = 1 - 1}}",
             json!({"foo": 1, "bar": ["str", true], "baz": {"subfoo": true, "subbar": 0}})
         );
     }
 
     #[test]
-    fn enriched_values() {
+    fn meta_values() {
         assert_json_eq!(
-            "{a | default = 1; b | doc \"doc\" = 2+2; c = 3}",
+            "{a | default = 1, b | doc \"doc\" = 2+2, c = 3}",
             json!({"a": 1, "b": 4, "c": 3})
         );
 
@@ -369,10 +369,10 @@ mod tests {
 
     #[test]
     fn prevalidation() {
-        assert_pass_validation!(ExportFormat::Json, "{a = 1; b = { c = fun x => x }}", false);
+        assert_pass_validation!(ExportFormat::Json, "{a = 1, b = {c = fun x => x}}", false);
         assert_pass_validation!(
             ExportFormat::Json,
-            "{foo = { bar = let y = \"a\" in y}; b = [[fun x => x]] }",
+            "{foo.bar = let y = \"a\" in y, b = [[fun x => x]]}",
             false
         );
         assert_pass_validation!(ExportFormat::Json, "{foo = null}", true);
@@ -384,8 +384,6 @@ mod tests {
         assert_involutory!("{val = 1 + 1}");
         assert_involutory!("{val = \"Some string\"}");
         assert_involutory!("{val = [\"a\", 3, []]}");
-        assert_involutory!(
-            "{a = {foo = {bar = \"2\"}}; b = false; c = [{d = \"e\"}, {d = \"f\"}]}"
-        );
+        assert_involutory!("{a.foo.bar = \"2\", b = false, c = [{d = \"e\"}, {d = \"f\"}]}");
     }
 }
diff --git a/stdlib/builtins.ncl b/stdlib/builtins.ncl
index a7a1188c..27615dc1 100644
--- a/stdlib/builtins.ncl
+++ b/stdlib/builtins.ncl
@@ -1,11 +1,11 @@
 {
   builtins = {
-    isNum : Dyn -> Bool = fun x => %isNum% x;
-    isBool : Dyn -> Bool = fun x => %isBool% x;
-    isStr : Dyn -> Bool = fun x => %isStr% x;
-    isFun : Dyn -> Bool = fun x => %isFun% x;
-    isList : Dyn -> Bool = fun x => %isList% x;
-    isRecord : Dyn -> Bool = fun x => %isRecord% x;
+    isNum : Dyn -> Bool = fun x => %isNum% x,
+    isBool : Dyn -> Bool = fun x => %isBool% x,
+    isStr : Dyn -> Bool = fun x => %isStr% x,
+    isFun : Dyn -> Bool = fun x => %isFun% x,
+    isList : Dyn -> Bool = fun x => %isList% x,
+    isRecord : Dyn -> Bool = fun x => %isRecord% x,
     typeOf : Dyn -> <
       TypeNum,
       TypeBool,
@@ -20,20 +20,20 @@
       else if %isFun% x then `TypeFun
       else if %isList% x then `TypeList
       else if %isRecord% x then `TypeRecord
-      else `Other;
+      else `Other,
 
-    seq : forall a. Dyn -> a -> a = fun x y => %seq% x y;
-    deepSeq : forall a. Dyn -> a -> a = fun x y => %deepSeq% x y;
+    seq : forall a. Dyn -> a -> a = fun x y => %seq% x y,
+    deepSeq : forall a. Dyn -> a -> a = fun x y => %deepSeq% x y,
 
-    id : forall a. a -> a = fun x => x;
+    id : forall a. a -> a = fun x => x,
 
     hash : <Md5, Sha1, Sha256, Sha512> -> Str -> Str =
-      fun type s => %hash% type s;
+      fun type s => %hash% type s,
 
     serialize : <Json, Toml, Yaml> -> Dyn -> Str = fun format x =>
-      %serialize% format (%deepSeq% x x);
+      %serialize% format (%deepSeq% x x),
 
     deserialize : <Json, Toml, Yaml> -> Str -> Dyn = fun format x =>
-      %deserialize% format x;
+      %deserialize% format x,
   }
 }
diff --git a/stdlib/contracts.ncl b/stdlib/contracts.ncl
index 68ec43e5..1a952575 100644
--- a/stdlib/contracts.ncl
+++ b/stdlib/contracts.ncl
@@ -1,46 +1,46 @@
 {
-  dyn = fun l t => t;
+  dyn = fun l t => t,
 
-  num = fun l t => if %isNum% t then t else %blame% l;
+  num = fun l t => if %isNum% t then t else %blame% l,
 
-  bool = fun l t => if %isBool% t then t else %blame% l;
+  bool = fun l t => if %isBool% t then t else %blame% l,
 
-  string = fun l t => if %isStr% t then t else %blame% l;
+  string = fun l t => if %isStr% t then t else %blame% l,
 
-  list = fun elt l t => if %isList% t then %map% t (elt (%goList% l)) else %blame% l;
+  list = fun elt l t => if %isList% t then %map% t (elt (%goList% l)) else %blame% l,
 
   func = fun s t l e =>
       if %isFun% e then
           (fun x => t (%goCodom% l) (e (s (%chngPol% (%goDom% l)) x)))
       else
-          %blame% l;
+          %blame% l,
 
   forall_var = fun sy pol l t =>
       let lPol = %polarity% l in
       if pol == lPol then
           %unwrap% sy t (%blame% l)
       else
-          %wrap% sy t;
+          %wrap% sy t,
 
-  fail = fun l t => %blame% (%tag% "Fail" l);
+  fail = fun l t => %blame% (%tag% "Fail" l),
 
   row_extend = fun contr case l t =>
       if (case t) then
           t
       else
-          contr (%tag% "NotRowExt" l) t;
+          contr (%tag% "NotRowExt" l) t,
 
   record = fun cont l t =>
       if %isRecord% t then
           cont {} l t
       else
-          %blame% (%tag% "not a record" l);
+          %blame% (%tag% "not a record" l),
 
   dyn_record = fun contr l t =>
       if %isRecord% t then
           %recordMap% t (fun _field => contr l)
       else
-          %blame% (%tag% "not a record" l);
+          %blame% (%tag% "not a record" l),
 
   record_extend = fun field contr cont acc l t =>
       if %hasField% field t then
@@ -48,7 +48,7 @@
           let t = t -$ field in
           cont acc l t
       else
-          %blame% (%tag% "missing field `#{field}`" l);
+          %blame% (%tag% "missing field `#{field}`" l),
 
   forall_tail = fun sy pol acc l t =>
       let magic_fld = "_%wrapped" in
@@ -64,16 +64,16 @@
           else
               %blame% (%tag% "missing polymorphic part" l)
       else
-          acc$[magic_fld = %wrap% sy t];
+          acc$[magic_fld = %wrap% sy t],
 
-  dyn_tail = fun acc l t => acc & t;
+  dyn_tail = fun acc l t => acc & t,
 
   empty_tail = fun acc l t =>
       if t == {} then acc
-      else %blame% (%tag% "extra field `#{%head% (%fieldsOf% t)}`" l);
+      else %blame% (%tag% "extra field `#{%head% (%fieldsOf% t)}`" l),
 
   contracts = {
-    blame = fun l => %blame% l;
-    tag = fun msg l => %tag% msg l;
-  };
+    blame = fun l => %blame% l,
+    tag = fun msg l => %tag% msg l,
+  },
 }
diff --git a/stdlib/lists.ncl b/stdlib/lists.ncl
index 0ad2c076..d3ec025a 100644
--- a/stdlib/lists.ncl
+++ b/stdlib/lists.ncl
@@ -1,16 +1,16 @@
 {
   lists = {
-    head : forall a. List a -> a = fun l => %head% l;
+    head : forall a. List a -> a = fun l => %head% l,
 
-    tail : forall a. List a -> List a = fun l => %tail% l;
+    tail : forall a. List a -> List a = fun l => %tail% l,
 
-    length : forall a. List a -> Num = fun l => %length% l;
+    length : forall a. List a -> Num = fun l => %length% l,
 
-    map : forall a b. (a -> b) -> List a -> List b = fun f l => %map% l f;
+    map : forall a b. (a -> b) -> List a -> List b = fun f l => %map% l f,
 
-    elemAt : forall a. List a -> Num -> a = fun l n => %elemAt% l n;
+    elemAt : forall a. List a -> Num -> a = fun l n => %elemAt% l n,
 
-    concat : forall a. List a -> List a -> List a = fun l1 l2 => l1 @ l2;
+    concat : forall a. List a -> List a -> List a = fun l1 l2 => l1 @ l2,
 
     foldl : forall a b. (a -> b -> a) -> a -> List b -> a =
       fun f fst l =>
@@ -18,33 +18,33 @@
           fst
         else
           let rest = foldl f fst (%tail% l) in
-          %seq% rest (f rest (%head% l));
+          %seq% rest (f rest (%head% l)),
 
     fold : forall a b. (a -> b -> b) -> List a -> b -> b =
       fun f l fst =>
         if %length% l == 0 then
           fst
         else
-          f (%head% l) (fold f (%tail% l) fst);
+          f (%head% l) (fold f (%tail% l) fst),
 
-    cons : forall a. a -> List a -> List a = fun x l => [x] @ l;
+    cons : forall a. a -> List a -> List a = fun x l => [x] @ l,
 
     filter : forall a. (a -> Bool) -> List a -> List a =
       fun pred l =>
-        fold (fun x acc => if pred x then acc @ [x] else acc) l [];
+        fold (fun x acc => if pred x then acc @ [x] else acc) l [],
 
     //TODO: this enforces a List contract at each iteration. Get rid of it once
     //parametrized list types lands and `fold` get a more precise type.
     flatten : forall a. List (List a) -> List a =
       fun l =>
-        fold (fun l acc => l @ acc) l [];
+        fold (fun l acc => l @ acc) l [],
 
     all : forall a. (a -> Bool) -> List a -> Bool =
       fun pred l =>
-        fold (fun x acc => if pred x then acc else false) l true;
+        fold (fun x acc => if pred x then acc else false) l true,
 
     any : forall a. (a -> Bool) -> List a -> Bool =
       fun pred l =>
-        fold (fun x acc => if pred x then true else acc) l false;
+        fold (fun x acc => if pred x then true else acc) l false,
   }
 }
diff --git a/stdlib/records.ncl b/stdlib/records.ncl
index 8349657c..42b850c8 100644
--- a/stdlib/records.ncl
+++ b/stdlib/records.ncl
@@ -1,10 +1,10 @@
 {
   records = {
-    map : forall a b. (Str -> a -> b) -> {_: a} -> {_: b} = fun f r => %recordMap% r f;
+    map : forall a b. (Str -> a -> b) -> {_: a} -> {_: b} = fun f r => %recordMap% r f,
 
     // TODO: change Dyn to { | Dyn} once the PR introducing open contracts lands
-    fieldsOf : Dyn -> List Str = fun r => %fieldsOf% r;
+    fieldsOf : Dyn -> List Str = fun r => %fieldsOf% r,
 
-    hasField : Str -> Dyn -> Bool = fun r field => %hasField% r field;
+    hasField : Str -> Dyn -> Bool = fun r field => %hasField% r field,
   }
 }


Test patch:
diff --git a/src/parser/tests.rs b/src/parser/tests.rs
index c4f8695e..d9c0e39d 100644
--- a/src/parser/tests.rs
+++ b/src/parser/tests.rs
@@ -163,7 +163,7 @@ fn enum_terms() {
 #[test]
 fn record_terms() {
     assert_eq!(
-        parse_without_pos("{ a = 1; b = 2; c = 3;}"),
+        parse_without_pos("{ a = 1, b = 2, c = 3}"),
         RecRecord(
             vec![
                 (Ident::from("a"), Num(1.).into()),
@@ -177,7 +177,7 @@ fn record_terms() {
     );
 
     assert_eq!(
-        parse_without_pos("{ a = 1; \"#{123}\" = (if 4 then 5 else 6); d = 42;}"),
+        parse_without_pos("{ a = 1, \"#{123}\" = (if 4 then 5 else 6), d = 42}"),
         mk_app!(
             mk_term::op2(
                 BinaryOp::DynExtend(),
@@ -336,7 +336,7 @@ fn line_comments() {
     assert_eq!(
         parse_without_pos(
             "{ // Some comment
-            field = foo; // Some description
+            field = foo, // Some description
             } // Some other"
         ),
         parse_without_pos("{field = foo}")
diff --git a/tests/contracts_fail.rs b/tests/contracts_fail.rs
index dd3e4084..23258e22 100644
--- a/tests/contracts_fail.rs
+++ b/tests/contracts_fail.rs
@@ -60,7 +60,7 @@ fn merge_compose_contract() {
             "let Even = fun l x => if x % 2 == 0 then x else %blame% l in
         let DivBy3 = fun l x => if x % 3 ==  0 then x else %blame% l in
         let composed = {{a | #Even}} & {{a | #DivBy3}} in
-        (({{a = {};}}) & composed).a",
+        (({{a = {},}}) & composed).a",
             arg
         )
     };
@@ -76,21 +76,21 @@ fn merge_compose_contract() {
 fn records_contracts_simple() {
     assert_raise_blame!("{a=1} | {}");
 
-    assert_raise_blame!("let x | {a: Num, s: Str} = {a = 1; s = 2} in %deepSeq% x x");
-    assert_raise_blame!("let x | {a: Num, s: Str} = {a = \"a\"; s = \"b\"} in %deepSeq% x x");
+    assert_raise_blame!("let x | {a: Num, s: Str} = {a = 1, s = 2} in %deepSeq% x x");
+    assert_raise_blame!("let x | {a: Num, s: Str} = {a = \"a\", s = \"b\"} in %deepSeq% x x");
     assert_raise_blame!("let x | {a: Num, s: Str} = {a = 1} in %deepSeq% x x");
     assert_raise_blame!("let x | {a: Num, s: Str} = {s = \"a\"} in %deepSeq% x x");
     assert_raise_blame!(
-        "let x | {a: Num, s: Str} = {a = 1; s = \"a\"; extra = 1} in %deepSeq% x x"
+        "let x | {a: Num, s: Str} = {a = 1, s = \"a\", extra = 1} in %deepSeq% x x"
     );
 
     assert_raise_blame!(
-        "let x | {a: Num, s: {foo: Bool}} = {a = 1; s = {foo = 2}} in %deepSeq% x x"
+        "let x | {a: Num, s: {foo: Bool}} = {a = 1, s = {foo = 2}} in %deepSeq% x x"
     );
     assert_raise_blame!(
-        "let x | {a: Num, s: {foo: Bool}} = {a = 1; s = {foo = true; extra = 1}} in %deepSeq% x x"
+        "let x | {a: Num, s: {foo: Bool}} = {a = 1, s = {foo = true, extra = 1}} in %deepSeq% x x"
     );
-    assert_raise_blame!("let x | {a: Num, s: {foo: Bool}} = {a = 1; s = {}} in %deepSeq% x x");
+    assert_raise_blame!("let x | {a: Num, s: {foo: Bool}} = {a = 1, s = {}} in %deepSeq% x x");
 }
 
 #[test]
@@ -103,7 +103,7 @@ fn records_contracts_poly() {
     assert_raise_blame!(&format!("{} {{}}", remv));
 
     let bad_cst = "let f | forall a. { | a} -> { | a} = fun x => {a=1} in f";
-    let bad_acc = "let f | forall a. { | a} -> { | a} = fun x => %seq% (x.a) x in f";
+    let bad_acc = "let f | forall a. { | a} -> { | a} = fun x => %seq% x.a x in f";
     let bad_extd = "let f | forall a. { | a} -> {foo: Num | a} = fun x => x-$\"foo\" in f";
     let bad_rmv = "let f | forall a. {foo: Num | a} -> { | a} = fun x => x$[\"foo\"=1] in f";
 
@@ -126,7 +126,7 @@ fn records_contracts_poly() {
                 -> {a: Num | a}
                 -> { | a}
             = fun f rec => (f rec) -$ \"a\" -$ \"b\" in
-        f (fun x => x) {a = 1; b = true; c = 3}"
+        f (fun x => x) {a = 1, b = true, c = 3}"
     );
 }
 
diff --git a/tests/infinite_rec.rs b/tests/infinite_rec.rs
index 0216de3d..c1ac5995 100644
--- a/tests/infinite_rec.rs
+++ b/tests/infinite_rec.rs
@@ -11,15 +11,15 @@ fn infinite_loops() {
         Err(Error::EvalError(EvalError::InfiniteRecursion(..)))
     );
     assert_matches!(
-        eval("{x = y; y = z; z = x }.x"),
+        eval("{x = y, y = z, z = x }.x"),
         Err(Error::EvalError(EvalError::InfiniteRecursion(..)))
     );
     assert_matches!(
-        eval("{x = y + z; y = z + x; z = 1}.x"),
+        eval("{x = y + z, y = z + x, z = 1}.x"),
         Err(Error::EvalError(EvalError::InfiniteRecursion(..)))
     );
     assert_matches!(
-        eval("{x = (fun a => a + y) 0; y = (fun a => a + x) 0}.x"),
+        eval("{x = (fun a => a + y) 0, y = (fun a => a + x) 0}.x"),
         Err(Error::EvalError(EvalError::InfiniteRecursion(..)))
     );
 }
diff --git a/tests/pass/builtins.ncl b/tests/pass/builtins.ncl
index 3795a036..1e2bac24 100644
--- a/tests/pass/builtins.ncl
+++ b/tests/pass/builtins.ncl
@@ -7,16 +7,16 @@ let Assert = fun l x => x || %blame% l in
 /// just that the evaluation succeeds
 (%seq% 1 true | #Assert) &&
 (let x = (1 + 1) in %seq% x x == 2 | #Assert) &&
-(let r = {a=(1 + 1);} in
+(let r = {a=(1 + 1),} in
   %deepSeq% r (r.a) == 2 | #Assert) &&
-(let r = {a=(1 + 1);b=("a" ++ "b");} in
+(let r = {a=(1 + 1),b=("a" ++ "b"),} in
   %deepSeq% r (r.b) == "ab" | #Assert) &&
 (let r = {a = {b = 1 + 1}} in
   %deepSeq% r (r.a.b) == 2 | #Assert) &&
 
 (let inj = fun x => {b=(x + 2)} in
   let cat = fun x => fun y => x ++ y in
-  let r = {a=(inj 1);b=(cat "a" "b")} in
+  let r = {a=(inj 1),b=(cat "a" "b")} in
   %deepSeq% r (r.a.b) == 3 | #Assert) &&
 
 true
diff --git a/tests/pass/contracts.ncl b/tests/pass/contracts.ncl
index 53980e8f..3cea5432 100644
--- a/tests/pass/contracts.ncl
+++ b/tests/pass/contracts.ncl
@@ -41,12 +41,12 @@ f `boo == 3) &&
 
 // records_simple
 (({} | {}) == {} | #Assert) &&
-(let x | {a: Num, s: Str} = {a = 1; s = "a"} in
-  %deepSeq% x x == {a = 1; s = "a"}
+(let x | {a: Num, s: Str} = {a = 1, s = "a"} in
+  %deepSeq% x x == {a = 1, s = "a"}
   | #Assert) &&
 
-(let x | {a: Num, s: {foo: Bool}} = {a = 1; s = { foo = true}} in
-  %deepSeq% x x == {a = 1; s = { foo = true}}
+(let x | {a: Num, s: {foo: Bool}} = {a = 1, s = { foo = true}} in
+  %deepSeq% x x == {a = 1, s = { foo = true}}
   | #Assert) &&
 
 // polymorphism
@@ -57,27 +57,27 @@ f `boo == 3) &&
     x -$ "foo" in
 
   (id {} == {} | #Assert) &&
-  (id {a = 1; b = false} == {a = 1; b = false} | #Assert) &&
+  (id {a = 1, b = false} == {a = 1, b = false} | #Assert) &&
   (extend {} == {foo = 1} | #Assert) &&
-  (extend {bar = false} == {foo = 1; bar = false} | #Assert) &&
+  (extend {bar = false} == {foo = 1, bar = false} | #Assert) &&
   (remove {foo = 1} == {} | #Assert) &&
-  (remove {foo = 1; bar = 1} == {bar = 1} | #Assert) &&
+  (remove {foo = 1, bar = 1} == {bar = 1} | #Assert) &&
   (remove (extend {}) == {} | #Assert) &&
   (extend (remove {foo = 2}) == {foo =1} | #Assert) &&
   (let f | forall a b. {f: a -> a, arg: a | b} -> a =
       fun rec => rec.f (rec.arg) in
-    f { f = fun x => x ++ " suffix"; arg = "foo" }
+    f { f = fun x => x ++ " suffix", arg = "foo" }
     == "foo suffix"
     | #Assert)
 ) &&
 
 // records_dynamic_tail
-(({a = 1; b = "b"} | {a: Num, b: Str | Dyn}) == {a = 1; b = "b"}
+(({a = 1, b = "b"} | {a: Num, b: Str | Dyn}) == {a = 1, b = "b"}
   | #Assert) &&
-(({a = 1; b = "b"; c = false} | {a: Num, b: Str | Dyn})
-  == {a = 1; b = "b"; c = false}
+(({a = 1, b = "b", c = false} | {a: Num, b: Str | Dyn})
+  == {a = 1, b = "b", c = false}
   | #Assert) &&
-((fun r => r.b | {a: Num | Dyn} -> Dyn) {a = 1; b = 2} == 2
+((fun r => r.b | {a: Num | Dyn} -> Dyn) {a = 1, b = 2} == 2
   | #Assert) &&
 
 
diff --git a/tests/pass/eq.ncl b/tests/pass/eq.ncl
index da314768..b605e992 100644
--- a/tests/pass/eq.ncl
+++ b/tests/pass/eq.ncl
@@ -36,30 +36,30 @@ let Assert = fun l x => x || %blame% l in
 // records
 ({} == {} | #Assert) &&
 ({}$["a" = 1]$["b" = true]
-  == {a = 1; b = true}
+  == {a = 1, b = true}
   | #Assert) &&
-({a = 1 + 0; b = 1 + 1; c = 1 + 1 + 1}
-  == { a = 1; b = 2; c = 3 }
+({a = 1 + 0, b = 1 + 1, c = 1 + 1 + 1}
+  == { a = 1, b = 2, c = 3 }
   | #Assert) &&
 ({
-    foo = 1 + 0;
-    bar = "a" ++ "b";
+    foo = 1 + 0,
+    bar = "a" ++ "b",
     baz = if true then true else false
-  } == {foo = 1; bar = "ab"; baz = true}
+  } == {foo = 1, bar = "ab", baz = true}
   | #Assert) &&
 
 ({}$["a" = { a = { a = {} } }]
   == { a = { a = { a = {} } } }
   | #Assert) &&
 ({
-    foo = {bar = 2 + (-1)};
+    foo = {bar = 2 + (-1)},
     baz = {foo = {bar = 1 + 1}}
   }
-  == {foo = {bar = 1}; baz = {foo = {bar = 2}}}
+  == {foo = {bar = 1}, baz = {foo = {bar = 2}}}
   | #Assert) &&
 ({} != {a = true} | #Assert) &&
 ({a = 1} != {a = 2} | #Assert) &&
-({ a = "a"; b = true } != { a = true; b = "a"} | #Assert) &&
+({ a = "a", b = true } != { a = true, b = "a"} | #Assert) &&
 ({ a = { a = true } } != {a = { a = { a = true } } } | #Assert) &&
 
 // Now that the equality operator directly uses the stack to store its continuation (see
@@ -71,8 +71,8 @@ let Assert = fun l x => x || %blame% l in
       if b then true else false in
     not (not (not (not ((x) == (y))))) in
   (eq_with_ctxt
-      {a = 1 + 0; b = 1 + 1 + a; c = 0; d = 0}
-      { a = 1; b = 3; c = 0; d = 0}
+      {a = 1 + 0, b = 1 + 1 + a, c = 0, d = 0}
+      { a = 1, b = 3, c = 0, d = 0}
     | #Assert) &&
   (eq_with_ctxt
       [[1,2,3,4], [1,0,3,4], [1,2,3,4], [1,2,3,4]]
diff --git a/tests/pass/metavalues.ncl b/tests/pass/metavalues.ncl
index 39a5b4fe..4bd158aa 100644
--- a/tests/pass/metavalues.ncl
+++ b/tests/pass/metavalues.ncl
@@ -8,23 +8,23 @@ let Assert = fun l x => x || %blame% l in
   builtins.seq (x.a) ((x & {a=2}).a) == 2 | #Assert) &&
 
 // merge_default
-(({a = 2} & {a | default = 0; b | default = true}) == {a = 2; b = true}
+(({a = 2} & {a | default = 0, b | default = true}) == {a = 2, b = true}
   | #Assert) &&
-({a | default = {x = 1}} & {a | default = {y = "y"}} == {a = {x = 1; y = "y"}}
+({a | default = {x = 1}} & {a | default = {y = "y"}} == {a = {x = 1, y = "y"}}
   | #Assert) &&
 
 // merge_contract
-({a = 2; b | Bool} & {a | Num; b | default = true}
-  == {a = 2; b = true}
+({a = 2, b | Bool} & {a | Num, b | default = true}
+  == {a = 2, b = true}
   | #Assert) &&
 
 // merge_default_contract
-({a = 2} & {a | default | Num = 0; b | default = true}
-  == {a = 2; b = true}
+({a = 2} & {a | default | Num = 0, b | default = true}
+  == {a = 2, b = true}
   | #Assert) &&
 
 ({a=2} & {a | Num} & {a | default = 3} == {a = 2} | #Assert) &&
-({a=2} & {b | Num} & {b | default = 3} == {a = 2; b = 3} | #Assert) &&
+({a=2} & {b | Num} & {b | default = 3} == {a = 2, b = 3} | #Assert) &&
 (({a | default = 1} & {b | Num} & {a | default = 1}).a
   == 1
   | #Assert) &&
diff --git a/tests/pass/records.ncl b/tests/pass/records.ncl
index c4c1e437..ec728c10 100644
--- a/tests/pass/records.ncl
+++ b/tests/pass/records.ncl
@@ -1,13 +1,13 @@
 let Assert = fun l x => x || %blame% l in
 
 // accesses
-(({foo = 3; bar = true}).bar == true | #Assert) &&
-({"#{if true then "foo" else "bar"}" = false; bar = true}.foo
+(({foo = 3, bar = true}).bar == true | #Assert) &&
+({"#{if true then "foo" else "bar"}" = false, bar = true}.foo
   == false
   | #Assert) &&
 
-(({foo = 3; bar = true})."bar" == true | #Assert) &&
-({"#{if true then "foo" else "bar"}" = false; bar = true}."#{"foo"}"
+(({foo = 3, bar = true})."bar" == true | #Assert) &&
+({"#{if true then "foo" else "bar"}" = false, bar = true}."#{"foo"}"
  == false 
  | #Assert) &&
 
@@ -15,67 +15,67 @@ let Assert = fun l x => x || %blame% l in
   | #Assert) &&
 
 // primitive_ops
-(records.hasField "foo" {foo = 1; bar = 2} | #Assert) &&
-(records.hasField "fop" {foo = 1; bar = 2} == false | #Assert) &&
-(records.hasField "foo" ({foo = 2; bar = 3} -$ "foo")
+(records.hasField "foo" {foo = 1, bar = 2} | #Assert) &&
+(records.hasField "fop" {foo = 1, bar = 2} == false | #Assert) &&
+(records.hasField "foo" ({foo = 2, bar = 3} -$ "foo")
   == false
   | #Assert) &&
 
 (records.hasField "foo" ({bar = 3}$["foo" = 1]) | #Assert) &&
 
 // lazyness of map
-((records.map (fun x y => y + 1) {foo = 1; bar = "it's lazy"}).foo
+((records.map (fun x y => y + 1) {foo = 1, bar = "it's lazy"}).foo
   == 2
   | #Assert) &&
 
 (let r = records.map
     (fun y x => if %isNum% x then x + 1 else 0)
-    {foo = 1; bar = "it's lazy"} in
+    {foo = 1, bar = "it's lazy"} in
   (r.foo) + (r.bar) == 2
   | #Assert) &&
 
 // merging
-({a = 1} & {b=true} == {a = 1; b = true} | #Assert) &&
-({a = 1; b = 2} & {b = 2; c = 3}
-  == {a = 1; b = 2; c = 3}
+({a = 1} & {b=true} == {a = 1, b = true} | #Assert) &&
+({a = 1, b = 2} & {b = 2, c = 3}
+  == {a = 1, b = 2, c = 3}
   | #Assert) &&
 
 ({a = {b = 1}} & {a = {c = true}}
-  == {a = {b = 1; c = true}}
+  == {a = {b = 1, c = true}}
   | #Assert) &&
 
 // merge_complex
 (let rec1 = {
-    a = false;
-    b = if true then (1 + 1) else (2 + 0);
-    c= ((fun x => x) (fun y => y)) 2;
+    a = false,
+    b = if true then (1 + 1) else (2 + 0),
+    c= ((fun x => x) (fun y => y)) 2,
   } in
   let rec2 = {
-    b = ((fun x => x) (fun y => y)) 2;
-    c = if true then (1 + 1) else (2 + 0);
-    d = true;
+    b = ((fun x => x) (fun y => y)) 2,
+    c = if true then (1 + 1) else (2 + 0),
+    d = true,
   } in
   let result = {
-    a = false;
-    b = 2;
-    c = 2;
-    d = true;
+    a = false,
+    b = 2,
+    c = 2,
+    d = true,
   } in
   rec1 & rec2 == result
   | #Assert) &&
 
 // merge_with_env
 ((fun y => ((fun x => {a=y}) 1) & ({b=false})) 2
-  == {a = 2; b = false}
+  == {a = 2, b = false}
   | #Assert) &&
 
 // merge_with_env_nested
-({b={c=10}} & ((fun x => {a=x; b={c=x}}) 10)
-  == {a=10; b = {c = 10}}
+({b={c=10}} & ((fun x => {a=x, b={c=x}}) 10)
+  == {a=10, b = {c = 10}}
   | #Assert) &&
 
 // recursive_records
-({a = 1; b = a + 1; c = b + a} == {a = 1; b = 2; c = 3} | #Assert) &&
+({a = 1, b = a + 1, c = b + a} == {a = 1, b = 2, c = 3} | #Assert) &&
 ({f = fun x y =>
     if x == 0 then y else f (x + (-1)) (y + 1)
   }.f 5 5
@@ -87,7 +87,7 @@ let Assert = fun l x => x || %blame% l in
     f = fun x =>
       if x == 0 then
         res
-      else g x;
+      else g x,
     g = fun y => f (y + (-1))
   }.f 10 in
   with_res "done" == "done"
diff --git a/tests/pass/serialize.ncl b/tests/pass/serialize.ncl
index 54cbfc79..bca17a1e 100644
--- a/tests/pass/serialize.ncl
+++ b/tests/pass/serialize.ncl
@@ -18,15 +18,15 @@ let assertDeserInv = fun x =>
 (assertSerInv {val = 1 + 1} | #Assert) &&
 (assertSerInv {val = "Some string"} | #Assert) &&
 (assertSerInv {val = ["a", 3, []]} | #Assert) &&
-(assertSerInv {a.foo.bar = "2"; b = false; c = [{d = "e"}, {d = "f"}]}
+(assertSerInv {a.foo.bar = "2", b = false, c = [{d = "e"}, {d = "f"}]}
   | #Assert) &&
 
-(assertDeserInv {a = 1; b = 4; c = 3} | #Assert) &&
+(assertDeserInv {a = 1, b = 4, c = 3} | #Assert) &&
 (assertDeserInv {a.b.c = "richtig"} | #Assert) &&
 (assertDeserInv {
-    foo = 1;
-    bar = ["str", true];
-    baz = {subfoo = true; subbar = 0}
+    foo = 1,
+    bar = ["str", true],
+    baz = {subfoo = true, subbar = 0}
   } | #Assert) &&
 
 
diff --git a/tests/pass/typechecking.ncl b/tests/pass/typechecking.ncl
index 24fa3f8f..b0264fa0 100644
--- a/tests/pass/typechecking.ncl
+++ b/tests/pass/typechecking.ncl
@@ -76,22 +76,22 @@ let typecheck = [
 
   // static records
   ({bla = 1} : {bla : Num}),
-  ({blo = true; bla = 1} : {bla : Num, blo : Bool}),
+  ({blo = true, bla = 1} : {bla : Num, blo : Bool}),
   ({blo = 1}.blo : Num),
-  ({bla = true; blo = 1}.blo : Num),
-  let r : {bla : Bool, blo : Num} = {blo = 1; bla = true} in
+  ({bla = true, blo = 1}.blo : Num),
+  let r : {bla : Bool, blo : Num} = {blo = 1, bla = true} in
     ((if r.bla then r.blo else 2) : Num),
 
   let f : forall a. (forall r. {bla : Bool, blo : a, ble : a | r} -> a) =
       fun r => if r.bla then r.blo else r.ble in
-    (if (f {bla = true; blo = false; ble = true; blip = 1; }) then
-      (f {bla = true; blo = 1; ble = 2; blip = `blip; })
+    (if (f {bla = true, blo = false, ble = true, blip = 1, }) then
+      (f {bla = true, blo = 1, ble = 2, blip = `blip, })
     else
-      (f {bla = true; blo = 3; ble = 4; bloppo = `bloppop; }) : Num),
+      (f {bla = true, blo = 3, ble = 4, bloppo = `bloppop, }) : Num),
 
-  ({ "#{if true then "foo" else "bar"}" = 2; } : {_ : Num}),
-  ({ "#{if true then "foo" else "bar"}" = 2; }."bla" : Num),
-  ({ foo = 3; bar = 4; } : {_ : Num}),
+  ({ "#{if true then "foo" else "bar"}" = 2, } : {_ : Num}),
+  ({ "#{if true then "foo" else "bar"}" = 2, }."bla" : Num),
+  ({ foo = 3, bar = 4, } : {_ : Num}),
 
   // seq
   (%seq% false 1 : Num),
@@ -115,18 +115,18 @@ let typecheck = [
   fun i l => %elemAt% l i : forall a. Num -> List a -> a,
 
   // recursive_records
-  {a : Num = 1; b = a + 1} : {a : Num, b : Num},
+  {a : Num = 1, b = a + 1} : {a : Num, b : Num},
   {a : Num = 1 + a} : {a : Num},
   {a : Num = 1 + a} : {a : Num},
 
   // let_inference
   (let x = 1 + 2 in let f = fun x => x + 1 in f x) : Num, 
   // (let x = 1 + 2 in let f = fun x => x ++ "a" in f x) : Num,
-  {a = 1; b = 1 + a} : {a : Num, b : Num},
-  {f = fun x => if x == 0 then 1 else 1 + (f (x + (-1)));}
+  {a = 1, b = 1 + a} : {a : Num, b : Num},
+  {f = fun x => if x == 0 then 1 else 1 + (f (x + (-1))),}
     : {f : Num -> Num},
 
-  { f = fun x => if x == 0 then 1 else 1 + (f (x + (-1)));}
+  { f = fun x => if x == 0 then 1 else 1 + (f (x + (-1))),}
     : {f : Num -> Num},
 
   // polymorphic_row_constraints
@@ -134,8 +134,8 @@ let typecheck = [
     let remove | forall c. {a: Str | c} -> { | c} = 0 in
     (let good = remove (extend {}) in 0) : Num,
 
-  let r | {a: Num | Dyn} = {a = 1; b = 2} in (r.a : Num),
-  ({a = 1; b = 2} | {a: Num | Dyn}) : {a: Num | Dyn},
+  let r | {a: Num | Dyn} = {a = 1, b = 2} in (r.a : Num),
+  ({a = 1, b = 2} | {a: Num | Dyn}) : {a: Num | Dyn},
 
   //Regression test following [#270](https://github.com/tweag/nickel/issues/270). Check that
   //unifying a variable with itself doesn't introduce a loop. The failure of this test results
diff --git a/tests/records_fail.rs b/tests/records_fail.rs
index fc608f1b..59655ee5 100644
--- a/tests/records_fail.rs
+++ b/tests/records_fail.rs
@@ -11,7 +11,7 @@ fn records_access() {
         Err(Error::EvalError(EvalError::FieldMissing(..)))
     );
     assert_matches!(
-        eval("({ \"#{(if false then \"foo\" else \"bar\")}\" = false; bar = true; }).foo"),
+        eval("({ \"#{(if false then \"foo\" else \"bar\")}\" = false, bar = true, }).foo"),
         Err(Error::EvalError(EvalError::Other(msg, ..))) if msg.starts_with("$[ .. ]"));
 }
 
@@ -22,7 +22,7 @@ fn non_mergeable() {
         Err(Error::EvalError(EvalError::MergeIncompatibleArgs(..)))
     );
     assert_matches!(
-        eval("({a | default = false;} & {a | default = true}).a"),
+        eval("({a | default = false} & {a | default = true}).a"),
         Err(Error::EvalError(EvalError::MergeIncompatibleArgs(..)))
     );
     assert_matches!(
diff --git a/tests/typecheck_fail.rs b/tests/typecheck_fail.rs
index 01146aba..a7284081 100644
--- a/tests/typecheck_fail.rs
+++ b/tests/typecheck_fail.rs
@@ -119,19 +119,19 @@ fn static_record_simple() {
     assert_typecheck_fails!(
         "let f : forall a. (forall r. {bla : Bool, blo : a, ble : a | r} -> a) =
             fun r => if r.bla then r.blo else r.ble in
-         (f {bla = true; blo = 1; ble = true; blip = `blip} : Num)"
+         (f {bla = true, blo = 1, ble = true, blip = `blip} : Num)"
     );
     assert_typecheck_fails!(
         "let f : forall a. (forall r. {bla : Bool, blo : a, ble : a | r} -> a) =
             fun r => if r.bla then (r.blo + 1) else r.ble in
-         (f {bla = true; blo = 1; ble = 2; blip = `blip} : Num)"
+         (f {bla = true, blo = 1, ble = 2, blip = `blip} : Num)"
     );
 }
 
 #[test]
 fn dynamic_record_simple() {
     assert_typecheck_fails!(
-        "({ \"#{if true then \"foo\" else \"bar\"}\" = 2; \"foo\" = true; }.\"bla\") : Num"
+        "({ \"#{if true then \"foo\" else \"bar\"}\" = 2, \"foo\" = true, }.\"bla\") : Num"
     );
 }
 
@@ -186,8 +186,8 @@ fn imports() {
 
 #[test]
 fn recursive_records() {
-    assert_typecheck_fails!("{a : Num = true; b = a + 1} : {a : Num, b : Num}");
-    assert_typecheck_fails!("{a = 1; b : Bool = a} : {a : Num, b : Bool}");
+    assert_typecheck_fails!("{a : Num = true, b = a + 1} : {a : Num, b : Num}");
+    assert_typecheck_fails!("{a = 1, b : Bool = a} : {a : Num, b : Bool}");
 }
 
 #[test]
@@ -223,7 +223,7 @@ fn polymorphic_row_constraints() {
 
     let mut res = type_check_expr(
         "let extend | forall c. { | c} -> {a: Str | c} = null in
-           (let bad = extend {a = 1;} in 0) : Num",
+           (let bad = extend {a = 1} in 0) : Num",
     );
     assert_row_conflict(res);
 
@@ -238,7 +238,7 @@ fn polymorphic_row_constraints() {
 fn dynamic_row_tail() {
     // Currently, typechecking is conservative wrt the dynamic row type, meaning it can't
     // convert to a less precise type with a dynamic tail.
-    assert_typecheck_fails!("{a = 1; b = 2} : {a: Num | Dyn}");
+    assert_typecheck_fails!("{a = 1, b = 2} : {a: Num | Dyn}");
     assert_typecheck_fails!("{a = 1} : {a: Num | Dyn}");
     assert_typecheck_fails!("({a = 1} | {a: Num | Dyn}) : {a: Num}");
     assert_typecheck_fails!("{a = 1} : {a: Num | Dyn}");