Repository: tweag/nickel
Pull request #634 (2022-03-03 14:56:39)

Syntax/hashtag for comment
now use `#` for comments
relate to #295 


Patch:
diff --git a/doc/manual/contracts.md b/doc/manual/contracts.md
index 5db59533..100e5e3d 100644
--- a/doc/manual/contracts.md
+++ b/doc/manual/contracts.md
@@ -15,10 +15,10 @@ let x = (1 + 1 | Num) in x
 Contract can also be attached to identifiers in a definition:
 
 ```nickel
-// let-binding: equivalent to the previous example
+# let-binding: equivalent to the previous example
 let x | Num = 1 + 1 in x
 
-// on a record field
+# on a record field
 {x | Num = 1 + 1}
 ```
 
@@ -165,7 +165,7 @@ let Between = fun min max =>
   contract.from_predicate (fun value =>
     value >= min &&
     value <= max) in
-// alternative without from_predicate
+# alternative without from_predicate
 let BetweenAlt = fun min max label value =>
   if builtin.is_num value &&
      value >= min &&
@@ -197,9 +197,9 @@ let Nullable = fun contract label value =>
     value 
   else
     contract.apply contract label value in
-// succeeds
+# succeeds
 null | Nullable Num
-// succeeds too
+# succeeds too
 1 | Nullable Num
 ```
 
@@ -580,7 +580,7 @@ let NumBoolDict = fun label value =>
       |> record.fields
       |> array.foldl (fun acc field_name =>
         if string.is_match "^\\d+$" field_name then
-          acc // unused and always null through iteration
+          acc # unused and always null through iteration
         else
           contract.blame_with "field name `#{field_name}` is not a number" label
         ) null in
@@ -628,7 +628,7 @@ Let us see if we indeed preserved laziness:
 
 ```
 nickel>let config | NumBoolDict = {
-    "1" = 1 + "a", // Same as our previous "fail"
+    "1" = 1 + "a", # Same as our previous "fail"
     "0" | doc "Some information" = true,
 }
 nickel>:query config."0"
diff --git a/doc/manual/correctness.md b/doc/manual/correctness.md
index 018a6c0e..23efbb0c 100644
--- a/doc/manual/correctness.md
+++ b/doc/manual/correctness.md
@@ -118,12 +118,12 @@ Here is the definition for `split`, but with a twist. We mistakenly forgot to
 wrap `pair.key` as an array before concatenating at line 6:
 
 ```nickel
