Skip to content

Releases: tweag/nickel

1.12.2

25 Jun 09:08
b232af7
Compare
Choose a tag to compare

Fix the generated package-enabled binary artifacts (with -pkg). They didn't include the package management experimental feature as initially advertised in 1.12.0 (and 1.12.1) due to an error in the build workflow.

1.12.1

24 Jun 13:36
e35f04e
Compare
Choose a tag to compare

[EDIT: this release is strictly identical to 1.12.0; the pkg fix is actually not included. We keep it to avoid messing with package managers relying on release events, but you should use 1.12.2 instead for the pkg fix]

Fix the generated package-enabled binary artifacts (with -pkg). They didn't include the package management experimental feature as initially advertised in 1.12.0 due to an error in the build workflow.

1.12.0

05 Jun 07:04
11fba54
Compare
Choose a tag to compare

Version 1.12 (2025-06-04)

Nickel 1.12 includes the long-awaited addition of field punning, in the form of include expressions, which makes it easy to re-use a variable as a record field without running into infinite recursion errors or clumsy renamings. If foo is a symbol in the environment (e.g. a variable defined earlier or a function parameter), one can now write { include foo } instead of having to write let foo_ = foo in { foo = foo_ } to put it in a field with the same name. See the syntax section of the manual for more details.

The Nickel CLI now accepts any supported configuration format as file input, making the nickel binary a possible merge engine for JSON, YAML or TOML configurations. for example, nickel export conf1.json conf2.toml --format YAML --output result.yaml will merge a JSON configuration and a TOML configuration into a YAML one using Nickel's merge semantics. Together with the just added --apply-contract argument, it's also possible to use Nickel as a non-invasive validator for existing configurations without needing to convert them to Nickel first. For example, nickel eval config.json --apply-contract schema.ncl will validate config.json against the Nickel contract schema.ncl.

Core language

  • [Feat] Field punning (include expressions) by @yannham in #2241
  • [Feat] Support annotations on included expressions by @yannham in #2252

LSP

  • Add context to error opening trace file in nls by @L0r3m1p5um in #2244
  • Update behavior of debugLog flag in VSCode extension by @L0r3m1p5um in #2257
  • Filter out LSP diagnostics for labels with no message by @jneem in #2263

Tooling

  • Improved error message when subtyping an inhomogeneous record as a dict by @jneem in #2234
  • Only output up to 10 warnings by @jneem in #2239
  • Negation error messages by @jneem in #2242
  • [Feat] Add --apply-contract argument to the CLI by @yannham in #2266
  • [Feat] Determine the format automatically for input files on the CLI by @yannham in #2267

Fixes

New Contributors

Full Changelog: 1.11.0...1.12.0

1.11.0

11 Apr 12:59
3c437b7
Compare
Choose a tag to compare

Nickel 1.11 includes a new experimental package manager. It is integrated directly in the normal Nickel binary, but is not enabled by default: you either need to use a package-enabled pre-built binary (ending with -pkg) or build Nickel from source with the feature package-experimental. Please refer to the new package management chapter of the manual for more details.

