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

feat: generalized imports supporting pattern matching and selective field import #3076

Merged
merged 56 commits into from
Jan 28, 2022

Conversation

ggreif
Copy link
Contributor

@ggreif ggreif commented Jan 27, 2022

Resolves #2354, the bulk of it.

We can now import subsets of modules:

import { cons; nil = empty } = "lib/ListM";

let s = cons(1, empty());

Yay!

These will be done separately:

@ggreif ggreif changed the title Explicit symbol imports Explicit symbol imports Jan 27, 2022
mostly failing now
@ggreif ggreif marked this pull request as draft January 27, 2022 15:53
@github-actions
Copy link

github-actions bot commented Jan 27, 2022

Comparing from 7437bc1 to af6941a:
In terms of gas, no changes are observed in 3 tests.
In terms of size, no changes are observed in 3 tests.

@@ -299,6 +299,7 @@

<imp> ::=
'import' <id>? '='? <text>
'import' '{' <list(<pat_field>, ';')> '}' '=' <text>
Copy link
Contributor

@crusso crusso Jan 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not just <pat> = text?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed the syntax here ought to simply be <pat> (or <pat_nullary>).

Copy link
Contributor Author

@ggreif ggreif Jan 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't that allow tuple patterns and all the other things (wildcard and literals)?
What would those even mean?
Or should we just delegate those to the type-checker (will error out) and accept _ as a NOP import?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could insist the pattern is irrefutable, I think, as with shared function args.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, that's what I do. I have also added tests for it.

Copy link
Contributor Author

@ggreif ggreif Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crusso the pattern matches arising from imports have this form

  (LetD (ObjP (cons (VarP cons)) (nil (VarP nil))) (VarE file$lib/ListM.mo))

but we have little control about the RHS (VarE file$lib/ListM.mo). What we could do is, when in check_ir, detect ids like file$* and run check (Ir_utils.is_irrefutable p) on the LHS pattern. Is this what you mean?

Well, we know a bit about the RHS, after all. It gets built in desugar.ml/transform_import and we can anticipate names. Would it be possible to have an IrrefutableLetD and insert that in transform_import?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@crusso what about 4c94e00?

Copy link
Contributor Author

@ggreif ggreif Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay now I reuse the coverage check from typing.ml but make it an error when its is happening in an error. PTAL! 2d9b797

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JFTR, <pat> gives

      menhir mo_frontend/parser.{ml,mli} (exit 1)
(cd _build/default && /nix/store/ih98div9nccad7gjvksxwzhyl0jag1m7-ocaml4.12.0-menhir-20211012/bin/menhir --table --inspection -v --strict mo_frontend/parser.mly --base mo_frontend/parser)
Error: one state has shift/reduce conflicts.
Warning: one shift/reduce conflict was arbitrarily resolved.

@ggreif ggreif force-pushed the gabor/deconstruct-import branch from bf4606a to a1ee29c Compare January 27, 2022 21:33
now we get the best desugaring:
``` scheme
(LetD (ObjP (cons (VarP cons)) (nil (VarP nil))) (VarE file$lib/ListM.mo))
```
@crusso crusso changed the title Explicit symbol imports feat: generalized imports supporting pattern matching and selective field import Jan 28, 2022
@crusso crusso self-requested a review January 28, 2022 20:38
Comment on lines 92 to 100
let import_decs =
List.map (fun { it = (pat, fp, ri); at; note} ->
{ it = LetD (pat,
{ it = ImportE (fp, ri);
at;
note = { note_typ = note; note_eff = Type.Triv} });
at;
note = { note_typ = note; note_eff = Type.Triv } }
) imports
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use the identation style on the left - I think that's what Andreas was advocating... (at least my understanding of it).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what emacs gave me, will change.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -298,7 +298,7 @@
<obj_body>

<imp> ::=
'import' <id>? '='? <text>
'import' <pat_nullary> '='? <text>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there any reason this isn't just <pat> as for let?

Copy link
Contributor Author

@ggreif ggreif Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't want (?(#foo)) here, do we? <pat> just doesn't have any sensible use-case in this place.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, but I don't think we should enforce typing properties using the grammar.
Also, it keeps the grammar closer to the informal language reference.
Plus, you might want a type annotation on the pattern without having to parenthesize it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can I do this tomorrow in a new PR? I am totally burnt out, sorry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tomorrow is saturday. Monday!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't work: #3076 (comment)

Copy link
Contributor

@crusso crusso left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For safety, I would add a quick test/run-drun test to see this works on imports to compiled actors - it should be fine, but the code for compilation units is more complicated than it should be and something could be going wrong.

@ggreif
Copy link
Contributor Author

ggreif commented Jan 28, 2022

For safety, I would add a quick test/run-drun test to see this works on imports to compiled actors - it should be fine, but the code for compilation units is more complicated than it should be and something could be going wrong.

I get errors: af6941a, but that is fine, I think.

@ggreif ggreif added the automerge-squash When ready, merge (using squash) label Jan 28, 2022
@crusso
Copy link
Contributor

crusso commented Jan 28, 2022

For safety, I would add a quick test/run-drun test to see this works on imports to compiled actors - it should be fine, but the code for compilation units is more complicated than it should be and something could be going wrong.

I get errors: af6941a, but that is fine, I think.

Right, but that won't exercise the codegen path.

Maybe add another or different test (Like your List client in test/run above, but enclode in actor {...}), that actually compiles and runs.

BTW, do we allow actor patterns and module patterns, if you specify the keyword (actor or module)? Indeed, it's a bit odd that we can use a record pattern to deconstruct something that is declared as a module, not object (shouldn't the full pattern syntax be <obj_sort> {field_pat *}, but never mind...)

@crusso
Copy link
Contributor

crusso commented Jan 28, 2022

(wrote you a drun test in #3081 - to merge into this branch)

@mergify mergify bot merged commit 09dcba8 into master Jan 28, 2022
@mergify mergify bot removed the automerge-squash When ready, merge (using squash) label Jan 28, 2022
mergify bot pushed a commit that referenced this pull request Jan 28, 2022
Additional test for #3076 (testing wasm execution on IC)
@ggreif ggreif deleted the gabor/deconstruct-import branch January 29, 2022 00:06
@q-uint q-uint mentioned this pull request Feb 23, 2022
mergify bot pushed a commit that referenced this pull request Jun 4, 2022
This PR adds straightforward "go to definition" support for Motoko's pattern-style import syntax. 

For example, `import { v|als } "mo:base/Array"` and `v|als(x)` (where `|` represents the cursor) will correctly navigate to the corresponding `Array.vals` declaration. 

As with existing language server functionality, these changes do not yet account for variable shadowing. However, the updated `parse_module_header` function already parses import patterns such as (`import {alias = field} "..."`) based on the proposed generalized import syntax (#3076). 

Please let me know if additional explanation would be helpful for any of these changes. I also included four test cases to cover the newly expected behavior of `definition_handler` and `parse_module_header`. 

Tested in VSCode on WSL using the official Motoko extension.

Fixes #3078
Supersedes #3263

CC @kritzcreek, @crusso, @matthewhammer
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 this pull request may close these issues.

Allow explicit imports
3 participants