-// lib.ncl
+# lib.ncl
 {
   split = fun pairs =>
     array.fold (fun pair acc =>
       {
-        // problem: the right expression to use is [pair.key]
+        # problem: the right expression to use is [pair.key]
         keys = acc.keys @ pair.key,
         values = acc.values @ [pair.value],
       })
@@ -135,7 +135,7 @@ wrap `pair.key` as an array before concatenating at line 6:
 And we call to split from our configuration:
 
 ```nickel
-// config.ncl
+# config.ncl
 let {split} = import "lib.ncl" in
 split [{key = "foo", value = 1}, {key = "bar", value = 2}]
 ```
diff --git a/doc/manual/merging.md b/doc/manual/merging.md
deleted file mode 100644
index f20b2ddf..00000000
--- a/doc/manual/merging.md
+++ /dev/null
@@ -1,522 +0,0 @@
-# Merging records
-
-In Nickel, the basic building blocks for data are records (objects in JSON or
-attribute sets in Nix). Merging is a fundamental built-in operation whose role
-is to combine records togethers. Fields common to several records will be
-themselves recursively merged if possible, following the semantics described in
-this document.
-
-Merging is useful to compose small and logical blocks into a potentially complex
-final configuration, making it more manageable. A merge is performed by the `&`
-operator.
-
-Merge is a **symmetric** operation (or, pedantically, commutative). In practice,
-this means that order doesn't matter, and `left & right` is the same thing as
-`right & left`. When the operands need to be distinguished, as we will see for
-default values for example, the idea is to use metadata to do so (annotations),
-rather than relying on the left or right position.
-
-**Warning**: At the time of writing, Nickel's version is 0.1. Important
-additions to merging are planned for coming versions, including priorities and
-custom merge functions. They are not detailed here yet. For more details, see
-the associated technical document [RFC001][rfc001].
-
-The section describes the behavior and use-cases of merge, by considering the
-following situations:
-
-- [Merging two records without common fields](#simple-merge-(no-common-fields))
-- [Merging records with common fields](#recursive-merge-(with-common-fields))
-- [Merging records with metadata](#merging-record-with-metadata)
-  * [Default values](#default-values)
-  * [Contracts](#contracts)
-  * [Documentation](#documentation)
-- [Recursive overriding](#recursive-overriding)
-
-## Simple merge (no common fields)
-
-Merging two records with no common fields results in a record with the fields
-from both operands. That is, `{foo = 1, bar = "bar"} & {baz =false}` evaluates
-to `{foo = 1, bar = "bar", baz = false}`.
-
-### Specification
-
-Technically, if we write the left operand as:
-
-```
-left = {
-  field_left_1 = value_left_1,
-  ..,
-  field_left_n = value_left_n,
-}
-```
-
-And the right operand as:
-
-```
-right {
-  field_right_1 = value_right_1,
-  ..,
-  field_right_k = value_right_k
-}
-```
-
-Then the merge `left & right` evaluates to the record:
-
-```
-{
-  field_left_1 = value_left_1,
-  ..,
-  field_left_n = value_left_n,
-  field_right_1 = value_right_1,
-  ..,
-  field_right_k = value_right_k
-}
-```
-
-In other terms, `left & right` is the union of `left` and `right`.
-
-### Examples
-
-#### Split
-
-You can split a configuration into subdomains:
-
-```nickel
-// file: server.ncl
-{
-    host_name = "example",
-    host = "example.org",
-    ip_addr = "0.0.0.0",
-}
-
-// file: firewall.ncl
-{
-    enable_firewall = true,
-    open_ports = [23, 80, 443],
-}
-
-// file: network.ncl
-let server = import "server.ncl" in
-let firewall = import "firewall.ncl" in
-server & firewall
-```
-
-This gives:
-
-```nickel
-{
-    host_name = "example",
-    host = "example.org",
-    ip_addr = "0.0.0.0",
-    enable_firewall = true,
-    open_ports = [23, 80, 443],
-}
-```
-
-#### Extension
-
-Given a configuration, you can use merge to add new fields:
-
-```nickel
-// file: safe-network.ncl
-let base = import "network.ncl" in
-base & {use_iptables = true}
-```
-
-## Recursive merge (with common fields)
-
-When the two operands have fields in common, those fields are recursively
-merged. For example:
-
-```nickel
-{
-  top_left = 1,
-  common = {left = "left"}}
-& {
-  top_right = 2,
-  common = {right = "right"}
-}
-```
-
-Evaluates to the record:
-
-```nickel
-{
-  top_left = 1,
-  top_right = 2,
-  common = {left = "left", right = "right"}
-}
-```
-
-When one or both of the common fields are not records, the merge will fail
-unless one of the following condition hold:
-
-- They are both of a primitive data type `Num`, `Bool`, `Enum`, `String` and
-  they are equal
-- They are both null
-
-### Specification
-
-```
-left = {
-  field_left_1 = value_left_1,
-  ..,
-  field_left_n = value_left_n,
-  common_1 = common_vleft_1,
-  ..,
-  common_m = common_vleft_m,
-}
-```
-
-And the right operand as:
-
-```
-right {
-  field_right_1 = value_right_1,
-  ..,
-  field_right_k = value_right_k
-  common_1 = common_vright_1,
-  ..,
-  common_m = common_vright_m,
-}
-```
-
-Where the `field_left_i` and `field_right_j` are distinct for all `i` and `j`.
-Then the merge `left & right` evaluates to the record:
-
-```
-{
-  field_left_1 = value_left_1,
-  ..,
-  field_left_n = value_left_n,
-  field_right_1 = value_right_1,
-  ..,
-  field_right_k = value_right_k
-  common_1 = common_vleft_1 & common_vright_1,
-  ..,
-  common_m = common_vleft_m & common_vright_m,
-}
-```
-
-For two values `v1` and `v2`, if at least one value is not a record, then
-
-```
-v1 & v2 = v1    if (type_of(v1) is Num, Bool, Str, Enum or v1 == null)
-                   AND v1 == v2
-          _|_   otherwise (indicates failure)
-```
-
-### Example
-
-```nickel
-// file: udp.ncl
-{
-    // same as firewall = {open_ports = {udp = [...]}},
-    firewall.open_ports.udp = [12345,12346],
-}
-
-// file: tcp.ncl
-{
-    // same as firewall = {open_ports = {tcp = [...]}},
-    firewall.open_ports.tcp = [23, 80, 443],
-}
-
-// firewall.ncl
-let udp = import "udp.ncl" in
-let tcp = import "tcp.ncl" in
-udp & tcp
-```
-
-In the above example, we merge two records, both with a field `firewall`. On
-both sides, the value is a record, which is therefore merged. The same process
-happens one layer below, on the common field `open_ports`, to result in the
-final record:
-
-```nickel
-{
-    firewall = {
-      open_ports = {
-        udp = [12345, 12346],
-        tcp = [23, 80, 443],
-      }
-    }
-}
-```
-
-## Merging record with metadata
-
-Metadata can be attached to values thanks to the `|` operator. Metadata
-currently includes contract annotations, default value, and documentation. We
-describe in this section how metadata interacts with merging.
-
-### Default values
-
-A `default` annotation can be used to provide a base value, but let it be
-overridable through merging. For example, `{foo | default = 1} & {foo = 2}`
-evaluates to `{foo = 2}`. Without the default value, this merge would have
-failed with a `non mergeable fields` error, because merging being symmetric, it
-doesn't know how to combine `1` and `2` in a generic and meaningful way.
-
-#### Specification
-
-We can consider the merging system to feature priorities. To each field
-definition `foo = val` is associated a priority `p(val)`. When merging two
-common fields `value_left` and `value_right`, then the results is either the one
-with the highest priority (that overrides the other), or the two are tentatively
-recursively merged, if the priorities are the same. Without loss of generality,
-we consider the simple case of two records with only one field, which is the
-same on both side:
-
-```
-{common = left} & {common = right}
-= {
-  common = left          if p(left) > p(right)
-           right         if p(left) < p(right)
-           left & right  if p(left) = p(right)
-}
-```
-
-Currently, there are only two priorities, `normal` (by default, when nothing is
-specified) and the `default` one, with `default < normal`. We plan to add more
-in the future (see [RFC001](https://github.com/tweag/nickel/blob/c21cf280dc610821fceed4c2caafedb60ce7177c/rfcs/001-overriding.md#priorities)).
-
-#### Example
-
-Let us stick to our firewall example. Thanks to default values, we set the most
-restrictive configuration by default, which can still be overridden if needed.
-
-Let us first try without default values:
-
-```nickel
-let base = {
-  firewall.enabled = true,
-  firewall.type = "iptables",
-  firewall.open_ports = [21, 80, 443],
-} in
-let patch = {
-  firewall.enabled = false,
-  server.host.options = "TLS",
-} in
-base & patch
-```
-
-Because merging is meant to be symmetric, Nickel is unable to know which value
-to pick between `enabled = true` and `enabled = false` for the firewall, and
-thus fail:
-
-```
-error: non mergeable terms
-  ┌─ repl-input-0:2:22
-  │
-2 │   firewall.enabled = true,
-  │                      ^^^^ cannot merge this expression
-  ·
-7 │   firewall.enabled = false,
-  │                      ^^^^^ with this expression
-
-```
-
-We can use default values to give the priority to the right side:
-
-```nickel
-let base = {
-  firewall.enabled | default = true,
-  firewall.type | default = "iptables",
-  firewall.open_ports | default = [21, 80, 443],
-} in
-let patch = {
-  firewall.enabled = false,
-  server.host.options = "TLS",
-} in
-base & patch
-```
-
-This evaluates to:
-
-```
-{
-  firewall = {
-    enabled = false,
-    open_ports = [21, 80, 443],
-    type = "iptables",
-  },
-  server = {
-    host = {
-      "options": "TLS"
-    }
-  }
-}
-```
-
-### Contracts
-
-*Note*: see the [correctness section](./correctness.md) and the
-[contracts section](./contracts.md) for a thorough introduction to contracts in
-Nickel.
-
-Fields may have contracts attached, either directly, as in `{foo | Num = 1}`, or
-propagated from an annotation higher up, as in `{foo = 1} | {foo | Num}`. In
-both cases, `foo` must satisfy the contract `Num`. What happens if the value of
-`foo` is altered in a subsequent merge? For example:
-
-- Should `{foo | default | Num = 1} & {foo = "bar"}` succeed, although `foo`
-  would be a string in the final result?
-- Should `{foo.subfield | Str = "a"} & {foo.other_subfield = 1}`
-  succeed, although a closed contract `{subfield | Str}` is attached to `foo`,
-  and the final result would have an additional field `other_subfield` ?
-
-Nickel chooses to answer **no** to both. In general, when a contract is attached
-to a field `foo`, merging ensures that whatever is this field merged with,
-including being dropped in favor of another value, the final value for `foo` has
-to respect the contract as well or the evaluation will fail accordingly.
-
-#### Specification
-
-For two operands with one field each, which is the same on both side, with respective
-contracts `Left1, .., Leftn` and `Right1, .., Rightk` attached:
-
-```nickel
-left = {
-  common | Left1
-         | ..
-         | Leftn
-}
-```
-
-And
-
-```nickel
-right = {
-  common | Right1
-         | ..
-         | Rightk
-}
-```
-
-Then the `common` field of `left & right` will be checked against `Left1, ..,
-Leftn, Right1, .., Rightk`. Here, we ignore the case of type annotations such as
-`common: LeftType` that can just be considered as an additional contract
-`Left0`.
-
-#### Example
-
-```nickel
-let Port
-  | doc "A valid port number"
-  = contract.from_predicate (fun value =>
-    builtin.is_num value &&
-    value % 1 == 0 &&
-    value >= 0 &&
-    value <= 65535) in
-let GreaterThan
-  | doc "A number greater than the paramater"
-  = fun x => contract.from_predicate (fun value => value > x) in
-
-{
-    port | GreaterThan 1024
-         | default = 8080,
-} & {
-    port | Port = 80,
-}
-```
-
-This fails at evaluation:
-
-```
-error: contract broken by a value.
-[..]
-   ┌─ repl-input-1:16:19
-   │
-16 │     port | Port = 80,
-   │                   ^^ applied to this expression
-
-note:
-   ┌─ repl-input-1:13:12
-   │
-13 │     port | GreaterThan 1024
-   │            ^^^^^^^^^^^^^^^^ bound here
-```
-
-
-### Documentation
-
-Documentation is attached via the `doc` keyword. Documentation is propagated
-during merging. For example, querying `foo` by using the command `nickel -f
-config.ncl query foo` on:
-
-```nickel
-// config.ncl
-{
-  foo | doc "Some documentation"
-      | = {}
-} & {
-  foo.field = null,
-}
-```
-
-Will print `"Some documentation"` as expected. If both sides have documentation, the behavior
-is unspecified, as merging two distinct blobs of text doesn't make sense
-in general. Currently, Nickel will randomly keeps one of the two in practice.
-
-## Recursive overriding
-
-We've seen in the section on default values that they are useful to override
-(update) a single field with a different value. The combo of merging and default
-values can do more. In Nickel, records are recursive by default, in order to
-express easily dependencies between the different fields of the configuration.
-Concretely, you can refer to other fields of a record from within this record:
-
-```nickel
-let base_config = {
-  version | default = "20.09",
-  input.url | default = "nixpkgs/nixos-%{version}",
-} in
-base_config
-```
-
-Here, we referred to `version` from the `input` field transparently. This
-configuration evaluates to:
-
-```nickel
-{
-  version = "20.09",
-  input = {url = "nixpkgs/nixos-20.09"},
-}
-```
-
-Merging handles overriding on recursive record too. More precisely, when we
-override the default value of `version`, *the fields that depend on `version` --
-here, `input` -- will also be updated automatically*. For example, `base_config
-& {version = "unstable"}` will evaluate to:
-
-```nickel
-{
-  version = "unstable",
-  input = {url = "nixpkgs/nixos-unstable"},
-}
-```
-
-Currently, one can only override a field that has been marked as default beforehand. A
-more ergonomic way of overriding is planned, and described in [RFC001][rfc001].
-
-### Example
-
-Here is another variation of recursive overriding on our `firewall` example:
-
-```nickel
-let security = {
-    firewall.open_proto.http | default = true,
-    firewall.open_proto.https | default = true,
-    firewall.open_proto.ftp | default = true,
-    firewall.open_ports = []
-        @ (if firewall.open_proto.ftp then [21] else [])
-        @ (if firewall.open_proto.http then [80] else [])
-        @ (if firewall.open_proto.https then [443] else []),
-} in // => security.firewall.open_ports = [21, 80, 443]
-security & {firewall.open_proto.ftp = false} // => firewall.open_ports = [80, 443]
-```
-
-Here, `security.firewall.open_ports` is `[21, 80, 443]`. But in the returned
-configuration (let's call it `result`), `result.firewall.open_ports = [80, 443]`.
-
-[rfc001]: https://github.com/tweag/nickel/blob/c21cf280dc610821fceed4c2caafedb60ce7177c/rfcs/001-overriding.md
diff --git a/doc/manual/typing.md b/doc/manual/typing.md
index 5b1b6a47..b4564748 100644
--- a/doc/manual/typing.md
+++ b/doc/manual/typing.md
@@ -99,15 +99,15 @@ block*.
 
 Example:
 ```
-// Let binding
+# Let binding
 let f : Num -> Bool = fun x => x % 2 == 0 in
 
-// Record field
+# Record field
 let r = {
   count : Num = 2354.45 * 4 + 100,
 } in
 
-// Inline
+# Inline
 1 + ((if f 10 then 1 else 0) : Num)
 ```
 
@@ -389,7 +389,7 @@ summed, without modifying the rest:
 ```nickel
 let sum : forall r. {a : Num, b : Num | r} -> {a : Num, b : Num, sum : Num | r}
         = fun x => x $[ "sum" = x.a + x.b]
-in sum {a = 1, b = 2, c = 3} // {a=1, b=2, sum=3, c=3}
+in sum {a = 1, b = 2, c = 3} # {a=1, b=2, sum=3, c=3}
 ```
 
 Note that row polymorphism also works with enums, with the same intuition of a
diff --git a/examples/arrays/arrays.ncl b/examples/arrays/arrays.ncl
index b460551b..d0bdca46 100644
--- a/examples/arrays/arrays.ncl
+++ b/examples/arrays/arrays.ncl
@@ -1,5 +1,5 @@
-// Example array functions. This code is illustrative: prefer using the array 
-// stdlib functions `array.map` and `array.fold` instead.
+# Example array functions. This code is illustrative: prefer using the array 
+# stdlib functions `array.map` and `array.fold` instead.
 let my_array_lib = {
   map : forall a b. (a -> b) -> Array a -> Array b = fun f arr =>
     if arr == [] then
@@ -18,6 +18,6 @@ let my_array_lib = {
           let tail = array.tail arr in
           f head (fold f tail first),
 } in
-// Compute `7!`
+# Compute `7!`
 let l = my_array_lib.map (fun x => x+1) [1, 2, 3, 4, 5, 6] in
 my_array_lib.fold (fun x acc => x * acc) l 1
diff --git a/examples/config-gcc/README.md b/examples/config-gcc/README.md
index 5dd09816..1702c14a 100644
--- a/examples/config-gcc/README.md
+++ b/examples/config-gcc/README.md
@@ -20,7 +20,7 @@ This example defines a couple contracts:
     appears as such in the output. This contract is illustrative and by no mean
     exhaustive.
 - `Path`: define a valid `/`-separated path as a string. In particular, the
-    `//` sequence is forbidden.
+    `#` sequence is forbidden.
 - `SharedObjectFile`: define a file whose extension is `.so`.
 - `OptLevel`: optimization level, either `0`, `1` or `2`.
 - `Contract`: the schema of the end configuration.
diff --git a/examples/config-gcc/config-gcc.ncl b/examples/config-gcc/config-gcc.ncl
index 178b3779..409eeb35 100644
--- a/examples/config-gcc/config-gcc.ncl
+++ b/examples/config-gcc/config-gcc.ncl
@@ -1,7 +1,7 @@
-// Validate and normalize gcc flags. They can be either a string `-Wextra` or
-// a structured value `{flag = "W", arg = "extra"}`. Arguments are not checked.
+# Validate and normalize gcc flags. They can be either a string `-Wextra` or
+# a structured value `{flag = "W", arg = "extra"}`. Arguments are not checked.
 let GccFlag =
-  // We only allow the following flags
+  # We only allow the following flags
   let available = ["W", "c", "S", "e", "o"] in
   fun label value =>
   if builtin.is_str value then
@@ -13,7 +13,7 @@ let GccFlag =
   else if builtin.is_record value then
     if record.has_field "flag" value && record.has_field "arg" value then
       if array.any (fun x => x == value.flag) available then
-        //Normalize the tag to a string
+        #Normalize the tag to a string
         value.flag ++ value.arg
       else
         contract.blame_with "unknown flag %{value.flag}" label
diff --git a/examples/fibonacci/fibonacci.ncl b/examples/fibonacci/fibonacci.ncl
index 2b28eb60..8c6644e2 100644
--- a/examples/fibonacci/fibonacci.ncl
+++ b/examples/fibonacci/fibonacci.ncl
@@ -1,8 +1,8 @@
-// Currently, only record bindings are recursive. To use a recursive function,
-// one has to use a record.
+# Currently, only record bindings are recursive. To use a recursive function,
+# one has to use a record.
 
-// This is the naive, exponential version of fibonacci: don't call it on a big
-// value!
+# This is the naive, exponential version of fibonacci: don't call it on a big
+# value!
 let fibonacci = {
  f = fun n =>
   if n == 0 then
diff --git a/examples/merge/main.ncl b/examples/merge/main.ncl
index a097d287..53ca4795 100644
--- a/examples/merge/main.ncl
+++ b/examples/merge/main.ncl
@@ -1,6 +1,6 @@
-// Merge several blocks into one final configuration. In a real world case, one
-// would also want contracts to validate the shape of the data.
+# Merge several blocks into one final configuration. In a real world case, one
+# would also want contracts to validate the shape of the data.
 let server = import "server.ncl" in
 let security = import "security.ncl" in
-// Disabling firewall in the final result
+# Disabling firewall in the final result
 server & security & {firewall.enabled = false}
diff --git a/examples/polymorphism/polymorphism.ncl b/examples/polymorphism/polymorphism.ncl
index 891f51fa..8c2d591a 100644
--- a/examples/polymorphism/polymorphism.ncl
+++ b/examples/polymorphism/polymorphism.ncl
@@ -1,6 +1,6 @@
-// First projection, statically typed
+# First projection, statically typed
 let fst : forall a b. a -> b -> a = fun x y => x in
-// Evaluation function, statically typed
+# Evaluation function, statically typed
 let ev : forall a b. (a -> b) -> a -> b = fun f x => f x in
 let id : forall a. a -> a = fun x => x in
 (ev id (fst 5 10) == 5 : Bool)
diff --git a/examples/record-contract/record-contract.ncl b/examples/record-contract/record-contract.ncl
index 4aa564f0..bb69f087 100644
--- a/examples/record-contract/record-contract.ncl
+++ b/examples/record-contract/record-contract.ncl
@@ -1,6 +1,6 @@
-// An illustrative (thus incomplete and maybe incorrect) contract example for a
-// Kubernetes configuration.
-// Schema and example derived from https://github.com/kubernetes/examples/blob/master/guestbook-go/guestbook-controller.json.
+# An illustrative (thus incomplete and maybe incorrect) contract example for a
+# Kubernetes configuration.
+# Schema and example derived from https://github.com/kubernetes/examples/blob/master/guestbook-go/guestbook-controller.json.
 
 let Port | doc "A contract for a port number" = contract.from_predicate (fun value =>
   builtin.is_num value &&
diff --git a/examples/simple-contracts/simple-contract-bool.ncl b/examples/simple-contracts/simple-contract-bool.ncl
index 150c56f2..69a89a14 100644
--- a/examples/simple-contracts/simple-contract-bool.ncl
+++ b/examples/simple-contracts/simple-contract-bool.ncl
@@ -1,6 +1,6 @@
-// Example of simple custom contract, parametrized by a first argument.
-// In practice, for this kind of simple predicate, one should rather use
-// `contract.from_predicate`
+# Example of simple custom contract, parametrized by a first argument.
+# In practice, for this kind of simple predicate, one should rather use
+# `contract.from_predicate`
 let EqualsTo = fun reference_value label value =>
   if reference_value == value then
     value
@@ -10,9 +10,9 @@ let EqualsTo = fun reference_value label value =>
 let AlwaysTrue = EqualsTo true in
 let AlwaysFalse = EqualsTo false in
 
-// This contract says: `not` requires its argument to be true, and in return
-// promise that the return value is false.
-// Try passing `false` to `not`, or to use the identity function (replacing `!x`
-// by `x`) to see contract errors appear.
+# This contract says: `not` requires its argument to be true, and in return
+# promise that the return value is false.
+# Try passing `false` to `not`, or to use the identity function (replacing `!x`
+# by `x`) to see contract errors appear.
 let not | AlwaysTrue -> AlwaysFalse = fun x => !x in
 not true
diff --git a/examples/simple-contracts/simple-contract-div.ncl b/examples/simple-contracts/simple-contract-div.ncl
index 0e0ed165..1de1d0b7 100644
--- a/examples/simple-contracts/simple-contract-div.ncl
+++ b/examples/simple-contracts/simple-contract-div.ncl
@@ -1,5 +1,5 @@
-// /!\ THIS EXAMPLE IS EXPECTED TO FAIL
-// Illustrate a basic contract violation.
+# /!\ THIS EXAMPLE IS EXPECTED TO FAIL
+# Illustrate a basic contract violation.
 
 let Even = fun label value =>
   if builtin.is_num value && value % 2 == 0 then
@@ -11,6 +11,6 @@ let DivBy3 = fun label value =>
     value
   else
     contract.blame label in
-// Will cause an error! 4 is no divided by 3.
+# Will cause an error! 4 is no divided by 3.
 (4 | Even
    | DivBy3)
diff --git a/lsp/README.md b/lsp/README.md
index 42f013ea..ee667b3b 100644
--- a/lsp/README.md
+++ b/lsp/README.md
@@ -129,12 +129,12 @@ Add an `nickel_ls` entry to your configuration. Type `:CocConfig` in Neovim (or
 ```
 {
   "languageserver": {
-    // Your other language servers configuration
-    // ...,
+    # Your other language servers configuration
+    # ...,
     "nickel_ls": {
       "command": "nls",
-      // You can enable performance tracing with:
-      // "command": "nls --trace <file>",
+      # You can enable performance tracing with:
+      # "command": "nls --trace <file>",
       "rootPatterns": [
         ".git"
       ],
diff --git a/src/error.rs b/src/error.rs
index 75e8f86b..d9040bac 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -296,8 +296,8 @@ pub enum ParseError {
     /// the original syntax. Typically, a field assignment:
     ///
     /// ```nickel
-    /// forall a. {foo : Num; a} // allowed
-    /// forall a. {foo : Num = 1; a} // InvalidUniRecord error: giving a value to foo is forbidden
+    /// forall a. {foo : Num; a} # allowed
+    /// forall a. {foo : Num = 1; a} # InvalidUniRecord error: giving a value to foo is forbidden
     /// ```
     ///
     /// See [RFC002](../../rfcs/002-merge-types-terms-syntax.md) for more details.
diff --git a/src/parser/error.rs b/src/parser/error.rs
index 18e310d5..a7cd46f4 100644
--- a/src/parser/error.rs
+++ b/src/parser/error.rs
@@ -23,8 +23,8 @@ pub enum ParseError {
     /// the original syntax. Typically, a field assignment:
     ///
     /// ```nickel
-    /// forall a. {foo : Num; a} // allowed
-    /// forall a. {foo : Num = 1; a} // InvalidUniRecord error: giving a value to foo is forbidden
+    /// forall a. {foo : Num; a} # allowed
+    /// forall a. {foo : Num = 1; a} # InvalidUniRecord error: giving a value to foo is forbidden
     /// ```
     ///
     /// See [RFC002](../../rfcs/002-merge-types-terms-syntax.md) for more details.
diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs
index 98843527..746bf077 100644
--- a/src/parser/lexer.rs
+++ b/src/parser/lexer.rs
@@ -284,7 +284,7 @@ pub enum NormalToken<'input> {
     EnumOpen,
     #[token("|]")]
     EnumClose,
-    #[regex("//[^\n]*")]
+    #[regex("#[^\n]*")]
     LineComment,
 }
 
diff --git a/src/typecheck/mod.rs b/src/typecheck/mod.rs
index 1c4fb7c1..f82167c1 100644
--- a/src/typecheck/mod.rs
+++ b/src/typecheck/mod.rs
@@ -22,7 +22,7 @@
 //! mode, but it is never implicitly generalized. For example, the following program is rejected:
 //!
 //! ```text
-//! // Rejected
+//! # Rejected
 //! let id = fun x => x in seq (id "a") (id 5) : Num
 //! ```
 //!
@@ -35,7 +35,7 @@
 //! annotation is sufficient:
 //!
 //! ```text
-//! // Accepted
+//! # Accepted
 //! let id : forall a. a -> a = fun x => x in seq (id "a") (id 5) : Num
 //! ```
 //!
diff --git a/stdlib/string.ncl b/stdlib/string.ncl
index 86d01f2b..4d16d065 100644
--- a/stdlib/string.ncl
+++ b/stdlib/string.ncl
@@ -120,7 +120,7 @@
       else
         %blame% (%tag% "not a string" l),
 
-    // using a contract instead of type for now because of https://github.com/tweag/nickel/issues/226
+    # using a contract instead of type for now because of https://github.com/tweag/nickel/issues/226
     join | Str -> Array Str -> Str
     | doc m%"
       Joins a array of strings given a seperator.
@@ -357,7 +357,7 @@
       "%m
     = fun n => %to_str% n,
 
-    // from_enum | < | Dyn> -> Str = fun tag => %to_str% tag,
+    # from_enum | < | Dyn> -> Str = fun tag => %to_str% tag,
     from_enum | Dyn -> Str
     | doc m%"
       Converts an enum variant to its string representation.
@@ -409,7 +409,7 @@
       "%m
     = fun s => s == "true",
 
-    // to_enum | Ident -> < | Dyn> = fun s => %enum_from_str% s,
+    # to_enum | Ident -> < | Dyn> = fun s => %enum_from_str% s,
     to_enum | Ident -> Dyn
     | doc m%"
       Converts any string that represents an enum variant to that enum variant.


Test patch:
diff --git a/src/parser/tests.rs b/src/parser/tests.rs
index bff0f86d..3e62c54e 100644
--- a/src/parser/tests.rs
+++ b/src/parser/tests.rs
@@ -361,14 +361,14 @@ fn multiline_str_escape() {
 #[test]
 fn line_comments() {
     assert_eq!(
-        parse_without_pos("// 1 +\n1 + 1// + 3\n//+ 2"),
+        parse_without_pos("# 1 +\n1 + 1# + 3\n#+ 2"),
         parse_without_pos("1 + 1")
     );
     assert_eq!(
         parse_without_pos(
-            "{ // Some comment
-            field = foo, // Some description
-            } // Some other"
+            "{ # Some comment
+            field = foo, # Some description
+            } # Some other"
         ),
         parse_without_pos("{field = foo}")
     );
diff --git a/tests/pass/annotations.ncl b/tests/pass/annotations.ncl
index 3f857d7d..7e7c456f 100644
--- a/tests/pass/annotations.ncl
+++ b/tests/pass/annotations.ncl
@@ -1,7 +1,7 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // left_annot_precedence
+  # left_annot_precedence
   (let dummy = null in
     let LocalAssert = Assert in
     true | LocalAssert),
@@ -19,7 +19,7 @@ let Assert = fun l x => x || %blame% l in
       x | LocalAssert in
     f true),
 
-  // others_precedence
+  # others_precedence
   ((fun x => x | Assert) true),
   (let AssertOk = fun l t => if t == `Ok then t else %blame% l in
     switch {`Ok => true, `Err => false} `Ok | AssertOk),
diff --git a/tests/pass/arrays.ncl b/tests/pass/arrays.ncl
index e6e00199..55cc54a2 100644
--- a/tests/pass/arrays.ncl
+++ b/tests/pass/arrays.ncl
@@ -1,16 +1,16 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // accesses
+  # accesses
   array.elem_at 1 [1,2,3] == 2,
   array.elem_at 1 (array.map (fun x => x + 1) [1,2,3]) == 3,
 
-  // length
+  # length
   array.length [] == 0,
   array.length [1,2,3] == 3,
   array.length ([] @ [1,2] @ [3,4] @ []) == 4,
 
-  // Test case added after https://github.com/tweag/nickel/issues/154
+  # Test case added after https://github.com/tweag/nickel/issues/154
   let x = 1 in let l = [x] @ [2] in %head% l == 1,
 
   let Y = fun f => (fun x => f (x x)) (fun x => f (x x)) in
diff --git a/tests/pass/basics.ncl b/tests/pass/basics.ncl
index 1b9bb4a1..bfa85703 100644
--- a/tests/pass/basics.ncl
+++ b/tests/pass/basics.ncl
@@ -1,7 +1,7 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // basic arithmetic
+  # basic arithmetic
   1+1 == 2,
   1-2+3-4 == -2,
   2-3-4 == -5,
@@ -13,7 +13,7 @@ let Assert = fun l x => x || %blame% l in
   34 + (if true then 2 else 222)
     == 36,
 
-  // comparisons
+  # comparisons
   1 < 1 == false,
   1 <= 1 == true,
   1 > 1 == false,
@@ -31,7 +31,7 @@ let Assert = fun l x => x || %blame% l in
   1/4 + 1/4 - 1/4 + 1/4 >= 1/2 == true,
   1/4 + 1/4 - 1/4 + 1/4 < 1/2 == false,
 
-  // This test checks that the terms of a switch are closured
+  # This test checks that the terms of a switch are closured
   let x = 3 in (switch { `foo => 1, _ => x} (3 + 2)) == 3,
 ]
 |> array.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/builtins.ncl b/tests/pass/builtins.ncl
index 26758f96..d865b04f 100644
--- a/tests/pass/builtins.ncl
+++ b/tests/pass/builtins.ncl
@@ -1,11 +1,11 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // is_record
+  # is_record
   builtin.is_record {},
 
-  /// This currently do not check that subexpressions are actually forced,
-  /// just that the evaluation succeeds
+  # This currently does not check that subexpressions are actually forced,
+  # just that the evaluation succeeds
   %seq% 1 true,
   let x = (1 + 1) in %seq% x x == 2,
   let r = {a=(1 + 1),} in
diff --git a/tests/pass/contracts.ncl b/tests/pass/contracts.ncl
index 6c408904..2d847081 100644
--- a/tests/pass/contracts.ncl
+++ b/tests/pass/contracts.ncl
@@ -10,32 +10,32 @@ let Assert = fun l x => x || %blame% l in
   in let not | AlwaysTrue -> AlwaysFalse = fun b => if b then false else true in
   not true == false,
 
-  // id_polymorphic_contract
+  # id_polymorphic_contract
   let id | forall a. a -> a = fun x => x in id true,
 
-  // higher_order_contract
+  # higher_order_contract
   let to_bool | forall a. (a -> Bool) -> a -> Bool =
     fun f => fun x => f x in
     to_bool (fun x => true) 4,
 
-  // apply_twice
+  # apply_twice
   let twice | forall a. (a -> a) -> a -> a =
     fun f => fun x => f (f x) in
   twice (fun x => x + 1) 3 == 5,
 
-  // strings
+  # strings
   ("hello" | Str) == "hello",
   ("hello" ++ " world" | Str) == "hello world",
 
-  // enums_simple
+  # enums_simple
   (`foo | [| foo, bar |]) == `foo,
   (`bar | forall r. [| foo, bar ; r|]) == `bar,
 
-  // enums_escaped
+  # enums_escaped
   (`"foo:baz" | [| "foo:baz", "bar:baz" |]) == `"foo:baz",
   (`"bar:baz" | forall r. [| "foo:baz", "bar:baz" ; r |]) == `"bar:baz",
 
-  // enums_complex
+  # enums_complex
   let f : forall r. [| foo, bar ; r |] -> Num =
     fun x => switch { `foo => 1, `bar => 2, _ => 3, } x in
   f `bar == 2,
@@ -52,7 +52,7 @@ let Assert = fun l x => x || %blame% l in
     fun x => switch { `foo => 1, `"bar:baz" => 2, _ => 3, } x in
   f `"boo,grr" == 3,
 
-  // records_simple
+  # records_simple
   ({} | {}) == {},
   let x | {a: Num, s: Str} = {a = 1, s = "a"} in
     %deep_seq% x x == {a = 1, s = "a"},
@@ -60,7 +60,7 @@ let Assert = fun l x => x || %blame% l in
   let x | {a: Num, s: {foo: Bool}} = {a = 1, s = { foo = true}} in
     %deep_seq% x x == {a = 1, s = { foo = true}},
 
-  // polymorphism
+  # polymorphism
   (let id | forall a. { ; a} -> { ; a} = fun x => x in
     let extend | forall a. { ; a} -> {foo: Num ; a} = fun x =>
       x & {foo = 1} in
@@ -82,13 +82,13 @@ let Assert = fun l x => x || %blame% l in
       | Assert)
   ),
 
-  // records_dynamic_tail
+  # records_dynamic_tail
   ({a = 1, b = "b"} | {a: Num, b: Str ; Dyn}) == {a = 1, b = "b"},
   ({a = 1, b = "b", c = false} | {a: Num, b: Str ; Dyn})
   == {a = 1, b = "b", c = false},
   ((fun r => r.b) | {a: Num ; Dyn} -> Dyn) {a = 1, b = 2} == 2,
 
-  // records_open_contracts
+  # records_open_contracts
   ({a = 0, b = 0} | {a | Num, ..}) == {a = 0, b = 0},
   let Contract = {a | Num} & {..} in
   ({a = 0, b = 0} | Contract) == {a = 0, b = 0},
@@ -97,29 +97,29 @@ let Assert = fun l x => x || %blame% l in
   let Contract = {a | Num, ..} & {b | Num, ..} in
   ({a = 0, b = 0, c = 0} | Contract) == {a = 0, b = 0, c = 0},
 
-  // arrays 
+  # arrays 
   ([1, "2", false] | Array Dyn) == [1, "2", false],
   ([1, 2, 3] | Array Num) == [1, 2, 3],
   (["1", "2", "false"] | Array Str) == ["1", "2", "false"],
 
-  // full_annotations
-  // Check that the contract introduced by the type annotation doesn't interact
-  // with the `default` attribute
+  # full_annotations
+  # Check that the contract introduced by the type annotation doesn't interact
+  # with the `default` attribute
   ({foo : {bar: Bool} | default = {bar = false}} & {foo.bar = true}).foo.bar,
 
-  // nested_metavalues
-  // Regression test for #402
+  # nested_metavalues
+  # Regression test for #402
   let MyContract = { x | Str } in
   {
     foo | MyContract | default = { x = "From foo" },
     bar | {..} | default = foo
   } == { foo.x = "From foo", bar.x = "From foo"},
 
-  // mixing type and record contracts
+  # mixing type and record contracts
   let f | {foo | Num} -> {bar | Num} = fun r =>
     {bar = r.foo} in
   (f {foo = 1}).bar == 1,
-  // user-written contract application
+  # user-written contract application
   let Extend = fun base label value =>
     let derived = if builtin.is_record base then
       (base & {foo | Num})
diff --git a/tests/pass/eq.ncl b/tests/pass/eq.ncl
index 0a9a6c58..036a5a1e 100644
--- a/tests/pass/eq.ncl
+++ b/tests/pass/eq.ncl
@@ -1,7 +1,7 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // basic
+  # basic
   0 == 0 + 0 + 0,
   true == (if true then true else false),
   "a" ++ "b" ++ "c" == "%{"a" ++ "b"}" ++ "c",
@@ -18,7 +18,7 @@ let Assert = fun l x => x || %blame% l in
   `Less != 0,
   `Greater != false,
 
-  // arrays
+  # arrays
   [] == [],
   [(1 + 0), (1 + 1), (1 + 1 + 1)] == [1, 2, 3],
   [(1 + 0), ("a" ++ "b"), (if true then true else false)]
@@ -33,7 +33,7 @@ let Assert = fun l x => x || %blame% l in
   [1, "a", true] != [1, "a", false],
   [[true]] != [[[true]]],
 
-  // records
+  # records
   {} == {},
   {}$["a" = 1]$["b" = true]
     == {a = 1, b = true},
@@ -57,10 +57,10 @@ let Assert = fun l x => x || %blame% l in
   { a = "a", b = true } != { a = true, b = "a"},
   { a = { a = true } } != {a = { a = { a = true } } },
 
-  // Now that the equality operator directly uses the stack to store its continuation (see
-  // https://github.com/tweag/nickel/pull/247), check that it correctly cleans the stack when
-  // evaluating a subequality to `false`.
-  // Generate an non-empty evaluation context to evaluate equalities over a non-empty stack
+  # Now that the equality operator directly uses the stack to store its continuation (see
+  # https://github.com/tweag/nickel/pull/247), check that it correctly cleans the stack when
+  # evaluating a subequality to `false`.
+  # Generate an non-empty evaluation context to evaluate equalities over a non-empty stack
   let eq_with_ctxt = fun x y =>
       let not = fun b =>
         if b then true else false in
diff --git a/tests/pass/functions.ncl b/tests/pass/functions.ncl
index 8301810c..1576c18a 100644
--- a/tests/pass/functions.ncl
+++ b/tests/pass/functions.ncl
@@ -9,7 +9,7 @@ let Assert = fun l x => x || %blame% l in
   let f = fun f y => f (f y) in f (fun x => x+1) 3 == 5,
   let g  = fun x => if x then 0 else false in g ((fun x => true) 23)
     == 0,
-  // Y fixpont combinator
+  # Y fixpont combinator
   let Y = (fun f => (fun x => f (x x)) (fun x => f (x x))) in
     let g = Y (fun g => (fun x => if x  then (g false) else 4)) in
     g true
diff --git a/tests/pass/imported.ncl b/tests/pass/imported.ncl
index 0d72daea..9723a848 100644
--- a/tests/pass/imported.ncl
+++ b/tests/pass/imported.ncl
@@ -1,2 +1,2 @@
-// This isn’t really a test, mostly an auxiliary file used by `import.ncl`
+# This isn’t really a test, mostly an auxiliary file used by `import.ncl`
 fun x => x
diff --git a/tests/pass/metavalues.ncl b/tests/pass/metavalues.ncl
index 9d4dd0ad..239844f0 100644
--- a/tests/pass/metavalues.ncl
+++ b/tests/pass/metavalues.ncl
@@ -3,20 +3,20 @@ let Assert = fun l x => x || %blame% l in
 [
   (10 | default | Num) == 10,
 
-  // Check the correct handling of the update of thunks containing enriched values (see issue
-  // https://github.com/tweag/nickel/issues/123)
+  # Check the correct handling of the update of thunks containing enriched values (see issue
+  # https://github.com/tweag/nickel/issues/123)
   let x = {a = (fun x => (1 | default)) 1} in
     builtin.seq (x.a) ((x & {a=2}).a) == 2,
 
-  // merge_default
+  # merge_default
   ({a = 2} & {a | default = 0, b | default = true}) == {a = 2, b = true},
   {a | default = {x = 1}} & {a | default = {y = "y"}} == {a = {x = 1, y = "y"}},
 
-  // merge_contract
+  # merge_contract
   {a = 2, b | Bool} & {a | Num, b | default = true}
     == {a = 2, b = true},
 
-  // merge_default_contract
+  # merge_default_contract
   {a = 2} & {a | default | Num = 0, b | default = true}
     == {a = 2, b = true},
 
@@ -25,7 +25,7 @@ let Assert = fun l x => x || %blame% l in
   ({a | default = 1} & {b | Num} & {a | default = 1}).a
     == 1,
 
-  // composed
+  # composed
   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
@@ -33,24 +33,24 @@ let Assert = fun l x => x || %blame% l in
     (composed & {a = 12} == {a = 12} | Assert),
 
 
-  // Check that the environments of contracts are correctly saved and restored when merging. See
-  // issue [#117](https://github.com/tweag/nickel/issues/117)
+  # Check that the environments of contracts are correctly saved and restored when merging. See
+  # issue [#117](https://github.com/tweag/nickel/issues/117)
   (let ctr_num = let x = Num in {a | x} in
     let ctr_id = let x = fun l x => x in {a | x} in
     let val = let x = 1 in {a = x} in
     let def = let x = 2 in {a | default = x} in
     let def2 = let x = (1 + 1) in {a | default = x} in
-  // contract/contract -> contract/value -> value/default
+  # contract/contract -> contract/value -> value/default
   ((ctr_num & ctr_id & val & def).a == 1 | Assert) &&
-  // default/value <- value/contract
+  # default/value <- value/contract
   ((def & (val & ctr_num)).a == 1 | Assert) &&
-  // default/contract-> contract-default/contract-default <- contract/default
+  # default/contract-> contract-default/contract-default <- contract/default
   (((def & ctr_num) & (ctr_id & def2)).a == 2 | Assert) &&
-  // default/contract -> contract-default/contract -> contract-default/value
+  # default/contract -> contract-default/contract -> contract-default/value
   ((def & ctr_num & ctr_id & val).a == 1 | Assert) &&
-  // default/contract -> contract-default/default
+  # default/contract -> contract-default/default
   ((def & ctr_num & def2).a == 2 | Assert) &&
-  // value/contract-default <- contract/contract-default
+  # value/contract-default <- contract/contract-default
   ((val & (ctr_num & def)).a == 1 | Assert)),
 ]
 |> array.foldl (fun x y => (x | Assert) && y) true
diff --git a/tests/pass/overriding.ncl b/tests/pass/overriding.ncl
index bffceb0a..9f163c89 100644
--- a/tests/pass/overriding.ncl
+++ b/tests/pass/overriding.ncl
@@ -63,8 +63,8 @@ let Assert = contract.from_predicate function.id in
   |> builtin.deep_seq ext1
   |> builtin.deep_seq ext2,
 
-  // Test that the evaluation of a recursive record patches the right
-  // environment in some edge cases (when fields only contains a variable)
+  # Test that the evaluation of a recursive record patches the right
+  # environment in some edge cases (when fields only contains a variable)
   let foo = 1 in
   let y = foo in
   {bar = y, foo = 2}.bar == 1,
diff --git a/tests/pass/record-defs.ncl b/tests/pass/record-defs.ncl
index 1db699da..61a23097 100644
--- a/tests/pass/record-defs.ncl
+++ b/tests/pass/record-defs.ncl
@@ -1,7 +1,7 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // piecewise_definitions
+  # piecewise_definitions
   {foo.bar.stuff = 1} == {foo = {bar = {stuff = 1}}},
   {foo.bar.stuff = 1, foo.bar.stuff = 1} == {foo = {bar = {stuff = 1}}},
   {a.b.c.d = "foo"} == {a = {b = {c = {d = "foo"}}}},
@@ -15,7 +15,7 @@ let Assert = fun l x => x || %blame% l in
   {foo = {}, foo.bar = {}, foo.bar.baz = true}
     == {foo = {bar = {baz = true}}},
 
-  // quoted_fields
+  # quoted_fields
   {"foo$-^bar" = "foo"}."foo$-^bar" == "foo",
   let x = "fo" ++ "o" in
     {"%{x}-bar" = "foo"}."foo-bar" == "foo",
@@ -23,20 +23,20 @@ let Assert = fun l x => x || %blame% l in
   {"foo-bar"."baz+baz" = false}."foo-bar"."baz+baz" == false,
   {foo-bar.baz-baz = false}.foo-bar.baz-baz == false,
 
-  // recursive_paths
+  # recursive_paths
   {foo.bar.baz = 1, bar.baz.foo = foo.bar.baz + 1}
     == {foo = {bar = {baz = 1}}, bar = {baz = {foo = 2}}},
   {foo."bar"."baz" = 1, "bar"."baz"."foo" = foo.bar."baz" + 1}
     == {foo = {bar = {baz = 1}}, bar = {baz = {foo = 2}}},
 
 
-  // piecewise_annotations
+  # piecewise_annotations
   {foo.bar | default = 1, foo.baz = 2}
     == {foo = {bar = 1, baz = 2}},
   {foo.bar | default = 1, foo.bar = 2} == {foo = {bar = 2}},
   {foo.bar.baz | Bool = true}.foo.bar.baz,
 
-  // recursive_dynamic_fields
+  # recursive_dynamic_fields
   let x = "foo" in {"%{x}" = bar, bar = 1} == {foo = 1, bar = 1},
   ({"%foo"."%bar".baz = other + 1, other = 0}."%foo"."%bar".baz == 1),
 ]
diff --git a/tests/pass/records.ncl b/tests/pass/records.ncl
index f5522ce0..735cd57c 100644
--- a/tests/pass/records.ncl
+++ b/tests/pass/records.ncl
@@ -1,7 +1,7 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // accesses
+  # accesses
   ({foo = 3, bar = true}).bar == true,
   {"%{if true then "foo" else "bar"}" = false, bar = true}.foo
     == false,
@@ -12,7 +12,7 @@ let Assert = fun l x => x || %blame% l in
 
   ({bar = 3}$["foo" = true]).foo == true,
 
-  // primitive_ops
+  # primitive_ops
   record.has_field "foo" {foo = 1, bar = 2},
   record.has_field "fop" {foo = 1, bar = 2} == false,
   record.has_field "foo" ({foo = 2, bar = 3} -$ "foo")
@@ -20,7 +20,7 @@ let Assert = fun l x => x || %blame% l in
 
   record.has_field "foo" ({bar = 3}$["foo" = 1]),
 
-  // lazyness of map
+  # lazyness of map
   (record.map (fun x y => y + 1) {foo = 1, bar = "it's lazy"}).foo
     == 2,
 
@@ -29,7 +29,7 @@ let Assert = fun l x => x || %blame% l in
       {foo = 1, bar = "it's lazy"} in
     (r.foo) + (r.bar) == 2,
 
-  // merging
+  # merging
   {a = 1} & {b=true} == {a = 1, b = true},
   {a = 1, b = 2} & {b = 2, c = 3}
     == {a = 1, b = 2, c = 3},
@@ -40,7 +40,7 @@ let Assert = fun l x => x || %blame% l in
   {a = `A, b = `B} & {a = `A, c = `C}
     == {a = `A, b = `B, c = `C},
 
-  // merge_complex
+  # merge_complex
   let rec1 = {
       a = false,
       b = if true then (1 + 1) else (2 + 0),
@@ -59,15 +59,15 @@ let Assert = fun l x => x || %blame% l in
     } in
     rec1 & rec2 == result,
 
-  // merge_with_env
+  # merge_with_env
   (fun y => ((fun x => {a=y}) 1) & ({b=false})) 2
     == {a = 2, b = false},
 
-  // merge_with_env_nested
+  # merge_with_env_nested
   {b={c=10}} & ((fun x => {a=x, b={c=x}}) 10)
     == {a=10, b = {c = 10}},
 
-  // recursive_records
+  # recursive_records
   {a = 1, b = a + 1, c = b + a} == {a = 1, b = 2, c = 3},
   {f = fun x y =>
       if x == 0 then y else f (x + (-1)) (y + 1)
@@ -84,7 +84,7 @@ let Assert = fun l x => x || %blame% l in
     }.f 10 in
   with_res "done" == "done",
 
-  // piecewise signatures
+  # piecewise signatures
   {
       foo : Num,
       bar = 3,
@@ -97,9 +97,9 @@ let Assert = fun l x => x || %blame% l in
   }.bar == 1,
   let {foo : Num} = {foo = 1} in foo == 1,
 
-  // recursive overriding with common fields
-  // regression tests for [#579](https://github.com/tweag/nickel/issues/579)
-  // and [#583](https://github.com/tweag/nickel/issues/583)
+  # recursive overriding with common fields
+  # regression tests for [#579](https://github.com/tweag/nickel/issues/579)
+  # and [#583](https://github.com/tweag/nickel/issues/583)
   ({foo.bar = foo.baz, foo.baz | default = 2} & {foo.baz = 1}).foo.bar == 1,
   let Name = fun b label name => if b then "hijack" else contract.blame label in
   let Config = {
diff --git a/tests/pass/serialize-package.ncl b/tests/pass/serialize-package.ncl
index b4c135a5..1f865652 100644
--- a/tests/pass/serialize-package.ncl
+++ b/tests/pass/serialize-package.ncl
@@ -10,7 +10,7 @@ let ctr = {
                   The list of inputs for this package, specified as a
                   `NixPackage`."
                 | Array NixPackage,
-    // Many more missing
+    # Many more missing
   },
 
   Shell = Derivation & {},
diff --git a/tests/pass/strings.ncl b/tests/pass/strings.ncl
index 7543275f..7599785a 100644
--- a/tests/pass/strings.ncl
+++ b/tests/pass/strings.ncl
@@ -1,7 +1,7 @@
 let Assert = fun l x => x || %blame% l in
 
 [
-  // interpolation
+  # interpolation
   "simple %{"interp" ++ "olation"} here" == "simple interpolation here",
   "%{"alone"}" == "alone",
   "nested %{ "%{(fun x => "%{x}") "expression"}" }" == "nested expression",
@@ -11,12 +11,12 @@ let Assert = fun l x => x || %blame% l in
     "Hello, %{x}! Welcome in %{let y = "universe" in "the %{x}-%{y}"}")
     == "Hello, world! Welcome in the world-universe",
 
-  // regression test for issue #361 (https://github.com/tweag/nickel/issues/361)
+  # regression test for issue #361 (https://github.com/tweag/nickel/issues/361)
   m%""%{"foo"}""%m == "\"foo\"",
   m%"""%m == "\"",
   m%""%"%"%"%m == "\"%\"%\"%",
 
-  // regression test for issue #596 (https://github.com/tweag/nickel/issues/596)
+  # regression test for issue #596 (https://github.com/tweag/nickel/issues/596)
   let s = "Hello" in m%%""%%{s}" World"%%m == "\"Hello\" World",
   let s = "Hello" in m%%""%%%{s}" World"%%m == "\"%Hello\" World",
   m%%""%%s"%%m == "\"%%s",
diff --git a/tests/pass/typechecking.ncl b/tests/pass/typechecking.ncl
index e339b523..12b8aa0d 100644
--- a/tests/pass/typechecking.ncl
+++ b/tests/pass/typechecking.ncl
@@ -1,5 +1,5 @@
 let typecheck = [
-  // basics
+  # basics
   true : Bool,
   false : Bool,
   0 : Num,
@@ -10,18 +10,18 @@ let typecheck = [
   (true | Num) : Num,
   "hello" : Str,
 
-  // functions
+  # functions
   (fun x => if x then x + 1 else 34) false,
   let id : Num -> Num = fun x => x in (id 4 : Num),
-  // the id parameter is inferred
+  # the id parameter is inferred
   (fun id => (id 4 : Num)) (fun x => x),
-  // non strict zones don't unify
+  # non strict zones don't unify
   (fun id => (id 4) + (id true: Bool)) (fun x => x),
-  // contracts are opaque types
+  # contracts are opaque types
   (let AlwaysTrue = fun l t => if t then t else %blame% l in
   ((fun x => x) : AlwaysTrue -> AlwaysTrue)),
 
-  // simple_polymorphism
+  # simple_polymorphism
   let f : forall a. a -> a = fun x => x in
     ((if (f true) then (f 2) else 3) : Num),
 
@@ -31,7 +31,7 @@ let typecheck = [
   let f : forall a. (forall b. b -> b) -> a -> a = fun f x => f x in
     f (fun z => z : forall y. y -> y),
 
-  // forall nested
+  # forall nested
   let f : forall a. a -> a =
       let g | forall a. (a -> a) = fun x => x in
       g in
@@ -48,7 +48,7 @@ let typecheck = [
       g 0 in
     ((if (f true) then (f 2) else 3) : Num),
 
-  // enums_simple
+  # enums_simple
   (`bla : [|bla |]),
   (`blo : [|bla, blo |]),
   (`bla : forall r. [|bla ; r |]),
@@ -56,7 +56,7 @@ let typecheck = [
   ((switch {`bla => 3} `bla) : Num),
   ((switch {`bla => 3, _ => 2} `blo) : Num),
 
-  // enums_complex
+  # enums_complex
   ((fun x => switch {`bla => 1, `ble => 2} x) : [|bla, ble |] -> Num),
   ((fun x => switch {`bla => 1, `ble => 2, `bli => 4} (%embed% bli x))
     : [|bla, ble |] -> Num),
@@ -74,7 +74,7 @@ let typecheck = [
     fun x => switch {`blo => `bla, `ble => `bli, _ => `bla} x in
     f `bli,
 
-  // static records
+  # static records
   ({bla = 1} : {bla : Num}),
   ({blo = true, bla = 1} : {bla : Num, blo : Bool}),
   ({blo = 1}.blo : Num),
@@ -93,35 +93,35 @@ let typecheck = [
   ({ "%{if true then "foo" else "bar"}" = 2, }."%{"bl" ++ "a"}" : Num),
   ({ foo = 3, bar = 4, } : {_ : Num}),
 
-  // seq
+  # seq
   (%seq% false 1 : Num),
   ((fun x y => %seq% x y) : forall a. (forall b. a -> b -> b)),
   let xDyn = if false then true else false in
     let yDyn = 1 + 1 in (%seq% xDyn yDyn : Dyn),
 
-  // arrays_simple
+  # arrays_simple
   [1, "2", false],
-  //TODO: the type system may accept the following test at some point.
-  //([1, "2", false] : Array Dyn),
+  #TODO: the type system may accept the following test at some point.
+  #([1, "2", false] : Array Dyn),
   ["a", "b", "c"] : Array Str,
   [1, 2, 3] : Array Num,
   (fun x => [x]) : forall a. a -> Array a,
 
-  // arrays_ops
+  # arrays_ops
   (fun l => %tail% l) : forall a. Array a -> Array a,
   (fun l => %head% l) : forall a. Array a -> a,
   (fun f l => %map% l f) : forall a b. (a -> b) -> Array a -> Array b,
   (fun l1 => fun l2 => l1 @ l2) : forall a. Array a -> Array a -> Array a,
   (fun i l => %elem_at% l i) : forall a. Num -> Array a -> a,
 
-  // recursive_records
+  # recursive_records
   {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_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,
+  # (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))),}
     : {f : Num -> Num},
@@ -129,7 +129,7 @@ let typecheck = [
   { f = fun x => if x == 0 then 1 else 1 + (f (x + (-1))),}
     : {f : Num -> Num},
 
-  // polymorphic_row_constraints
+  # polymorphic_row_constraints
   let extend | forall c. { ; c} -> {a: Str ; c} = 0 in
     let remove | forall c. {a: Str ; c} -> { ; c} = 0 in
     (let good = remove (extend {}) in 0) : Num,
@@ -137,9 +137,9 @@ let typecheck = [
   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
-  //in a stack overflow.
+  #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
+  #in a stack overflow.
   {gen_ = fun acc x =>
     if x == 0 then
       acc
@@ -150,36 +150,36 @@ let typecheck = [
 
   {f = fun x => f x}.f : forall a. a -> a,
 
-  // shallow_inference
+  # shallow_inference
   let x = 1 in (x + 1 : Num),
   let x = "a" in (x ++ "a" : Str),
   let x = "a%{"some str inside"}" in (x ++ "a" : Str),
   let x = false in (x || true : Bool),
   let x = false in let y = x in let z = y in (z : Bool),
-  // Regression test following, see [#297](https://github.com/tweag/nickel/pull/297). Check that
-  // [apparent_type](../fn.apparent_type.html) doesn't silently convert array literals from `Array
-  // T` (for `T` a type or a type variable) to `Array Dyn`.
+  # Regression test following, see [#297](https://github.com/tweag/nickel/pull/297). Check that
+  # [apparent_type](../fn.apparent_type.html) doesn't silently convert array literals from `Array
+  # T` (for `T` a type or a type variable) to `Array Dyn`.
   {foo = [1]} : {foo : Array Num},
   (let y = [] in y) : forall a. Array a,
 
-  // full_annotations
+  # full_annotations
   let x : Num | doc "some" | default = 1 in x + 1 : Num,
 
-  // Typed import
+  # Typed import
   import "typed-import.ncl" : Num,
 
-  // Regression test for #430 (https://github.com/tweag/nickel/issues/430)
+  # Regression test for #430 (https://github.com/tweag/nickel/issues/430)
   let x = import "typed-import.ncl"
   in x : Num,
 
-  // recursive_records_quoted
+  # recursive_records_quoted
   {"foo" = 1} : {foo : Num},
 
-  // stdlib typechecking:
+  # stdlib typechecking:
   string.length : Str -> Num,
   (string.length "Ok") : Num,
   (string.length "Ok" == 2) : Bool,
-  // partial application
+  # partial application
   (string.split ".") : Str -> Array Str,
   (array.length [] == 0) : Bool,
   (array.map (fun x => x ++ "1") ["a", "b", "c"]) : Array Str,