Nickel 1.11 also includes a number of additions to the stdlib, improvements in tooling (environment variable passing), the stdlib, the contract system, and string interpolation (many cases don't need the explicit std.to_string anymore). See the detailed changelog below for more details.

The large refactoring splitting up the internal representation into two intermediate representations, started a few minor versions ago and paving the ground for a more efficient interpreter, has been completed. Users should not see much difference, although it already leads to better information in the LSP.

Breaking changes

  • The typechecking of chains of imports has been modified due to the migration to a new internal intermediate representation. Before, when importing file A in a statically typed block, if the imported file was itself a single import of B, and B contained, say, the number 2, then the typechecker would follow the chain and infer the type Number for the initial import of A. Now, the typechecker only looks at the apparent type of A but doesn't follow imports chains further. If the import expression in A doesn't have a type annotation, as in import "B.ncl", its type will be inferred to be Dyn instead.

    If this breaks your code, the solution is to add missing type annotations to the intermediate imports, here import "B.ncl" : Number.

Core language

  • Allow custom contracts to customize the label by @jneem in #2176
  • Automatically convert interpolated values to string by @yannham in #2195

Documentation

  • Describe customize mode in the CLI chapter of the manual by @yannham in #2219

Stdlib

  • Adds a Matches contract to std.string by @jneem in #2172
  • Adds a FieldsMatch contract for validating record fields against a regex by @jneem in #2174
  • Add std.cast by @jneem in #2184

LSP

  • Bump the VSCode extension to 0.4 by @yannham in #2162
  • Support pull diagnostics and use them for testing by @jneem in #2166
  • ADT and package management improvements in nls by @jneem in #2217

Tooling

  • Add support for environment variables sigil @env on the command line by @yannham in #2201
  • Experimental package manager:
    • Package management CLI, part 1 by @jneem in #2146
    • Support for index packages by @jneem in #2175
    • Support for index packages with version resolution. by @jneem in #2183
    • Fix error message for bad package ids by @jneem in #2209

Fixes

1.10.0

11 Feb 15:59
4ba057b
Compare
Choose a tag to compare

Nickel 1.10 includes various bug fixes and quality of life improvements. Nickel now comes with more prebuilt binary packages (adding Windows and arm-based MacOS), is now built with LTO (Link-Time Optimization), and comes with official python bindings to be published on PyPI together with this release.

Under the hood, a lot of work has been devoted to internal refactorings in order to prepare the implementation of a bytecode compiler and virtual machine (RFC007). Those changes shouldn't have any noticeable effects currently for users.

Breaking changes

  • Record freezing (#2113, #2131). To fix an unsound and unexpected behavior appearing when first altering a record with dictionary operations (std.record.remove, std.record.insert or std.record.update - see #1877) and then overriding it, the aforementioned stdlib operations now freeze the returned record, which removes the possibility of performing further recursive overriding.

    Typically, the record returned by one of those operations is a static dictionary instead of a record with recursive dependencies. While you can still override specific fields through merging, the information about internal dependencies is lost and their reverse dependencies won't be updated automatically.

Documentation

Stdlib

  • Add the package std module by @jneem in #2104
  • Fix empty capture groups in regexes by @jneem in #2109
  • Add filter_map, dedup and some variants to the stdlib by @yannham in #2120

LSP

Tooling

New Contributors

Full Changelog: 1.9.1...1.10.0

1.9.1

19 Dec 15:02
32f7ecc
Compare
Choose a tag to compare

This patch release fixes a bug in NLS (the Nickel Language Server) that would make it crash unexpectedly in some circumstances (#2125).

1.9.0

12 Nov 17:45
7236f8e
Compare
Choose a tag to compare

Nickel 1.9 includes various bug fixes and quality of life improvements.

Noteworthy additions are:

  • let-blocks: declaring several variables at once instead of chaining
    let ... in ...
  • explicit import: the ability to specify explicitly the format of an imported
    file (it was based on the file extension implicitly and would default
    to Nickel), e.g. as import "foo.txt" as 'Json or import "bar.ncl" as 'Text.
  • the addition of a nickel test command that can extract snippets from the
    in-code documentation (the | doc metadata) together with their expected
    result and run them. The feature is detailed in a new CLI chapter of the user
    manual.

Two important future evolutions have been designed and discussed through RFCs:
package management and a performant bytecode virtual machine. Those features
aren't implemented yet, but the initial designs have been agreed upon.

Breaking changes

  • Formatting: the formatting of let bindings has been fixed and improved. To
    avoid a large, irrelevant diff on your next commits, we advise formatting your
    whole codebase first after upgrading to 1.9 in a separate commit.

Core language

  • Let blocks by @jneem (#2010,
    #2031,
    #2051)
  • Fix unsound record contract deduplication by @yannham in #2042
  • Explicit import format: import "sample.html" as 'Text by @vi
    (#2036,
    #2070)
  • Thunks for resolved imports (detect import infinite loops and avoid work duplication) by @jneem in #2052
  • Use a persistent vector to represent arrays instead of an Rc<[..]> by @jneem in #2057

Documentation

LSP

  • Remove the option for an external formatter in nls by @jneem in #2064
  • Fix completions in incomplete field name position. by @jneem in #2069
  • Bound the length of nls completions by @jneem in #2073

Tooling

  • Add --format argument to nickel query command by @suimong in #2015
  • Adds a nickel test subcommand for testing examples in docs. by @jneem in #2020
  • Detect infinite recursions in nickel doc by @yannham in #2055
  • Strict typechecking mode by @jneem in #2077
  • Switch to toml-edit for spanned deserialization fixing TOML deserialization bug by @jneem in #2074
  • Make serde-wasm-bindgen optional in core by @akavel in #2089
  • Move 'clap' crate dependency behind feature flag in core by @akavel in #2090

New Contributors

Full Changelog: 1.8.1...1.9.0

1.8.1

17 Sep 12:52
0279208
Compare
Choose a tag to compare

This releases includes a fix to a bug discovered by @alialabbas, which has been introduced in 1.3.0 with the contract deduplication optimization.

The contract deduplication optimization would eliminate some contracts unduly, because the optimizer wrongly deemed them equivalent to another contract already applied to the same value. This could result in some record contracts being potentially silently ignored in specific conditions, letting wrong values slip through.

See #2041 for more details.

1.8.0

09 Sep 14:48
c587e35
Compare
Choose a tag to compare

Version 1.8 (2024-09-09)

After a summer break, the team is happy to release Nickel 1.8!

This release ships with an important rework of the contract system, and in particular the interface of custom contracts. The new system is more intuitive for users implementing their own contracts, and makes it possible to use a limited form of boolean logic on contracts that have been added to the stdlib (std.contract.one_of, std.contract.all_of, std.contract.not,
std.contract.check).

We advise reading the updated manual section on writing custom contracts and to migrate your custom contracts to take advantage of the simplification of the interface and those new operators. Most custom contracts can likely be implemented as validators (see std.contract.from_validator).

The contract system rework is backward compatible and existing custom contracts will continue to work as before. Though in the future, Nickel will probably emit a warning of deprecation when a custom contract is defined as a naked function instead of using one of the new contract constructors.

A limited form of subtyping has been added in 1.8 as well, making it easier to use records as dictionaries in statically typed code. A new paragraph has been added to the typing chapter of the manual accordingly.

Breaking changes

  • Formatting: to better accommodate the new contract system, the formatting of
    function applications and definitions have been changed. To avoid a large,
    irrelevant diff on your next commits, we advise formatting your whole
    codebase first after upgrading to 1.8 in a separate commit.

Core language

  • Contract system rework:
    • Do not evaluate types away by @yannham in #1954
    • Add a contract node to the AST by @yannham in #1955
    • Add dedicated node and constructor for general custom contracts by @yannham in #1964
    • Introduce validators for building custom contracts by @yannham in #1970
    • Split contracts into an immediate part and a delayed part by @yannham in #1975
    • Re-introduce unified representation for custom contracts, migrate builtin contracts by @yannham in #1987
  • Allow some function equality comparison by @yannham in #1978
  • Dictionary subtyping:
    • Add a subsumption rule between record types and dictionary types by @Eckaos in #1977
    • Add array constructor to subsumption rule by @Eckaos in #1991
    • Add dictionary constructor to subsumption rule by @Eckaos in #1998
    • Add record constructor to subtyping by @Eckaos in #2007
  • Add record/split_pair and record/disjoint_merge by @yannham in #1982
  • Optimize std.contract.Equal using %record/split_pair% by @yannham in #1988
  • [Optimization] Cache contract generation and pre-compile some match expression by @yannham in #2013
  • Fix and improve contract generation optimization for static types by @yannham in #2017

Stdlib

Documentation

LSP

Tooling

New Contributors

Full Changelog: 1.7.0...1.8.0

1.7.0

13 Jun 23:50
af99d71
Compare
Choose a tag to compare

Version 1.7 (2024-06-11)

Note: the previous 1.7 released pointed to the wrong revision and was deleted. Although the attached artifacts and the tarball would still include all the actual 1.7 features, the nickel and nls binary would identify as 1.6 when using nickel --version. This release is identical to the previous one but points to the right revision with the version numbers up to date.

Nickel 1.7 ships with several extensions to pattern matching which was introduced in Nickel 1.5 but had a number of limitations. See below for further details. Releases on other platforms that GitHub (such as crates.io) are unaffected.

Additionally, the publication of Topiary to the crates registry makes it so that all versions of Nickel from 1.7 and onward, however they are built, ship with nickel format and the language server formatting command working out of the box without needing a separate installation of Topiary (which was previously required when installing from crates.io using cargo install nickel-lang-cli or cargo install nickel-lang-lsp).

Breaking changes

  • Although primitive operators are internal and aren't officially part of any stability guarantee, some libraries sometimes need to resort to using them, when there's no equivalent in the stdlib. Nickel 1.7 had a big primop refactoring, amounting mostly to renaming. If you're using primops, please look at the corresponding pull request

  • The behavior of destructuring has been changed to match exactly the behavior of pattern matching. While there should be no difference on well-behaving programs, this change makes destructuring stricter and can lead to some programs that were running fine before 1.7 to now fail with unmatched pattern. The typical example is when destructuring a record with a field that is not present: let {x,y, ..} = import "lib.ncl" in. If x is absent from the lib.ncl but is never used anywhere, this used to work fine before 1.7 (the error would only trigger upon usage of x) but will now fail eagerly.

    If you need to fix a large codebase with long import destructuring chains and you don't know which fields are the offending ones, one possible technique is to open the importing file in an editor and use the goto definition command of the NLS on each field of a faulty pattern. If it works, the field is present, but if it doesn't, the field might be faulty. You can also apply a record contract mimicking the structure of the pattern to the import "..." expression to get better error reporting.

Core language

  • Patterns now support constant values (1, null, "a", etc.), array
    patterns ([fst, snd, ..tail]), pattern guards ('Foo x if std.is_number x), wildcard patterns (_ placeholder) and or-patterns (('Foo x) or ('Bar x) or ('Baz x)): (see the syntax section of the manual for more details)
  • Uniformize destruct and pattern matching logic by @yannham in #1907
  • Opaque values by @jneem in #1913

Stdlib

  • Add record.get_or to get value from record supplying default value by @olorin37 in #1920
  • [Fix] Avoid record.get_or failing on field without definition by @yannham in #1946
  • Add stdlib function array.at_or by @olorin37 in #1927
  • Add std.enum.(from/to)_tag_and_arg and std.enum.map to dynamically decompose and recompose an enum by @yannham in #1939
  • Add std.test module with Assert and assert_all function to testing by @ajbt200128 in #1914

Documentation

LSP

  • Tell NLS about variable bindings in match statements by @jneem in #1926
  • Add --version support to NLS and fix feature unification issues by @yannham in #1936
  • Fix NLS crash and better refresh diagnostics by @jneem in #1944

Tooling

  • Include field path in non serializable error by @yannham in #1905
  • Allow single input to nickel xxx command to be JSON, YAML or TOML as well by @olorin37 in #1902
  • Use Topiary's published crates over git to always enable formatting by @ErinvanderVeen in #1919

New Contributors

Full Changelog: 1.6.0...1.7.0