1
1
mirror of https://github.com/tweag/nickel.git synced 2024-10-03 22:57:11 +03:00
Commit Graph

4175 Commits

Author SHA1 Message Date
Yann Hamdaoui
0b251e83b4
Detect infinite recursions in nickel doc (#2055)
* Detect infinite recursions in `nickel doc`

This commit fixes an issue where legit recursive configurations cause
infinite recursion when trying to extract their documentation. Indeed,
`nickel doc` calls to `eval_record_spine`, which is unable to detect
loops that span multiple evaluation step (an evaluation step is
evaluating one field to a weak head normal form).

This commit changes `eval_record_spine` and related methods to lock (in
practice just flip a bit in the thunk's state) the active thunks, that
is the thunks of parents of the field that we are currently evaluating.

If we ever come across a thunk that is already locked, the field is left
unevaluated, avoiding infinite recursion.

* Fix clippy warning

* Fix typo in code comment
2024-10-02 13:25:21 +00:00
Yann Hamdaoui
927ee23993
Update flake inputs (#2058)
Update various flake inputs and the flake.lock file. Adapt the flake.nix
file, as well as the Rust source code, to accomodate the latest changes
(new clippy warnings, etc.).

Topiary is getting hard to use from the flake, because there are two
conflicting versions: the one that is pulled from Nix to be used in the
CI (checking that files are properly formatted), and the one built into
Nickel via cargo. Both must agree (or at least there might be a
difference in formatting between the two if they aren't the same
version). Since the addition of dynamic loading of grammars, latest
Topiary has become harder to build from Nix.

To avoid all those pitfalls, this commit gets rid of the Topiary as a
flake input, and use `nickel format` instead, ensuring that the
formatting is consistent. As a consequence, Topiary isn't included in
the development shell anymore, but it's arguably not an issue: it was
included before `nickel format`, as we needed a third party formatter,
but now one can just build Nickel locally with their preferred method
and use `nickel format`.
2024-10-02 09:12:03 +00:00
dependabot[bot]
378ece30b3
chore(deps): bump actions/github-script from 6 to 7 (#2016)
Bumps [actions/github-script](https://github.com/actions/github-script) from 6 to 7.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-30 07:46:06 +00:00
dependabot[bot]
1ddfe25f46
chore(deps): bump cachix/install-nix-action from V28 to 29 (#2054)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V28 to 29. This release includes the previously tagged commit.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/V28...v29)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-27 11:52:25 +00:00
jneem
eee41e3dd2
Adds a nickel test subcommand for testing examples in docs. (#2020)
* Doctests

* Add a custom_transform method

* Make the vm private again

* Update doc

* Add some snapshot tests

* Split out closurized and non-closurized variants of eval_record_spine

* Fix doc link

* Add some docs, but not sure where they should go

* Make report_as_str honor the color setting

* Separate the stdout and stderr outputs more intentionally

* Commit the other snapshots
2024-09-26 13:45:03 +00:00
jneem
a285d9e923
Thunks for resolved imports (#2052)
* Closurize resolved imports so they detect recursion

* Add a test

* Update core/src/cache.rs

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
2024-09-26 10:59:49 +00:00
Vitaly Shukela
c50647d281
Explicit imports: import 'Raw "sample.html" (#2036)
* Explicit imports

* explicit import: more changes.

* Rename typ to format
* Bring back the fallback
* Implement pretty-printer part
* Fix compilation of NLP

* Document imports

* Apply suggestions from code review

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* minor fix

* explicit imports: add tests

* explicit imports: support importing the same file with different formats

* fmt

* Reinforce explicit imports test against some whitespace changes.

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
2024-09-18 15:59:48 +00:00
Yann Hamdaoui
dceb960f09
Fix release script to handle more deps style (#2044)
Update `sed` invocation to handle dependencies specification of the form
`deps = { workspace = true, ..etc }` and not only `deps.workspace = true`.
2024-09-17 14:26:06 +00:00
Yann Hamdaoui
4a4825e688
Fix unsound record contract deduplication (#2042)
* Fix contract equality unsound on records

Contract equality code used to flat out ignore all of the metadata of a
fields, including contract annotations, which is obviously entirely
wrong. This means that `{foo | String}` and `{foo | Number}` was deemed
equal and deduplicated as the same contract.

This commit fixes the issue by comparing the metadata as well. Contract
labels are a subtle matter, and they are the only part that is ignored
by the contract equality code.

* Add comparison of label's type_environment for safety

* Update core/src/typecheck/eq.rs

Co-authored-by: jneem <joeneeman@gmail.com>

* Add integration test for contract dedup unsoundness

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-09-16 16:08:55 +00:00
dependabot[bot]
5145172e7b
chore(deps): bump cachix/install-nix-action from V27 to 28 (#2038)
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V27 to 28. This release includes the previously tagged commit.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/V27...V28)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-13 08:44:58 +00:00
suimong
9bcd369afe
Add --format argument to nickel query command (#2015)
* add structured output formats for `nickel query`.

WIP on interface

WIP

WIP

WIP.

Fix CI; improve impl Serialize for MergePriority

remove `Default` impl for `ExportFormatCommon`

change naming.

fix clippy warning

improvements on handling markdown format

- make markdown the default export format
- print error message when user want to export markdown format to a file.

* prune null/empty output fields

* fix clippy warnings

* fixes

* make value field a pretty printed string

---------

Co-authored-by: Ben Yang <ben@ya.ng>
2024-09-12 08:45:17 +00:00
jneem
3663b0af63
Let rec patterns (#2031)
* Add attrs to let patterns

* Implement let-rec patterns

* Fix markdown

* More markdown

* Put a test in the right place

* Revert the comment change

* Review comments
2024-09-12 01:57:15 +00:00
jneem
58412e8e5b
Let blocks (#2010)
* Add let blocks to the AST

* Add parsing and tests

* Fix build

* Missing insta

* Fix it again

* Add a custom parse error

* Try out smallvec

* Support multiple patterns in the ast

* Support constructing let blocks with patterns

* Fix warning

* Review comments

* WIP

* WIP

* Fix typechecking

* Add lsp tests

* Add an error for duplicate bindings in a let block

* Update the manual

* Delete the old pattern file.

* Move test to integration
2024-09-10 15:06:07 +00:00
dependabot[bot]
e5e6988e3f
chore(deps): bump DeterminateSystems/update-flake-lock from 23 to 24 (#2035)
Bumps [DeterminateSystems/update-flake-lock](https://github.com/determinatesystems/update-flake-lock) from 23 to 24.
- [Release notes](https://github.com/determinatesystems/update-flake-lock/releases)
- [Commits](https://github.com/determinatesystems/update-flake-lock/compare/v23...v24)

---
updated-dependencies:
- dependency-name: DeterminateSystems/update-flake-lock
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-10 10:00:58 +00:00
Yann Hamdaoui
3c2049fb82
[release.sh] update to 1.8.0 (#2034) 2024-09-09 16:38:26 +00:00
Yann Hamdaoui
c587d3aaff
Update to latest topiary-queries (formatting) (#2032)
* Update to latest topiary-queries

Formatting of Nickel code has been updated upstream to better anticipate
the usage of `std.contract.custom` and `std.contract.from_predicate`.
This commit updates to the latest version, and update the formatting of
the stdlib, the examples and the snippets of the manual.

* Update topiary's entry in flake.lock as well

* Format stdlib/internals and benchmarks
2024-09-09 10:42:33 +00:00
Nathan Pollart
273ae0f489
Add record constructor to subtyping (#2007)
* Initial draft without Constant and TailVar

* Restrict visibility of RemoveErrorRow to super

* Create trait Subsume for UnifType and UnifRecordRows

* Fix problem about {a: Type}<: {a:Type;b:Type} that was not accepted

* Copy comments (general comment on subsumption and closing a record when there is a record/dictionary subsumption)

* Fix problem (it was error reporting...)

* Rename trait

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Correct spelling in comments

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Rename trait impl

* Rename trait

* Update comments

* Remove subsumption function from typecheck/mod.rs

* Add test

* Add documentation

* Rename trait (for clippy)

* Add tests

* Modify snapshot lsp

* Update comments core/src/typecheck/subtyping.rs

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Update doc/manual/typing.md

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Modify comment

* Modify comment

* Revert lsp snapshot

* Cosmetic improvements

This commit performs minor cosmetic improvements in the code handling
subtyping, mostly around comments and function interfaces.

* Update snapshot test for LSP

The support of subtyping for record types makes some types to be
instantiated earlier than before. Given the way terms are visited, when
writing something like `let f = std.array.map in ..`, `std.array.map`
used to be inferred to be of a polymorphic type `forall a b. ...` and
then only was instantiated (because record access is inferred, while the
bound expression is checked). With the new implementation, it is
instantiated as part of the subsumption rule, meaning that it'll appear
differently on the LSP.

All in all, both version of the data shown by the LSP (before this
change and after) are meaningful, in some sense. The polymorphic type is
still shown when it's part of the metadata anyway, in addition to the
inferred monomorphic type. This also doesn't change which expressions
are accepted or not. It's more of an artifact of when we visit terms,
before or after instantiation and how those visits are intertwined with
`check` and `infer`. It's not easy to revert to the previous state of
affairs, and it's in fact not necessarily a good thing either: in the
example above, the LSP would also show a polymorphic type for `f` - the
one of `map` - while in fact `f` has a monomorphic type, so you couldn't
use it in different contexts (say on an `Array Number` and later on a
`Array String`). The current version is showing the real monomorphic
nature of `f`.

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
2024-09-06 15:38:18 +00:00
dependabot[bot]
44aef1672a
chore(deps): bump micromatch in /lsp/vscode-extension (#2030)
Bumps [micromatch](https://github.com/micromatch/micromatch) from 4.0.5 to 4.0.8.
- [Release notes](https://github.com/micromatch/micromatch/releases)
- [Changelog](https://github.com/micromatch/micromatch/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/micromatch/compare/4.0.5...4.0.8)

---
updated-dependencies:
- dependency-name: micromatch
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-09-04 12:34:47 +00:00
cydparser
165eeddcca
Fix windows tests (#2025)
* Fix benchmarks on Windows

* Fix tests for Windows

+ Improve failure messages

* Add CI job for Windows

* Disable unused warning for ParseFormatError

* Add `pprof` feature to utils
2024-08-09 01:26:23 +00:00
Yann Hamdaoui
275406576a
Fix and improve contract generation optimization for static types (#2017)
* Fix and improve static contract optimizations

This commit fixes a number of issues with the optimization of contract
generation from a static type annotation. It's been introduced to take
advantage of the guarantees of static typing to simplify the generated
contract and elide a number of useless checks at run-time.

However, this optimization was too agressive as implemented: it just
turned any non-function type in a positive position to `Dyn`. Indeed,
contracts in negative position must be kept around, because they check
what's come from the (potentially untyped) external world: the fact that
a function is statically typed doesn't ensure it'll be called with the
right arguments.

The first issue is that a negative contract can hide inside something
else than an arrow type. Typically, take `let functions: Array (Number
-> Number) in (std.array.at 0 functions) "a"`. The application is
untyped, and wrongly pass a string to a function of the array. However,
the current optimization code will turn this contract to just `Dyn` at
runtime and get rid of entirely, because there's an `Array _` in
positive position. This is only valid if `_` doesn't contain any arrow
type, which it does, in this example.

Another issue stems from the sealing/unsealing symmetry of polymorphic
row contracts. Take `let id : forall r. {foo : Number; r} -> {foo :
Number; r} = fun x => x in id {foo = 1, bar = 2}`. The current version
would return `{foo = 1}`, with the `bar` field missing. The issue is
that the second `{foo : Number; r}` is a record type in positive
position, which currently gets entirely elided, giving `forall r. {foo :
Number; r} -> Dyn` as an optimized contract. The argument contract seals
anything else than `foo` in the record's tail, but there's no dual
contract to unseal it anymore, such that it just becomes invisible.

This commit implements a more complicated strategy, but which is
hopefully correct. Instead of getting rid of type constructor in
positive positions, we try to simplify their content as well, and only
if the content is simplified down to `Dyn` (or `{; Dyn}` for record
rows, etc.), we get rid of the entire constructor. Otherwise, we try to
pay only for necessary checks. For example, `{foo : Number, bar : Number
-> Number}` now gets simplified to `{bar : Number -> Dyn; Dyn}` instead
of just `Dyn` before (which was incorrect).

The full simplification rules around polymorphic row contracts are a bit
intricate and are properly detailed in the documentation of the
corresponding methods.

* Add tests (wip)

* Add tests for type simplification, fix unveiled bug

* Apply suggestions from code review

Co-authored-by: jneem <joeneeman@gmail.com>

* Move back code comments to the right position

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-08-06 13:59:27 +00:00
Yann Hamdaoui
b3c8e30b68
[Optimization] Cache contract generation and pre-compile some match expression (#2013)
* Pre-generate contracts

After the introduction of a proper node for types in the AST, we
switched to a lazy way of generating contract: we keep the type as it
is, and convert it to a contract only once it's actually applied. While
simpler, this approach has the drawback of potentially wasting
computations by running the contract generation code many times for the
same contract, as some metrics showed (up to 1.6 thousand times on large
codebases).

This commit add a `contract` field to `Term::Type`, and statically
generates - in the parser - the contract corresponding to a type. This
is what we used to do before the introduction of a type node. Doing so,
we only generate at most one contract per user annotation, regardless of
how many times the contract is applied at runtime.

* Pre-compile match in enum contract

This commit saves some re-compilation of the match expression generated
by contracts converted from enum types by generating the compiled
version directly instead of a match.

* Fix unused import warnings
2024-08-02 06:36:42 +00:00
jneem
734bcc9bdd
Missing event.json upload (#2018)
* Missing event.json upload

* Right adapter name
2024-07-31 13:00:01 +00:00
jneem
0e060a0e29
Track benchmarks in CI (#2012)
* bencher

* backslash

* rust_criterion

* try out the tweag runner

* nix it

* try using the bencher secret

* run it on ubuntu-latest

* try the master/pr split

* huh?

* Rewrite it

* why isn't the upload running?

* test

* test

* Better workflow name

* test

* test

* test

* test

* put back the conditional

* Add docs
2024-07-29 14:04:48 +00:00
Eckaos
699cf5dff4
Adding documentation for subtyping (#1990)
* Add subsumption rule between Record/Dictionary

* Remove commented code

* Remove clone in pattern match, replaced fold by a for loop, take into account TailUnifVar and TailConstant

* Update & add comments

* Add integration tests

* add test with chaining std function on records

* add manual documentation for record/dictionary subtyping

* Modify manual

* Changing contract to typing

* Update core/tests/integration/inputs/typecheck/chaining_dictionary_function_record_dictionary_subtyping.ncl

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Update doc/manual/typing.md

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Fix test

* Add motivation

* Fix code example

* Add Array/Array and Dictionary/Dictionary subtyping documentation

* Fix code (does not fix TypecheckError)

* Fix code examples (does fix errors)

* Fix subsumption

* Fix subsumption

* Improve the manual section on subtyping

* Add generic example to work around function subsumption

* Update doc/manual/typing.md

* Update doc/manual/typing.md

* Fix format problem

* Update doc/manual/typing.md

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
2024-07-29 11:07:39 +00:00
Yann Hamdaoui
a7dc359462
Implement prepare_custom_contract natively (#2008)
After the rework of the contract system that sets enum as the default
return type of most custom and builtin contracts, some additional glue
code was needed to post-process such enums (and raise blame
accordingly). This has been implemented in the new internal function
`$prepare_custom_contract`.

While this function wasn't very long or involved, measurements showed
that contract application is a code path that is taken so much that this
additional blob of pure Nickel slowed down real world example by
potentially a huge factor (up to 5-6x).

While this is the symptom of other inefficiencies related to the
contract system in general (related to pattern matching, missed caching
opportunities for contract generation, etc.), bringing back the logic of
`$prepare_custom_contract` to native code brings back the overhead
(master compared to latest stable 1.7) to something like 1.1x or 1.2x.

This commit implements this strategy, by introducing two new primops:

- `%contract/postprocess_result%` which takes an enum `[| 'Ok value,
  'Error error_data |]` and either unwrap `'Ok`, or modify the label
  using the `error_data` and then blame
- `%label/with_error_data%`, which is used in the previous primop
  implementation but can be useful as a stand alone primop and stdlib
  wrapper in the future, which takes a value `{message, notes}`, a
  label, and update the label's data with the corresponding diagnostic
  message and notes

Additionally, this commit tries to avoid generating terms at run-time,
but rather setup the stack directly, to further make this hot path
faster.
2024-07-26 09:31:07 +00:00
Yann Hamdaoui
74fea843dd
Remove the contract guarding contract.apply (#2009)
Many contract helpers didn't have any type nor contract themselves in
the latest stable version of Nickel. With the contract system rework,
we've added missing annotations to make sure user writing contracts
would have better error messages.

However, this isn't free: on a medium-sized benchmark (25kLoC),
`contract.apply` is called approximatevely 100k times, which has an
impact on performance. While `contract.custom` or `contract.check` needs
their contract, `contract.apply` is hard to type and thus get a rather
vague type `Dyn -> Dyn -> Dyn -> Dyn`, which doesn't add much to good
error messages.

This commit removes the contract of `std.contract.apply`, reverting back
to the 1.7 situation, which shows non trivial improvements on the
benchmark mentioned above.
2024-07-26 08:49:54 +00:00
Yann Hamdaoui
e4ff05a9d6
apply_as_custom -> check (#2002)
* apply_as_custom -> check

After bikeshedding, it's been decided in the weekly meeting that we
should use `check` for the new variant of `contract.apply` introduced in
the latest contract system rework.

We couldn't find a meaningful name for this function: `try` and
`try_apply` would be nice, but they are deceptive because they sound
like `apply_as_custom` could catch all contract errors, while it only
makes immediate errors catchable. Also, we might introduce an actualy
`contract.try` at some point, which is able to catch contract errors.

`then` and `and_then` are reflective of how they're used in custom
contract, but that might not be the only possible usage. In the end, we
just needed something different than `apply`, and `check` was the less
bad candidate, with a slight connotation of trying something (as opposed
to `eval`).

* Fix typos in contract.check doc
2024-07-25 08:55:39 +00:00
Yann Hamdaoui
b53837fbd5
Add new perf measures (#2004)
This commit use the metrics infrastructure to measure many more
counters, including the number of times each primop is run, each import
is evaluated, the  number of contracts deduped and more. This only
impacts the build with feature `metrics` enabled (disabled by default),
and is proving useful right now to investigate a performance
degradation.
2024-07-25 08:23:28 +00:00
Hugal31
ffe80f0fb0
Add trigonometric functions, pi, e and log to the numbers module (#2006)
* Add trigonometric functions, pi, e and log to the numbers module

* Refactor the new maths primop, prefix them with "number/"

* Change the prefix of the arc-trigonometric functions from "a" to "arc"
2024-07-24 14:11:51 +00:00
Eckaos
e9770b0005
Adding dictionary constructor to subsumption rule (#1998)
* adding constructors to subsumption rule

* Add test

* Modify test

* Add dictionary constructor subtyping and adding a test for it

* Update core/tests/integration/inputs/typecheck/dictionary_subtyping.ncl

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>

* Modify subsumption function to clone less

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@gmail.com>
2024-07-19 12:00:11 +00:00
jneem
b934978748
Add short-circuiting fold_left (#2000)
* Add short-circuiting fold_left

* The naming from 1997 is better

* Update manual

* Add blank line

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>

* Convert any_of

* Update snapshots

* Fix manual tests

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
2024-07-19 05:23:21 +00:00
Yann Hamdaoui
4cb1679ce2
[Doc] Pass on the contract chapter of the manual (#1999)
* Pass on the contract chapter of the manual

Since this contract chapter of the manual has been reworked a lot in
various recent PR, given the changes to the contract system. This commit
is a result of a full pass on this chapter to ensure no inconsistencies
remain.

* Update doc/manual/contracts.md

Co-authored-by: jneem <joeneeman@gmail.com>

* Update doc/manual/contracts.md

Co-authored-by: jneem <joeneeman@gmail.com>

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-07-18 09:04:45 +00:00
Yann Hamdaoui
6be1f2ced3
Add boolean contract combinators to the stdlib (#1995)
* Add boolean contract combinators to the stdlib

This commit adds the boolean combinators `one_of`, `not` and `all_of` to
the contract module of the stdlib. They are implemented in the obvious
way, by making immediate decisions based on the immediate part of their
contract operands. The limitations and possible work arounds are
detailed in the documentation and in the manual.

* Add tests for boolean contract combinators

* Apply suggestions from code review

Co-authored-by: jneem <joeneeman@gmail.com>

* Implement review suggestions

Make a pass on the new documentation of boolean contract combinators to
implement the reviewer's suggestions.

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-07-17 14:49:12 +00:00
Eckaos
ffa55651a2
adding array constructor to subsumption rule (#1991)
* adding constructors to subsumption rule

* Add test

* Modify test
2024-07-17 12:42:34 +00:00
Yann Hamdaoui
1ac48b8436
Re-introduce unified representation for custom contracts, migrate builtin contracts (#1987)
* Split builtin contracts as immediate/delayed

This commit split the builtin contracts into explicitely separated
immediate and delayed part, as per the contract design introduced in a
previous commit. This incur broad changes, as this impact the internals
module of the stdlib, the stdlib itself, and the code generating
contracts from static types.

* Change custom contract representation (again)

After converting the builtin contracts to the immediate/delayed split
representation, a number of complications appeared. Nothing that can't
be overcome, but requiring unsatisfying ad-hoc treatments or a more
complex contract interface that wasn't easy to explain in the
documentation.

In particular, passing information between the immediate
part and the delayed part is cumbersome. Splitting the logic in two
different functions is arguably harder to understand. Contract
composition, while preserving the immediate and delayed parts, is
cumbersome as well.

In the end, it occurred that switching back to one implementation for
the whole contract, but which can return a value of type `[| 'Ok Dyn,
'Error {..} |]` achieves the same (makes the immediate part and delayed
part separable) while being much simpler both for us maintainers and for
users writing and manipulating contracts. This commit implements this
simplified representation.

* Update stdlib for new ctr repr

Update the stdlib for the new two-in-one custom contract representation
which returns an enum.

* Update tests, examples and doc for new ctr repr

After having introduced a single representation for custom contracts
(instead of a split delayed/immediate), update the various Nickel
snippets in the tests, examples and the documentation to follow this new
API.

* Record contracts and apply_as_custom

This commit adapts builtin record contracts, and thus merge in contract
mode as well, to follow the new contract representation: that is, this
commit makes record contract application to return either `'Error` for
immediate errors (the argument isn't a record or there are extra fields)
instead of blaming or an `'Ok`-wrapped result.

We also add a `apply_as_custom` operator, which preserves the
`'Ok`/`'Error` result (as opposed to `apply`) which is useful to
preserve the immediate checks when calling a contract from another
contract.

* 'Ok -> 'Ok value, use apply_as_custom instead of apply whenever mandated

* Update manual for apply vs apply_as_custom

* Fix usage of renamed of internals

* Fix double contract/custom wrapping failing tests

* Fix some failing tests

* Fix signature of std.contract.custom

* Update test snapshots

* Finish implementation of apply_as_custom

* Small broken test fixes

* Fix typing of contract/custom

* Fix manual snippets

* Fix clippy warning (useless into())

* Apply suggestions from code review

Co-authored-by: jneem <joeneeman@gmail.com>

* Apply suggestions from code review

Co-authored-by: jneem <joeneeman@gmail.com>

* Simplify documentation of contract.apply

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-07-17 09:57:55 +00:00
Yann Hamdaoui
fc88b6d08c
Refactor type error for primops (#1994)
This commit improves the macro that generates dynamic type error for
primitive operators to include the operator's name automatically from
its Display implementation instead of hardcoding it. This shouldn't have
any user-facing effect immediately but should avoid in the future (as it
has happened before) any drift between the dynamic type error messages
and the current syntax/name of primops.
2024-07-16 10:01:36 +00:00
Jeremy Schlatter
090984d0e2
clean up outdated primitive operator names (#1992)
* clean up outdated primitive operator names

PR #1937 recently renamed many primitive operators. It missed some
instances of the previous names, though. In particular:

- error messages
- comments
- an unused function "apply_contract" in core/src/term/mod.rs

While most of these names were only made obsolete in #1937, some of them
have been incorrect for longer, eg "%array_access%" in
core/src/term/pattern/compile.rs and "recordMap" in core/src/term/mod.rs.

I caught as many as I could find. However it's hard to be sure I got all
of them, given that some of the previous names are very general terms
like "value", "fields", "length", and "map".

The full list of renames I identifiend are as follows, formatted as
"<old name> <new name>".

First, the easy cases:

    chng_pol label/flip_polarity
    record_map record/map
    str_trim string/trim
    str_chars string/chars
    str_uppercase string/uppercase
    str_lowercase string/lowercase
    str_length string/length
    str_from to_string
    num_from number/from_string
    enum_from enum/from_string
    str_is_match string/is_match
    str_find string/find
    str_find_all string/find_all
    record_empty_with_tail record/empty_with_tail
    label_push_diag label/push_diag
    enum_unwrap_variant enum/unwrap_variant
    enum_is_variant enum/is_variant
    enum_get_tag enum/get_tag
    apply_contract contract/apply
    array_lazy_app_ctr contract/array_lazy_app
    record_lazy_app_ctr contract/record_lazy_app
    elem_at array/at
    str_split string/split
    str_contains string/contains
    record_insert record/insert
    record_insert_with_opts record/insert_with_opts
    record_remove record/remove
    record_remove_with_opts record/remove_with_opts
    label_with_message label/with_message
    label_with_notes label/with_notes
    label_append_note label/append_note
    str_replace string/replace
    str_replace_regex string/replace_regex
    str_substr string/substr
    record_seal_tail record/seal_tail
    record_unseal_tail record/unseal_tail
    array_slice array/slice

Then the harder cases:

    polarity label/polarity
    go_dom label/go_dom
    go_codom label/go_codom
    go_array label/go_array
    go_dict label/go_dict
    embed enum/embed
    map array/map
    generate array/generate
    length array/length
    fields record/fields
    fields_with_opts record/fields_with_opts
    values record/values
    go_field label/go_field
    has_field record/has_field
    has_field_with_opts record/has_field_with_opts
    field_is_defined record/field_is_defined
    field_is_defined_with_opts record/field_is_defined_with_opts
    lookup_type_variable label/lookup_type_variable
    insert_type_variable label/insert_type_variable

Finally, two cases that I didn't understand and seem to be unused:

    rec_force_op op rec_force
    rec_default_op op rec_default

* address code review comments
2024-07-10 09:04:42 +00:00
Jeremy Schlatter
58ef79d8e2
Comparisons for number, string, array, and record (#1985)
* Comparisons for number, string, array, and record

See https://github.com/tweag/nickel/issues/1030

* simplify

* address code review comments

* update snapshots

* remove unneeded contract annotation

* fix doc string formatting

* simplify std.array.compare

* std.record.on -> std.record.apply_on
2024-07-08 21:07:04 +00:00
Yann Hamdaoui
3750621b41
Optimize Equal using %record/split_pair% (#1988)
The std.contract.Equal contract needs to be lazy, which means that it
re-implement equality logic in pure Nickel code, which has proven to be
very slow (https://github.com/tweag/nickel/issues/1930).

This commit replaces the field difference operation, implemented using a
left fold, by the new builtin operator `%record/split_pair%`, which
shows a performance improvement of around 300% for the example of #1930.
2024-07-08 08:19:59 +00:00
Jeremy Schlatter
6b1fe613c2
flake: remove redundant transitive dependencies (#1986)
* flake: remove redundant transitive dependencies

- add several more `follows` relationships for de-duplication

- update to latest rust-overlay flake which drops flake-utils dependency

- set `follows = ""` for a few unused dependencies.
    See https://github.com/NixOS/nix/issues/7807

* delete `follows = ""` hacks

* delete one more `follows = ""` hack

* Fix new clippy 1.79 errors

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
2024-07-04 14:55:02 +00:00
jneem
935519f1ae
More aggressive type/contract deduplication on hover (#1984)
* More aggressive deduplication on hover.

Deduplicate not just the type annotations, but also the contract
annotations. Also, try to report Dyn less often.

* Add hover metadata for the field of a record.

* Review comments

* Add a comment
2024-07-03 18:56:20 +00:00
Yann Hamdaoui
18ee89b644
Split contracts into an immediate part and a delayed part (#1975)
* Add immediate/delayed notion to the manual

* Split custom contracts in immediate and delayed part

This commit explicitly split the custom contract representation and
constructors into an immediate part, similar to a validator, and a
delayed part, which is a partial identity. The stdlib and primops are
adapted as well (`%contract/custom%` now takes two arguments, the two
parts, and `%contract/from_xxx%` operators aren't used anymore as they
are subsumed by `%contract/custom%`).

* Rework prepare_contract to be more low-level and use null comparison

* Make `%contract/get_xxx%` panic on a Type

In the long run, we want that `%contract/get_immediate%` and
`%contract/get_delayed%` works as well on types, by calling to the right
function from the internals module. However, this requires deeper
changes, and is left for future work. Since those primops have just been
introduced, there's no reason they'd be used already in the wild, so for
now, we make the implemention panic if we try to apply them to a Type.

* Update stdlib doc, manual and examples

Update various documentation to reflect the new custom contract
constructor with an immediate and a delayed part.

* Update config-gcc example with new custom contract builder

* Fix tests

* Implement review suggestions

Co-authored-by: jneem <joeneeman@gmail.com>

* Review suggestion: use concrete example for delayed checks

* Review suggestion: deduplicate custom contracts in-code doc

* Update Topiary input to avoid CI error (gitsavannah)

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-07-03 09:38:00 +00:00
Yann Hamdaoui
3bafeff167
Add record/split_pair and record/disjoint_merge (#1982)
This is preliminary work for the rewriting of native contracts using the
(to be introduced in a coming PR) new immediate/delayed representation.
In particular, in order to efficiently implement the contracts for
static record types, we need a way to split and recombine record which
is efficient and preserves field metadata.

Those primops might be useful to efficiently implement other operations
(record differences, record projection, etc.)
2024-07-03 07:47:11 +00:00
Théophane Hufschmitt
32a4b675a4
Make the LSP configurable (#1974)
* Make the LSP options configurable

Take into account the configuration sent by the client through
[`InitializeParams.initializationOptions`](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initializeParams).

This is currently used to set the limits for the background evaluation,
although it also creates the infrastructure for setting more things.

* Fix the doc comments for the config

* Remove a useless explicit Default instance

Replace it by the derived one (thanks clippy)

* Comment fixes

Co-Authored-By: Yann Hamdaoui <yann.hamdaoui@tweag.io>

* Simplify the nls config definition

`#[serde(default)]` applied to a whole struct is enough for it to do the
right thing with the `Default` trait. Makes the module significantly
nicer to read.

---------

Co-authored-by: Yann Hamdaoui <yann.hamdaoui@tweag.io>
2024-07-02 19:24:30 +00:00
Eckaos
af5d1b557b
Add a subsumption rule between record types and dictionary types (#1977)
* Add subsumption rule between Record/Dictionary

* Remove commented code

* Remove clone in pattern match, replaced fold by a for loop, take into account TailUnifVar and TailConstant

* Update & add comments

* Add integration tests
2024-07-01 13:26:31 +00:00
Yann Hamdaoui
89639ca63e
Allow some function equality comparison (#1978)
* Allow some function equality comparison

Relax the initial restriction on comparing functions, which is that
comparing a function to anything else error out. In practice comparing a
function to a value of some other type isn't a problem, and can be
useful to allow patterns like `if x != null then ... else ...` without
having first to check if `x` is a function, because that would fail at
runtime.

Instead, we only forbid comparison between two function-like values
(functions, match expressions and custom contracts) and between two
opaque foreign values.

* Fix typo in code comment

* Additional tests for relaxed function comparison

Check the relaxed function comparison, which errors out when trying to
compare two functions, but can compare a function to a value of a
different type (by always returning false).

Tests that functions can't be compared were already there, but this
commit adds tests that function can be compared to other values.
2024-07-01 11:30:35 +00:00
dependabot[bot]
a3bdf62b09
chore(deps): bump DeterminateSystems/update-flake-lock from 22 to 23 (#1981)
Bumps [DeterminateSystems/update-flake-lock](https://github.com/determinatesystems/update-flake-lock) from 22 to 23.
- [Release notes](https://github.com/determinatesystems/update-flake-lock/releases)
- [Commits](https://github.com/determinatesystems/update-flake-lock/compare/v22...v23)

---
updated-dependencies:
- dependency-name: DeterminateSystems/update-flake-lock
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-07-01 08:58:56 +00:00
Yann Hamdaoui
9969d9a9d4
Introduce validators for building custom contracts (#1970)
* Add validator as a form of custom contract

* Support validators in %contract/apply%

* Add from_validator primop and stdlib function

* Add tests for custom contract constructors

* Migrate stdlib to use validators

* Add documentation on validators

* Fix manual snippets

* Apply suggestions from code review

Co-authored-by: jneem <joeneeman@gmail.com>

---------

Co-authored-by: jneem <joeneeman@gmail.com>
2024-06-24 13:19:06 +00:00
Yann Hamdaoui
dd0ccb1d60
Add dedicated node and constructor for general custom contracts (#1964)
* Add partial identity to custom contract type

* Use %contract/custom% in the stdlib

Use the previously introduced new primop in the stdlib, to migrate from
naked functions to wrapped custom contracts everywhere in the stdlib.

* Fix tests

* Migrate examples to use std.contract.custom

* Update the manual to use std.contract.custom

Introduce the new contract constructor std.contract.custom in the
manual, and make sure that this is now everywhere presented as the
official way of building custom contracts. The section on custom
contracts is also re-organized to make general custom contracts the last
section, and present it as a last resort rather than the default way of
building custom contracts. We also left some placeholder for to the
soon-to-come validators.

* Fix typo in code comment

* Revert std.contract.apply -> %contract/apply%

In a previous commit, after introducing %contract/custom%, the stdlib
was upgraded to use this new contract constructor. Doing so, in the
contract.unstable module, many `std.contract.apply` were turned into
`%contract/apply%` following the philosophy that the stdlib should avoid
indirection through other stdlib functions bit rather directly use
primops.

However, it turns out `%contract/apply%` is not equivalent to
`std.contract.apply`. The later also stack the current diagnostics,
while the former is really only performing a function-like application,
which does make a difference for error reporting - the version with
`%contract/apply%` could erase existing error reporting data.

This commit reverts those primops calls back to using
`std.contract.apply`.
2024-06-24 10:05:31 +00:00
Théophane Hufschmitt
e2e6742c5a
Don't blacklist files forever in the lsp (#1973)
When the evaluator in the LSP times out or overflows its stack, the
faulty file is blacklisted so that it doesn't get evaluated any more.
This blacklist used to be permanent, which is generally not desirable
since it makes the LSP unusable.

Change that to only blacklist the file for a fixed delay currently
(hardcoded at 30s).
2024-06-21 17:01:19 +00:00