Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nickel doc appears not to work for Let x in y expressions #1462

Closed
harris-chris opened this issue Jul 19, 2023 · 5 comments · Fixed by #1463
Closed

nickel doc appears not to work for Let x in y expressions #1462

harris-chris opened this issue Jul 19, 2023 · 5 comments · Fixed by #1463

Comments

@harris-chris
Copy link

Hello - running nickel doc -f test.ncl --stdout for this:

# test.ncl
{
  port
    | doc "a  port"
}

works fine, and outputs the documentation I'd expect. But if I change the file to this:

# test.ncl
let Port = {
  port
    | doc "a  port"
}
in Port

then I get an error:

error: no documentation found
  ┌─ test.ncl:1:1
  │  
1 │ ╭ let Port = {
2 │ │   port
3 │ │     | doc "a  port"
4 │ │ }
5 │ │ in Port
  │ ╰───────^
  │  
  = documentation can only be collected from a record.

I'd expect to get the same behaviour from both of these examples, I'd have thought that the second one would just resolve to the record shown in the first one.

Unless there's something I'm missing, this stops documentation being generated for schemas which use imports.

Thanks!

@vkleen
Copy link
Contributor

vkleen commented Jul 19, 2023

This is absolutely a bug, you're not missing anything. I'll try looking into it.

@yannham
Copy link
Member

yannham commented Jul 19, 2023

I wouldn't be surprised if nickel doc doesn't do any form of evaluation. That is, the file must syntactically be a record literal. Which is not well documented and quite limiting (the initial motivation coming from generating the documentation for the stdlib). I think it would actually be rather easy to change that, and it sounds like a good idea: evaluate the term (weakly, i.e "lazily"), substitute the environment and generate the doc.

@yannham
Copy link
Member

yannham commented Jul 19, 2023

By the way, if you don't specify --output, nickel additionally creates an empty file ./nickel/doc/out.md although there is an error. We should probably not mutate the filesystem in this case.

@vkleen
Copy link
Contributor

vkleen commented Jul 19, 2023

I almost feel like this needs to be a special evaluation mode. We need to not only evaluate to WHNF but also descend into record fields to collect documentation recursively. At the same time there's no need for the share normal form transformation and we don't really want to evaluate every field fully.

@yannham
Copy link
Member

yannham commented Jul 19, 2023

The issue is that I fear the evaluation will just blow up if we don't do the share normal form transformation, there's just too many parts of the evaluation (in particular merging) that heavily relies on this transformation being applied. I think.

Once again, share normal form wouldn't be an issue with a runtime AST repr that could encode closures directly, as we could just say goodbye to those heading let-bindings 🤷‍♂️

We did have different evaluation modes for metadata pre-RFC005. The code has been scrapped but shouldn't be too hard to revive, and I think provided a somehow principled approach to this idea (in particular the fact that being in one mode, you might want to evaluate a subterm in another mode - I don't know if that's the case here, but it was for metadata evaluation mode). It's not out of the question.

vkleen added a commit that referenced this issue Aug 14, 2023
…doc`

With this change we no longer print evaluated types or contracts in
field annotations for `nickel doc`. Ever since `nickel doc` started
evaluating terms to address #1462 contract and type annotations would be
evaluated before reaching the documentation extraction stage. This means
they would be affected by program transformations and the result would
most likely be meaningless to the user.

Incidentally, `nickel query` already correctly used the original
unevaluated type for contract annotations but not for type annotations.
If a type annotation contains a `Term` as a `TypeF::Flat` variant, it
was possible to trigger the same undesirable behaviour:

```
❯ cargo run --bin nickel -- query foo <<<'{ foo : { x | Dyn, y } = {x = 1, y = 2} | { x | Dyn, y } }'
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/nickel query foo`
• type: let %182 = $dyn in { x | Dyn, y, }

Available fields
• x
• y
```

Fixes #1519
github-merge-queue bot pushed a commit that referenced this issue Aug 14, 2023
…doc` (#1529)

* Use the original unevaluated type and contract annotation in `nickel doc`

With this change we no longer print evaluated types or contracts in
field annotations for `nickel doc`. Ever since `nickel doc` started
evaluating terms to address #1462 contract and type annotations would be
evaluated before reaching the documentation extraction stage. This means
they would be affected by program transformations and the result would
most likely be meaningless to the user.

Incidentally, `nickel query` already correctly used the original
unevaluated type for contract annotations but not for type annotations.
If a type annotation contains a `Term` as a `TypeF::Flat` variant, it
was possible to trigger the same undesirable behaviour:

```
❯ cargo run --bin nickel -- query foo <<<'{ foo : { x | Dyn, y } = {x = 1, y = 2} | { x | Dyn, y } }'
    Finished dev [unoptimized + debuginfo] target(s) in 0.12s
     Running `target/debug/nickel query foo`
• type: let %182 = $dyn in { x | Dyn, y, }

Available fields
• x
• y
```

Fixes #1519

* Add a snapshot test against regressions
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants