Releases: tweag/nickel
1.7.0
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
. Ifx
is absent from thelib.ncl
but is never used anywhere, this used to work fine before 1.7 (the error would only trigger upon usage ofx
) 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 theimport "..."
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
andstd.enum.map
to dynamically decompose and recompose an enum by @yannham in #1939 - Add
std.test
module withAssert
andassert_all
function to testing by @ajbt200128 in #1914
Documentation
- Fix typo in BlameError documentation by @ErinvanderVeen in #1899
- Update README.md for nix profile install by @cloudyluna in #1918
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
- @olorin37 made their first contribution in #1902
- @cloudyluna made their first contribution in #1918
- @ajbt200128 made their first contribution in #1914
Full Changelog: 1.6.0...1.7.0
1.6.0
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
- Extend merge to enum variants by @yannham in #1862
- [Fix] Allow multiple underscore to start identifiers by @yannham in #1884
Stdlib
- Add
std.string.find_all
by @fuzzypixelz in #1870 - Add empty optional fields-aware record operator variants by @yannham in #1876
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
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
- Allow metadata keywords in field position by @yannham in #1768
- Support other bases than decimal for num literals by @yannham in #1798
- Enum variants:
- Structural ADTs: first step by @yannham in #1770
- Implement equality on ADTs by @yannham in #1787
- Fix laziness closurization bug, add support for ADTs by @yannham in #1789
- ADT destructuring by @yannham in #1812
- Enum tag destructuring by @yannham in #1813
- Implement ADT contracts by @yannham in #1821
- Introduce application syntax for ADTs by @yannham in #1825
- Relax enum row conflicts by @yannham in #1831
- Properly force enum variants by @yannham in #1835
- Fix enum contract stripping unwrapping variant argument by @yannham in #1833
- Pattern matching:
- [Refactor] Pattern matching by @yannham in #1799
- Record pattern compilation by @yannham in #1816
- Enum pattern compilation by @yannham in #1817
- [Refactor] Pattern positions by @yannham in #1819
- Full pattern matching by @yannham in #1820
- Support pattern contracts in match statement by @yannham in #1823
- Fix the semantics of default values in patterns by @yannham in #1826
- Specialized pattern compilation for enum tags by @yannham in #1846
Stdlib
- Add
array.zip_with
andarray.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
- LSP: Add "goto definition" support for the import term by @jneem in #1756
- LSP: Add support for NICKEL_IMPORT_PATH environment variable @jneem in #1795
- LSP: Improved reference-finding by @jneem in #1800
- LSP: rename action by @jneem in #1811
- LSP: evaluation in the background by @jneem in #1814
- LSP: Improve document symbols by @jneem in #1848
- Add more spacing to contract error messages by @yannham in #1767
- Proper error message for non exhaustive match by @yannham in #1772
- Add InvalidContractError by @yannham in #1824
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
- Check if stderr is a terminal for error messages by @vkleen in #1766
- correctly drop Array::IntoIter by @Radvendii in #1773
- LSP: vendor codespan, and fix character offset issues by @jneem in #1793
- [Fix & Refactor] Row conflict error by @yannham in #1808
- Fix unbound identifier when querying in REPL by @yannham in #1843
- Fix --field not applying pending contracts by @yannham in #1778
New Contributors
- @cydparser made their first contribution in #1844
Full Changelog: 1.4.1...1.5.0
1.4.1
1.4.0
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
wasbar."%{foo}"
instead of the expectedfoo."%{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 asfun 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 newstd.record.get
.
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
- Support importing txt files as strings by @Quantum64 in #1734
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
(.)
innickel format
by @yannham in #1753
New Contributors
- @Quantum64 made their first contribution in #1734
- @kukimik made their first contribution in #1741
Full Changelog: 1.3.0...1.4.0
1.3.0
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 usenickel 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 previousnickel 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, usenickel eval config.ncl
instead.
- The file argument is now argument positional. That is, instead of running
-
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
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
- Contract elision for static types by @yannham in #1671
- Implement contract deduplication optimization by @yannham in #1631
- Array contract deduplication by @yannham in #1674
- Get rid of most generated variables by @yannham in #1679
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
1.2.1
1.2.0
Version 1.2
Version 1.2 comes with several improvements on the LSP and other components of the Nickel tooling. The new customize mode of the CLI makes it possible to dynamically turn a configuration into a command-line interface, which you can interact with.
Several related long-standing issues and limitations when typechecking polymorphic functions are also finally fixed.
Core language
- Make the lexer accept scientific notation by @vkleen in #1456
- Improve polymorphism handling, bidirectional typechecking and fix unsound generalization by @yannham in #1372
- Error on serializing very large numbers by @vkleen in #1470
- Import YAML files containing multiple documents as arrays by @vkleen in #1497
- Normalize line endings in string literals during parsing (Windows compatiblity) by @vkleen in #1562
- Implement curried dot operator by @suimong in #1578
- Statically merge partial record definitions by @vkleen in #1599
- Disable recursive priorities by @yannham in #1600
Fixes
- Various fixes to the pretty-printer by @vkleen (#1411, #1412, #1410, #1417)
- Fix REPL panic on transitive imports by @Radvendii in #1474
- Fix contract application order in let bindings and annotations by @vkleen in #1544
- Fix cursor desyncing when using REPL by @deotimedev in #1546
- Fix handling of relative imports @jneem in #1489
- LSP Fix two issues with incomplete input by @jneem in #1550
- Fix incomplete check of record row constraints by @yannham in #1558
- Fix LSP regression on hovering by @yannham in #1583
Tooling
- Full vscode extension by @szlend and @yannham in (#1405, #1413, #1416)
- Invalidate importers in NLS (plus a couple other import-related issues) by @jneem in #1426
- Improve
nickel query
(and:query
in the REPL) interface by @yannham in
#1447 - Topiary integration (formatting) as
nickel format
by @vkleen in #1371 - LSP: various improvements to completion by @jneem (#1450, #1473)
- Improve doc extraction capabilities through
nickel doc
(evaluate terms before extracting documentation) by @vkleen in #1463 - LSP Fix persistent diagnostics by @jneem in #1478
- Restore --version for CLI, include git revision by @yannham in #1486
- Disable the colors when stdout isn't a tty by @thufschmitt in #1508
- Improve type variables name allocation when reporting type errors by @yannham in #1512
- LSP formatting without calling the topiary binary by @vkleen in #1526
- LSP Initial handling of incomplete input by @jneem in #1541
- LSP resolve imports for incomplete inputs also by @jneem in #1542
- Add multiline string support for VSCode autoclosing pairs by @deotimedev in #1553
- Display icon for nickel file in vscode explorer by @suimong in #1556
- New experimental customize mode CLI to interact with a configuration on the
command line (seenickel help export
) by @Radvendii and @yannham in
#1475 - (LSP) Import completion by @deotimedev in #1561
- Get rid of uninformative generic notes for higher-order contract errors by @yannham in #1564
- Render hover documentation as Markdown in LSP by @deotimedev in #1559
- Exit with nonzero exit code on failure by @vkleen in #1576
Stdlib
- add
std.contract.Sequence
by @Radvendii in #1452
Documentation
- manual docs: fix mismatch between input command and its echo in the output by @foo-jin in #1421
- Add two examples: imports and foreach pattern by @mipmip in #1387
- Fix some leftover instances of the old enum syntax in the manual by @vkleen in #1548
New Contributors
- @szlend made their first contribution in #1405
- @foo-jin made their first contribution in #1421
- @nrhtr made their first contribution in #1454
- @deotimedev made their first contribution in #1547
- @suimong made their first contribution in #1556
Full Changelog: 1.1.1...1.2.0
1.1.1
This version mostly includes bugfixes and stdlib improvement since 1.0
. 1.1.0
has been immediately followed by 1.1.1
, because of a missing README issue on the new nickel-lang-cli
crate published to crates.io. Because crates on crates.io are immutable, we had to bump the minor version.
IMPORTANT: The main crate nickel-lang
has been split between nickel-lang-cli
(the binary) and nickel-lang-core
(the library). If you're using cargo
to install Nickel, please uninstall the previous crate by running cargo uninstall nickel-lang
, and from now one use cargo install nickel-lang-cli
to install 1.1 and do further updates.
Stdlib
- Encode more pre-conditions of stdlib functions as additional contracts,
replacing dynamic type errors with nice contract errors by @yannham in #1358 - ArraySliceFun incorrectly excluded the length of the array as the end index by @vkleen in #1396
Tooling
- Improve the pretty printing of terms in the CLI and within error messages @vkleen in #1262
- Fix LSP panic when importing JSON by @yannham in #1382
- Fix LSP hanging under certain conditions involving external imports by @yannham in #1390
- Better error message when contract makes certain rows illegal by @Radvendii in #1323
- Fix function params hovering in the LSP by @yannham in #1395
- Fix LSP infinite loop on hovering on external imports by @yannham in #1397
Fixes
- Fixes incorrect variable names in type mismatch errors by @vkleen in #1313
- Improve error messages for polymorphic tail parametricity violations by @matthew-healy in #1320
- Fix panic on duplicated top-level idents in record destructuring by @matthew-healy in #1324
- Prevent panic when parsing record type with field path by @matthew-healy in #1325
- Give a better error message when trying to query a non-record by @jneem in #1326
- Fix error position by @jneem in #1333
- Fix panic when interpolating fields in a record type by @jneem in #1332
- Fix type annotations not generating contracts by @yannham in #1379
- Fix typechecker looping by adding missing check for unifying equal type vars by @yannham in #1400
- Fix panic on function contract failure (position of arrow functions not set) by @yannham in #1407