Skip to content

Releases: tweag/nickel

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](#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

1.6.0

25 Apr 07:53
3441781
Compare
Choose a tag to compare

Version 1.6 (2024-04-25)

Nickel 1.6 is a maintenance release including several bug fixes and improvements, in particular around the features introduced in Nickel 1.5 (enum variants and background evaluation in the LSP).

Core language

Stdlib

Documentation

  • modular-configurations.md: to_lower -> lowercase by @Jasha10 in #1857
  • manual/modular-configurations.md: add argument to std.string.join by @Jasha10 in #1859
  • manual/syntax.md: minor typo by @Jasha10 in #1860

LSP

  • Improve diagnostic location in nls by @jneem in #1856
  • Propagate pending array contracts in permissive_eval by @jneem in #1854
  • Don't leak memory in background eval by @jneem in #1869
  • Add a recursion limit to background evaluation by @jneem in #1878
  • Dedup diagnostics by @jneem in #1883
  • Extend the symbol range to include the rhs by @jneem in #1887
  • Leverage function contract information by @yannham in #1888
  • Fix LSP not showing type signature in untyped code by @yannham in #1889

Tooling

  • Markdown documentation generation: do not insert line breaks by @yannham in #1879
  • [Fix] Nickel doc: fix missing newline in markdown output by @yannham in #1880
  • Fix infinite recursion in doc symbols. by @jneem in #1881

Fixes

New Contributors

Full Changelog: 1.5.0...1.6.0

1.5.0

12 Mar 18:52
13ffc85
Compare
Choose a tag to compare

Nickel 1.5 is a major release (albeit not literally), with new core language features and improved LSP. In particular, Nickel 1.5 introduces:

  • Full blown pattern matching. Patterns were previously restricted to destructuring let-bindings. They can now be used within match expressions as well (which only supported simple enum tags before).
  • Enum variants. Enum variants are a new language construct. Enum variants are enum tags with associated data (they are applied to an argument). They can be seen as form of algebraic data types (ADT). Patterns, enum types, typechecking and other parts of the language are extended accordingly to support them.
  • Background evaluation in the LSP. The LSP now performs evaluation of the current document in the background to report evaluation errors directly in your editor, and in particular contract errors.
  • A new section of the manual on writing modular configurations.

Please refer to the manual for more details on those new features.

Core language

Stdlib

  • Add array.zip_with and array.map_with_index to the standard library by @vkleen in #1797
  • fixed std.array.split_at behavior at right boundary. by @suimong in #1803
  • Update stdlib for ADTs by @yannham in #1822

Tooling

Documentation

  • Add patterns to the syntax section of the manual by @yannham in #1832
  • Improve the description of identifier syntax in the manual by @vkleen in #1839
  • Add subsection on enum types in the manual by @yannham in #1836
  • Fix old CLI syntax in documentation by @cydparser in #1844
  • Add manual section on modular configurations by @yannham in #1841
  • Update/refresh examples using latest Nickel idioms by @yannham in #1849

Fixes

New Contributors

Full Changelog: 1.4.1...1.5.0

1.4.1

25 Jan 19:22
25ea79e
Compare
Choose a tag to compare

This patch release fixes a bug that could lead the contract attached to a field to be silently ignored when extracting this field with the --field CLI argument introduced in 1.3.0. See #1774.

1.4.0

10 Jan 17:57
1fa5a79
Compare
Choose a tag to compare

Version 1.4

Nickel 1.4 is a maintenance release, at the exception of a breaking change (see below).

Breaking changes

  • The curried dot operator added in Nickel 1.3 was implemented the wrong way: the arguments were flipped, meaning that (.) foo bar was bar."%{foo}" instead of the expected foo."%{bar}". While the initial flipped implementation seems more useful for piping operations using the reverse application operator |>, it's inconsistent with all other curried operators, where (<operator>) is always defined as fun x y => x <operator> y. To ensure consistency, and because the initial behavior was an oversight and not a conscious design decision, we decided to change the definition of (.) to match the other curried operator by flipping its arguments.

    To fill the gap, Nickel 1.4 introduces std.record.get with the same definition as the (.) introduced in Nickel 1.3. To migrate from 1.3 to 1.4, you can either flip the arguments of the curried dot as a function (.) whenever possible, or you can just replace it with the new std.record.get.

    (implemented by @yannham in #1752)

Tooling

  • Search for imports in NICKEL_IMPORT_PATH by @jneem in #1716
  • Add a cli param --import-path to specify the search path by @jneem in #1721
  • LSP: Fix hover on assignments to subrecords by @jneem in #1725
  • Print something when nickel doc succeeds by @yannham in #1729
  • Add --error-format flag to serialize err diagnostics by @yannham in #1740

Core language

Fixes

  • format: don't fail silently on invalid input anymore by @yannham in #1749
  • LSP: get record completion in arrays by @jneem in #1746
  • Update Topiary dependencies to handle (.) in nickel format by @yannham in #1753

New Contributors

Full Changelog: 1.3.0...1.4.0

1.3.0

16 Nov 17:01
4798c4d
Compare
Choose a tag to compare

Version 1.3

Version 1.3 includes several new optimizations following reports of long evaluation time for medium-sized codebase. The command-line interface (CLI) has been reworked to be more user-friendly, at the cost of breaking changes: see below. Finally, the LSP has seen continuous improvement as well.

Breaking changes

  • @vkleen improved the CLI UX in numerous ways in #1632

    • The file argument is now argument positional. That is, instead of running nickel export -f config.ncl, now use nickel export config.ncl instead.
    • Every command which can take a file argument can now take several of them. The program parsed from the files are then merged before applying the action. For example, the new nickel export config1.ncl config2.ncl config3.ncl is the equivalent of the previous nickel export <<< '(import "config1.ncl") & (import "config2.ncl") & (import "config3.ncl")'
    • Evaluation is now an explicit subcommand, instead of being the default action. Instead of running nickel -f config.ncl to evaluate a file, use nickel eval config.ncl instead.
  • Not a breaking change per se, because the customize mode is experimental, but @yannham introduced a new syntax for customize mode in #1709. Instead of dynamically generating a CLI where arguments are field paths, the new customize mode CLI directly take assignments written in a Nickel-like syntax as positional arguments. For example, in 1.2, the command:

    $ nickel eval -f confing.ncl -- \
      --input.field1 '"Value"' --input.flag false \
      --override output.bar 0`

    now becomes

    $ nickel eval config.ncl -- \
      'input.field1="Value"' input.flag=false \
      --override output.bar=0`

Fixes

  • Fix record.update by making record.insert act consistently by @yannham in #1669

Tooling

  • LSP:
    • implement type-based completion in the new completer by @jneem in #1577
    • Improve context completion by @jneem in #1584
    • Take the ancestor path into account when env-completing from uncles. by @jneem in #1661
    • Add goto support for pattern bindings by @jneem in #1665
    • Add cousin search to goto and hover by @jneem in #1670
    • Improve hover output for let patterns by @jneem in #1696
    • First prototype of contract evaluation by @jneem in #1672
  • LSP: a large refactoring work by @jneem to get rid of the old and
    hard-to-maintain code analysis implementation
    (#1623,
    #1629,
    #1658,
    #1663)
  • Honor nostdlib in customize mode as well by @vkleen in #1634
  • Add the list subcommand to the customize mode by @yannham in #1709
  • add %eval_nix% primop for Nix interop by @Radvendii in
    #1465 (requires to build with the
    corresponding experimental feature enabled)
  • Get rid of shallow_repr and print full terms in error messages by @yannham in
    #1676
  • Add suggestions to the error message when misspelling a record field by @yannham in #1710
  • Add a --field argument to subcommands to target a specific field whenever it makes sense by @yannham in #1712

Optimizations

Documentation

  • Fix invalid example code in doc of blame_with_message by @bgni in #1689
  • Fix doc, example code for pipe lacks prefix by @bgni in #1692
  • change nickel-nix to organist by @Radvendii in #1691

New Contributors

Full Changelog: 1.2.2...1.3.0

1.2.2

29 Sep 12:11
fe2956b
Compare
Choose a tag to compare

This release contains a fix for code signing on MacOS in the nix build. All other installation methods (cargo and docker) are unchanged.