In Nickel 1.16, unicode characters can be escaped in strings using the
\u{1f923} syntax. It also fixes a few bugs in the interpreter and the language
server, and has some performance improvements in the language server.
- Allow unicode escape sequences in string literals by @L0r3m1p5um in #2520
- Fix panic when deserializing a too-large yaml number by @jneem in #2485
- Fix panic from unclosurized CLI overrides by @jneem in #2498
- Format nickel converted from other formats by @L0r3m1p5um in #2502
- Better localization of
std.fail_witherrors by @yannham in #2505 - Add a welcome message to the repl by @jneem in #2509
- Export NickelException in py-nickel. by @jneem in #2517
- Allow priority to be set for background evaluation in the LSP by @L0r3m1p5um in #2493
- Performance improvements for language server by @L0r3m1p5um in #2510
- Request cancellation for language server by @L0r3m1p5um in #2523
- Fix a missing closurization that was hiding some errors by @jneem in #2486
For several releases now, the runtime representation of Nickel expressions has been completely reworked behind the scenes for improved performance. Nickel 1.15 is the first version to migrate to the new representation. Our microbenchmarks show run time improvements since 1.14 on every single benchmark, ranging from 10% to 65%. On a large real-world configuration that was supplied to us by a user, run-time decreased by 40% and peak memory usage decreased by 50%. Most of these performance improvements were work of @yannham, most notably in #2302.
This release is also the first to provide a public API for Nickel as a library,
designed and implemented by @jneem. Some intrepid users were already embedding
the nickel_lang_core crate, and this remains the only way to access certain
internal features. However, we hope that most users will find it easier to use
the nickel_lang crate, which is simpler, better documented, and changes less
often. We also now have a public C API: the header file is available as a
release artifact, as are pre-built libraries for various architectures. Finally,
a go-lang API is available at https://github.com/nickel-lang/go-nickel.
- Add a YamlDocuments export format by @jneem in #2445
This change adds a new supported format
'YamlDocumentstostd.serializeandstd.deserialize. While standard calls toserializeordeserializeshould not be impacted even in statically typed code, this can be a breaking change if you copied the stdlib's format enum type in an annotation, for example:my_serialize : [| 'Json, 'Yaml, 'Toml, 'Text |] -> [...]. In this case, you must update such enum types. Run any evaluation or typehecking command on your codebase and simply let the typechecking errors guide you.
- NLS completions can now see through the built-in any_of, all_of and Sequence contracts by @jneem in #2391
- NLS can now report errors in YAML files by @jneem in #2383
- Better error messages for incomplete records, thanks to typechecking changes by @L0r3m1p5um in #2439
- New public rust and C apis by @jneem in #2378 and #2360
- Add locations to json by @jneem in #2382 and #2388
- Add note to error when arrays are merged piecewise in a record by @L0r3m1p5um in #2420
- Better error message for undefined record field by @jneem in #2427
- Allow the input format of stdin to be specified in the CLI by @L0r3m1p5um in #2435
- Adds a convert command by @jneem in #2437
- [RFC007] Migrate to the new compact value representation by @yannham in #2302
- [RFC007] Reduce
Termsize, chapter: functions by @yannham in #2409 - [RFC007] Reduce
Termsize, chapter:letby @yannham in #2410 - [RFC007] Reduce
Termsize, chapter: recursive records (revival) by @yannham in #2413 - [RFC007] Reduce
Termsize, chapter:Op1,Op2&OpNby @yannham in #2414 - [RFC007] Reduce
Termsize, chapter:Sealedby @yannham in #2415 - [RFC007] Reduce
Termsize, chapter:Annotatedby @yannham in #2416 - Fix large error types in
coreby @yannham in #2417 - [RFC007] Reduce
Termsize, chapter: errors by @yannham in #2421 - perf: reduce memory consumption of the stack by @yannham in #2442
- perf: optimize term and metadata representation by @yannham in #2451
- Pattern compilation improvements by @jneem in #2443 and #2453
- perf: store thunk data directly in value blocks by @yannham in #2455
- perf: rework ref counting to look like std::rc::Rc by @yannham in #2456
- perf: remove useless reserve by @yannham in #2457
- perf: optimize the label representation by @yannham in #2448
- perf: buffer output by @jneem in #2466
- Add base64 encoding and decoding functions to stdlib by @L0r3m1p5um in #2444
Nickel 1.14 has no core language changes. It adds position information to YAML documents, so that if some imported YAML breaks a contract then Nickel can blame the correct location in the YAML file. Nickel's LSP has had some bugfixes (thanks to @L0r3m1p5um), fixing a crash and avoiding stale data.
- Implement textDocument/didClose method for LSP by @L0r3m1p5um in #2323
- Pass sources from World into background eval by @L0r3m1p5um in #2338
- Avoid copying file contents in LSP eval by @L0r3m1p5um in #2347
- Fix crash in NLS when creating typechecking diagnostics by @L0r3m1p5um in #2357
- Fix performance of UsageLookup by @jneem in #2339
- Allow index packages to live in subdirectories of the repo by @jneem in #2315
- Convert to saphyr for positions in yaml by @jneem in #2332
- Initial public api rfc by @jneem in #2337
- Clean up Ident conversions to reduce accidental allocations by @jneem in #2341
- Declare MSRV as 1.85 by @brandonweeks in #2364
- Narrow serde_with features by @brandonweeks in #2366
- Bump malachite to version 0.6 by @brandonweeks in #2367
- Bump toml to version 0.9 and toml_edit to version 0.23 by @brandonweeks in #2368
- Plumb custom_transform into EntryState to minimize traversal by @twitchyliquid64 in #2346
- Restore the static nix release jobs by @jneem in #2373
- Fix broken note and other cosmetic changes in pkg manual by @yannham in #2329
- @brandonweeks made their first contribution in #2364
- @twitchyliquid64 made their first contribution in #2346
Nickel 1.13 includes various bug-fixes and some improvements to error messages, but no core language changes. There has been substantial work towards a new runtime representation, which will eventually reduce the interpreter's memory usage substantially (and it is also a step towards the upcoming bytecode interpreter).
- Fix cache miss when pulling source file by a relative path by @L0r3m1p5um in #2276
- Publish diagnostics for parsing errors in imported files by @L0r3m1p5um in #2299
- Wrap App arguments in atoms by @jneem in #2287
- Print more information for git errors by @jneem in #2283
- [RFC007] Improve the runtime value representation (not yet used by the interpreter) by @yannham in #2282, #2288, #2290, #2297, #2303
- Add format --check by @bthmc in #2309
- [nix-experimental] Provide the proper base path to Nix with
%eval_nix%by @yannham in #2314
- Fix formatting of doc/manual/package-management.md by @yannham in #2274
- Fix missing package field in package manual example by @yannham in #2275
- Update examples to use latest Nickel idioms by @yannham in #2289
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.
- [Feat] Field punning (include expressions) by @yannham in #2241
- [Feat] Support annotations on included expressions by @yannham in #2252
- 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
- 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-contractargument to the CLI by @yannham in #2266 - [Feat] Determine the format automatically for input files on the CLI by @yannham in #2267
- Don't quote enum tag keywords by @jneem in #2232
- Remove the unused merge keyword by @jneem in #2243
- Bigger stack on windows by @jneem in #2260
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.
-
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 typeNumberfor 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 inimport "B.ncl", its type will be inferred to beDyninstead.If this breaks your code, the solution is to add missing type annotations to the intermediate imports, here
import "B.ncl" : Number.
- Allow custom contracts to customize the label by @jneem in #2176
- Automatically convert interpolated values to string by @yannham in #2195
- Describe customize mode in the CLI chapter of the manual by @yannham in #2219
- 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
- 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
- Add support for environment variables sigil @env on the command line by @yannham in #2201
- Experimental package manager:
- Fix panic with multiple contracts on field by @yannham in #2199
- Traverse enum variants by @jneem in #2214
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.
-
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.insertorstd.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.
- Mention any_of as alternative to enum by @yannham in #2119
- Link to the CLI chapter in the manual intro by @yannham in #2144
- Add the package std module by @jneem in #2104
- Fix empty capture groups in regexes by @jneem in #2109
- Add
filter_map,dedupand some variants to the stdlib by @yannham in #2120
- Add support for packages to nickel-lang-core by @jneem in #2094
- Add support warnings by @jneem in #2086
- Fixed
Debugimpl ofEvalOrDeserErrorprinting entire source of files by @rben01 in #2118 - Do deep eval for doctests by @jneem in #2110
- pass thru feature
nix-experimentalby @KiaraGrouwstra in #2132 - Add github action for packaging and publishing python packages to PyPI (#1592) by @vlcek in #2126
- Include a release artifact for nls by @jneem in #2139
- Update rustyline to 15.0 by @neuschaefer in #2142
- Add LTO to static builds by @jneem in #2147
- Add import_paths parameter to Python bindings by @yannham in #2157
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 'Jsonorimport "bar.ncl" as 'Text. - the addition of a
nickel testcommand that can extract snippets from the in-code documentation (the| docmetadata) 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.
- 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.
- Let blocks by @jneem (#2010, #2031, #2051)
- Fix unsound record contract deduplication by @yannham in #2042
- Explicit import format:
import "sample.html" as 'Textby @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
- Add a manual chapter for the cli. by @jneem in #2065
- [RFC006] Package management by @jneem in #1983
- [RFC007] Bytecode interpreter by @yannham in #2045
- 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
- Add
--formatargument tonickel querycommand by @suimong in #2015 - Adds a
nickel testsubcommand for testing examples in docs. by @jneem in #2020 - Detect infinite recursions in
nickel docby @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
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. A lot of custom contract can most 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 constructor.
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.
- 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.
- 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 record/split_pair and record/disjoint_merge by @yannham in #1982
- Optimize
std.contract.Equalusing %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
- Comparisons for number, string, array, and record by @jeremyschlatter in #1985
- Add boolean contract combinators to the stdlib by @yannham in #1995
- Add short-circuiting fold_left by @jneem in #2000
- Add trigonometric functions, pi, e and log to the number module by @Hugal31 in #2006
- Pass on the contract chapter of the manual by @yannham in #1999
- Adding documentation for subtyping by @Eckaos in #1990
- Combine metadata for completion items instead of choosing arbitrarily. by @jneem in #1940
- Don't blacklist files forever by @thufschmitt in #1973
- Make the LSP configurable by @thufschmitt in #1974
- More aggressive type/contract deduplication on hover by @jneem in #1984
- Add span information for TOML imports by @yannham in #1949
- Update to latest topiary-queries (formatting) by @yannham in #2032
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.
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).
-
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. Ifxis absent from thelib.nclbut 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 definitioncommand 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.
- 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 on of the manual for more details) - Uniformize destruct and pattern matching logic by @yannham in #1907
- Opaque values by @jneem in #1913
- Add
record.get_orto get value from record supplying default value by @olorin37 in #1920 - [Fix] Avoid
record.get_orfailing on field without definition by @yannham in #1946 - Add stdlib function
array.at_orby @olorin37 in #1927 - Add
std.enum.(from/to)_tag_and_argandstd.enum.mapto dynamically decompose and recompose an enum by @yannham in #1939
- Fix typo in BlameError documentation by @ErinvanderVeen in #1899
- Update README.md for nix profile install by @cloudyluna in #1918
- 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
- Include field path in non serializable error by @yannham in #1905
- Allow single input to
nickel xxxcommand 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
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).
- Extend merge to enum variants by @yannham in #1862
- [Fix] Allow multiple underscore to start identifiers by @yannham in #1884
- Add
std.string.find_allby @fuzzypixelz in #1870 - Add empty optional fields-aware record operator variants by @yannham in #1876
- 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
- 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
- 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
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 constructs which 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.
-
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
- Add
array.zip_withandarray.map_with_indexto 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
- 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
- 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
- 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
Nickel 1.4 is a maintenance release, at the exception of a breaking change (see below).
-
The curried dot operator added in Nickel 1.3 was implemented the wrong way: the arguments were flipped, meaning that
(.) foo barwasbar."%{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.getwith 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.(implemented by @yannham in #1752)
- 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
- LSP: get record completion in arrays by @jneem in #1746
- Support importing txt files as strings by @Quantum64 in #1734
nickel format: don't fail silently on invalid input anymore by @yannham in #1749- Update Topiary dependencies to correctly handle
(.)innickel formatby @yannham in #1753
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.
- @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.nclinstead. - 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.nclis 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.nclto evaluate a file, usenickel eval config.nclinstead.
- 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 0now becomesnickel eval config.ncl -- \ 'input.field1="Value"' input.flag=false \ --override output.bar=0
- Fix
record.updateby makingrecord.insertact consistently by @yannham in #1669
- 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
nostdlibin customize mode as well by @vkleen in #1634 - Add the
listsubcommand 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
--fieldargument to subcommands to target a specific field whenever it makes sense by @yannham in #1712
- 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
- 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
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.
- 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
- 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
- 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:queryin the REPL) interface by @yannham in #1447 - Topiary integration (formatting) as
nickel formatby @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 (see
nickel 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
- add
std.contract.Sequenceby @Radvendii in #1452
- 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
This version mostly includes bugfixes and stdlib improvement since 1.0.
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.
- 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
- Improve the pretty printing of terms in the CLI and within error messages by @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 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
This is the 1.0 release! The syntax and the semantics of the core language have been stabilized and shouldn't evolve as much in the future.
- The core semantics of the language have been reworked and stabilized, in particular (but not limited to) merging, types and contracts with the implementation of RFC005
- The stdlib has been augmented with many new functions
- Parts of the syntax and some builtin symobls (types, stdlib functions, and so on) have been improved and made consistent
- New features for the LSP, and in particular code completion
- Various functions from the stdlib have been renamed for better discoverability, and the stdlib got a lot of new additions. Please refer to the documentation of the stdlib.
- String functions are now unicode-aware, and operate on the Unicode grapheme
cluster abstraction instead of the character abstraction (
string.length,string.is_match, etc.) - The
switchkeyword has been replaced bymatch, and can now be used as a standalone function (doesn't need to be applied right away) - The
NumandStrbuiltin types have been renamed toNumberandStringby @yannham in #1164 - The
numandstrstdlib modules have been renamed tonumberandstring - The
builtin.typeoffunction now returns'Number,'String,'Functioninstead of respectively'Num,'Str, and'Fun - The
builtin.is_num,builtin.is_strandbuiltin.to_strfunctions have been renamed tois_number,is_stringandto_string - The
string.to_numandstring.from_numfunctions have been renamed toto_numberandfrom_number - All the stdlib modules
array,string,record, etc. have been put under astdnamespace. They must now be accessed asstd.array,std.stringand so on. - RFC005 was implemented, which changes the semantics of contract annotations
and merging. See the RFC
content
for more details. Most notably, metadata annotation (default values,
optional, documentation, etc.) can only appear next to a record field. Contract and type annotations can still appear anywhere. Documentation can still appear on let-bindings. - Use static dictionary types for
record.fieldsandrecord.valuesby @matthew-healy in #1024 - Make type annotations to not propagate through merging by @yannham in #1271
- Change to dictionary contracts and introduction of a separate dictionary contract (in addition to dictionary type):
- Stdlib
string.Stringingable->string.Stringableby @vkleen in #1180 - Fix the type of
array.elemby @yannham in #1223 - Change the enum tag start delimiter from backtick to single-quote by @vkleen in #1279
importis now a statement,import "foo.ncl" arg1 arg2requires parenthesis now:(import "foo.ncl") arg1 arg2, see #1293
- Symbolic strings by @matthew-healy in #994
- [RFC005] Lazy propagation by @yannham in #1086
- Non-exported record fields by @vkleen in #1132
- Enrich label custom reporting data by @yannham in #1152
- Use type annotations in record patterns during typechecking by @matthew-healy in #1176
- Use arbitrary precision rationals as the underlying representation of numbers by @yannham in #1182
- Allow equal arrays to be merged in order to make merge idempotent by @yannham in #1229
- Use deterministic hashtables, making runtime errors and typechecking error deterministic by @yannham in #1235
- Add a %trace% primop (and
std.tracefunction) by @vkleen in #1055 - Add
std.contract.Equalcontract to the stdlib by @yannham in #1203
- Display meta information when providing completion in #966
- LSP completion for import terms by @ebresafegaga in #993
- Fix LSP server not giving completion when a non-contract meta-information is present in a declaration by @ebresafegaga in #991
- Fix LSP not giving completion when an identifier is prefixed by a delimiting character by @ebresafegaga in #1043
- Improve the "goto definition" feature of the LSP by making it work across multiple files by @ebresafegaga in #1029
- Add --color option to the CLI by @matthew-healy in #1033
- Make the "find references" feature of the LSP work across multiple files by @ebresafegaga in #1037
- Add support for LSP completion using the surrounding context by @ebresafegaga (context completion) in #1057
- Support completion for field names inside recursive records. by @ebresafegaga in #1088
- Improve contract violation error reporting by @ebresafegaga in #1139
- Add a JSON documentation export option by @vkleen in #1209
- Add support for formatting capabilities to the LSP by @ebresafegaga in #1216
- Do not panic on type path mismatch by @yannham in #1028
- Fix multiline string interpolation when preceded by a
"character by @matthew-healy in #1023 - Improve the performance of
std.array.fold_leftandstd.array.fold_rightby @vkleen in #1075 - Correctly type identifiers introduced in destructuring patterns by @matthew-healy in #1099
- Always include fields with a value in
record.fieldsby @vkleen in #1225 - Make partially applied boolean operators work by @vkleen in #1282
- Fix blame error when calling
string.findby @euank in #988
- Fix polymorphic contracts unduly changing semantics by @ebresafegaga in #802
- Fix typechecking and unification in presence of flat types (aka opaque types, aka contracts) by @yannham in #766
- Fix polarity for polymorphic contract failure by @ebresafegaga in #831
- Fix panic when a row mismatch occurs while unifying row tails by @matthew-healy in #847
- Fix type to term conversion causing unbound type variables errors by @francois-caddet in #854
- Fix bad lexing of enum tags by @matthew-healy in #874
- Fix multiple recursive overriding by @yannham in #940
- Optional fields by @yannham in #815
- Numeral merge priorities by @yannham in #829
- Recursive merge priorities (or push-priorities, or leafy priorities) by @yannham in #845
- Change
switchtomatchand make it a proper function by @yannham in #970
- Statically type
string.joinby @matthew-healy in #946
- Add record completion in the LSP by @ebresafegaga in
- Add completion for Nickel's stdlib in the LSP by @ebresafegaga in #918
- Lazy array contracts by @fuzzypixelz in #809
- Array slices by @fuzzypixelz in #776
- String interning for identifiers by @Acaccia in #835
- Using a contract as part of a static type annotation will in most cases fail with an appropriate error message. This is a temporary limitation in order to fix previously unsound behavior in the typechecker. This restriction will likely be lifted in the upcoming 0.3.x release. For more details, see issues #701 and #724
- Fix unnecessarily restricted record contract for
record.update - Fix wrong interpretation of long interpolation-like sequences
%..%{in strings - Fix panic when evaluating a
switchin specific cases - Fix fields without definition being assigned to
null, instead of just being marked as undefined
- Merging null values together gives null, and merging empty lists together gives
an empty list, instead of failing with
error: non mergeable terms - Add recursive let-bindings (
let rec) - Add type wildcards. Use
_in place of a type to let the typechecker fill the gap. Example:let foo : _ = array.all ((==) 2) [1,2,3] - Add
builtin.to_strandstring.fromto convert generic values to a string - Re-introduce an official syntax for enum types
- Add the
nickel pprint-astcommand to pretty print a parsed program (mostly debugging purpose) - Add the
nickel doccommand to produce markdown documentation from the in-codedocmetadata
- Fix various typos and remove use of deprecated syntax in the user manual
First release! The main focus has been the design of the Nickel language itself.
- Gradual type system with row types, polymorphism and type inference
- Contract system for data validation
- Merge system for recursive records that supports one level of overriding
- Metadata annotations (default values, documentation, etc.)
- Unified syntax for terms, types and contracts (RFC002)
- Record destructuring
-
The main binary supports the following subcommands:
nickel queryto show metadata and documentation of library functions, the field of a configuration, etc.nickel exportto serialize to JSON, YAML, or TOMLnickel replto launch an REPLnickel typecheckto do typechecking without evaluating
-
An LSP-server is included
- User manual sections on syntax, correctness (types and contracts), and merging
- The standard library has been documented in-code (use
nickel query/:queryto retrieve it)
-
The roadmap for overriding and the merge system (RFC001) has not been implemented fully yet.
-
Performance has not been prioritized.
-
Due to the use of reference counting as a memory management strategy, mutually recursive record fields are currently leaking memory. This shouldn't be an issue in a standard workflow.
-
Standard library APIs and language features are subject to change. There is no backward compatibility guarantees for this version. In general, this release is meant for experimenting and getting user feedback, but isn't intended to be used in production.