* Make the trace destination configurable
* Add a callback-oriented trace collector to the wasm repl
* Only call back on flush
* Fix clippy
* Silence trace output in pyckel.
This probably isn't the best thing, but it's probably still better than
polluting stderr in a library. Possibly a better solution is to
imitate the api of `subprocess.run`, but that requires breaking API
to return something other than a plain string.
* Add a GitHub action for automatically uploading release artifacts
The action is triggered on publishing a GitHub release and automaticlly
builds the `dockerImage` and `nickel-static` flake outputs for x86_64
Linux. It then uploads the results as release artifacts on GitHub.
* Apply suggestions from code review
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
* Add a small note about release branch targets
---------
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
* fixed dangling link and incorrect cmd invocation
* set number to be explicit type
* Update doc/manual/contracts.md
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
* export -> format
---------
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
Nickel does not support record types with field paths. i.e. while this
is a valid type:
```
{ x : { y : String } }
```
this is not:
```
{ x.y : String }
```
However, at some point rather than raising the appropriate error here,
we started panicking. This commit fixes that by checking that a field's
path only contains a single element before deciding whether to allow
it in a record type.
Previously Nickel would panic when encountering code like this:
```
let f = fun { x, x } = x in f { x = 1 }
```
This commit fixes that by checking each destructured record pattern for
duplciated identifiers at parsing time, and returning an error if any
are encountered.
Note, however, that in order to preserve backwards compatibility with
Nickel 1.0, the following code is still valid (and returns `1`):
```
let f = fun { x = { y }, z = { y } } => y
in f { x = { y = 1 }, z = { y = 2 } }
```
Previously, if we had a type whose return value contained a polymorphic
tail and we tried to return a value which was not statically known
to be in the return type, we would see a type mismatch error with an
"invented" type name (e.g. `a`) to represent "an arbitrary type in the
tail".
This made it unclear where the problem was, and didn't give any real
direction on how to fix the problem.
This commit raises a specific error in this case, which informs users
that the type they've tried to return is not guaranteed to exist in the
polymorphic tail. We also now pass around a var kind with type errors
related to constant mismatches, so we can print a representation of the
tail type (e.g. `[| ; x |]`) instead of inventing phantom type names
for errors.
Fixes#1316.
* Fixes incorrect variable names in type mismatch errors
In certain cases, it was possible for a row type variable to alias an
existing type variable, causing confusing error messages. This commit
fixes that by tracking type variable kinds together with their IDs.
Fixes#1312
Co-authored-by: Matthew Healy <matthew.healy@tweag.io>
* Pass VarId and VarKind separately for nicer call sites
* Update test expectations
---------
Co-authored-by: Matthew Healy <matthew.healy@tweag.io>
* Convert stdlib_arrays_fail test to new annotated format
* Convert typecheck_fail to new annotated format
* Convert unbound_type_variables to new annotated format
* Convert imports to new annotated format
* Convert infinite_rec tests to new format
* Convert merge_fail tests to new format
* Convert parse_fail tests to new format
* Convert records_fail tests to new format
* migrate nls from structopt to clap
* migrate nickel from structopt to clap
* qualify traits coming from clap
* use clap::ColorChoice with ColorOpt as a newtype
* remove explicit default() for value enums
[clap
Documentation](https://docs.rs/clap/latest/clap/_derive/index.html#arg-attributes)
states it will use `Default::default()` so there is no need to
explicitly call it.
* remove manual FromStr implementations and rely on ValueEnum
deriving `clap::ValueEnum` implements `FromStr` for the type, so doing
so manually isn't required any longer.
* Persuade `clap` to use default values
---------
Co-authored-by: Viktor Kleen <vkleen+github@17220103.de>
* Use single quote for consistency
* Convert contracts_fail to ncl files
* Convert existing ncl source files to annotated tests
This commit converts every existing .ncl file used in tests to an
annotated source file. This means we can change the glob we use to
pick up every .ncl file in the integration test subdirectory, which
makes test organisation significantly more flexible (and should
solve the problem of very long test file names by supporting arbitrary
nesting).
One additional change I had to make here, which increased the diff
significantly, is to add `repeat` functionality to the test annotations,
which allow a test to be re-run an arbitrary number of times. This is
to support tests where behaviour may be non-deterministic (e.g. it
occurs as the result of iterating through a `HashMap`).
* Add integration test infra to test for errors
* Rewrite eq_fail test as .ncl files
* Parse test expectation from header comment
This ensures that the test input files are still valid Nickel source
code.
* Use file path as thread & program name
* Fix clippy warnings
* Refactor for clarity
* Remove unnecessary Serialize impl
* PoC: annotation-based snapshot tests
* Split utilities crate into modules
* Extract annotated test code to utilities crate
* Use annotations for snapshot tests
* Convert basics_fail.rs to use test annotations
* Disable clippy warning about ErrorExpectation variant names
* Use common annotation parsing code for example tests
* Update tests README
* Remove println
* Update tests/README.md
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
---------
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Raise blame error when statically accessing sealed field
* Raise blame error when removing sealed field from record
* Raise blame error when dynamically accessing sealed field
* Store a vec of idents to avoid allocating strings on a hot codepath
Currently `import` is treated as a very special function that only
accepts literal string as its first argument. It has following
downsides:
* Special handling of `import` is hidden. User can assume that its
just a function while it's a special keyword. User might expect to
be able to pass variables to it while it is only handled before
typechecking and evaluation.
* We can't extend `import` functionality without introducing new
keywords which is not backward-compatible.
This change makes `import` into another statement like `let` or `fun`,
which means it cannot be confused with a function anymore. It also means
that expressions like `import "foo.ncl" bar` and
`import "foo.ncl" & {..}` are invalid, and `import` statement need to be
put in parethesis: `(import "foo.ncl") bar`.
For more context, see discussion in
https://github.com/tweag/nickel/issues/329#issuecomment-1531333491
* Keep track of field names when transforming records for generating contract applications
* Add snapshot tests for some blame errors
* Apply suggestions from code review
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
* Fix snapshot tests
* Move label field name tracking into the parsing phase
---------
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
* Change enum token start from backtick to single-quote
* Get tests to pass
* Fix printing in Term::shallow_repr
* Fix benchmark enum tag syntax
* Change enum tags in the documentation to the new syntax
* Format deploy-example.ncl
* Pass on error messages and definitions
* Remove unused RowKindMismatch error variant
This error variant is a leftover from a time where types, record row types and
enum row types were all merged in one Rust enum, and we could end up in
situations where we try to unify a record row with an enum row.
Nowadays, those type are properly distinguished and nested, avoiding
this situation at compile-time.
* Second half of the pass on error messages
* Fix test after changing a type definition
* Update snapshot tests after error messages pass
* Apply suggestions from code review
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
---------
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Use `transform` for the stdlib and `:load` in the REPL
* Update src/repl/mod.rs
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
---------
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
* Fix query path parsing
The parsing of a field path when querying metadata was broken (when
using quotes). Instead of duplicating the parsing logic, this commit
makes the query path code to piggy back on the actual Nickel parser to
parse a field path.
* Field renaming
* Update src/identifier.rs
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Please the Clippy God
---------
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Use record_insert instead of merge for std.record.from_array
* Use a type annotation for std.merge_all
* Run topiary on `stdlib/std.ncl`
* Fix a topiary formatting bug
* Move merge_all back into std.record
Custom contract errors were escaped too agressively (such as turning
`"` into `\"`), while we only want to escape ANSI escape sequences to
avoid messing up Nickel's error reporting. This commits use a
specialized crate to do that, instead of Rust's std `escape`.
* Separate between dictionary types and contracts
Since a recent addition, contracts derived from record types and
contracts derived from record contracts are different. The later are
local and don't propagate, while the former are propagated through
merging. This change calls for the same distinction for dictionaries.
This commit thus add two different dictionary syntax, the original
dictionary type `{_ : T}`, which derived contract is restored back to a
previous version where it's a mere map of the contract application of
`T` over the elements, and a new grammatical construct `{_ | T}` is
introduce, which contract is set to the contract used by `{_ : T}` in
the previous commit (which is a lazy, propagating contract).
As to make the impact of the change minimal, including for the LSP and
the error reporting of blame errors, `{_ | T}` is a variant of the
dictionary type which behave mostly exactly the same but for contract
generation. This way, the LSP, the typechecker and error reporting code
can stay mostly unchanged.
* Fix tests and pretty printing to use dict contracts
* Add more tests for dictionary type vs contract
* Formatting
* Fix type variable fixing for dictionary contracts
* Update LSP for new dict contracts
* Move (and fix) capture type variable test
* DictAttrs -> DictTypeFlavour
* First draft of making type not propagating
* Consider record types as such whenever possible
Before this change, a record literal was considered a record type
whenever it met a bunch of conditions AND was used in a type position.
This meant that `{foo : Number, bar : String}` was always considered as
a normal record (fields without definition) when used in a term
position. This was already subtly wrong, because this means for example
that `x | {foo : Number}` and `let C = {foo : Number} in x | C` are
operationally not equivalent.
Now that we've made a stronger distinction between static types and
contracts (types don't propagate through merging), then this behavior
is just unsound. As per this commit, a record literal is considered a
record type whenever it satisfies the syntactic conditions, be it in a
type or a term position.
Additionally, we've forbidden "mixed" style records, that is record
literals that are not a record type, but with fields that have a type
annotation and no definition. Beside being meaningless, they can be
deceiving, and are most often an error or a confusion from users. Either
the should use a record type, or use `|` everywhere, as in a record
contract.
* Fix tests after forbidding typed fields without definition
* More tests on types vs contracts propagation
* Formatting
* Apply suggestions from code review
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Update snapshot test output after typo fixup
---------
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Pass on the doc of the std top-level symbols
* Apply suggestions from code review
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
---------
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
* Pass on the documentation of std.string
* Fix tests for more restrictive string.to_bool/from_bool
* Apply suggestions from code review
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
---------
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>