Skip to content
This repository has been archived by the owner on Dec 28, 2021. It is now read-only.

Connection discovery and IDE identifier resolving spec #349

Draft
wants to merge 10 commits into
base: develop
Choose a base branch
from

Conversation

mwu-tow
Copy link
Contributor

@mwu-tow mwu-tow commented Apr 6, 2020

Pull Request Description

This PR describes language rules as I understand them in a scope necessary to implement proper connection discovery (#320). It covers general language rules (that are relevant) and assumptions and simplifications that IDE can currently make.

Also, a number of TODO notes are left for things that I don't understand yet or that haven't been clearly specified. They are not blocking the implementation for connections, rather something that we are allowed to fill out later.

Important Notes

Checklist

Please include the following checklist in your PR:

  • The documentation has been updated if necessary.
  • All code conforms to the Rust, Scala, Java or Haskell style guides as appropriate.
  • All code has been tested where possible.

@mwu-tow mwu-tow added Category: Documentation Documentation Change: Non-Breaking Difficulty: Core Contributor Should only be attempted by a core contributor Priority: Highest Should be completed ASAP Type: Enhancement An enhancement to the current state of Enso IDE Category: Controllers The Application layer not bound to visual part labels Apr 6, 2020
@mwu-tow mwu-tow requested review from wdanilo and farmaazon April 6, 2020 00:47
@mwu-tow mwu-tow self-assigned this Apr 6, 2020
@mwu-tow mwu-tow added this to the Sprint 2020-03-30 milestone Apr 6, 2020
Copy link
Collaborator

@farmaazon farmaazon left a comment

Choose a reason for hiding this comment

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

And as I understand the only case where identifier in node "body" (expression, right-side assignment operator) is shadowed is only lambda currently, right?

argument (lambdas are always unary) and the right-hand side is its body.
Right-hand side, i.e. the lambda body, introduces its own scope.

If the lambda is *not* introduced in what is already a pattern context, the `->`'s pattern introduces identifiers into the scope of the right-hand
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think you introduced pattern scopes, and pattern context is a term from some previous version of this doc.

Copy link
Contributor

@iamrecursion iamrecursion left a comment

Choose a reason for hiding this comment

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

Added a bunch of comments. Happy to discuss any of it with you.

* shadow identifiers from nested scope with a new binding;
* introduce new constraints on the identifiers from parent (or own) scopes.

The same identifier may be bound multiple times in the same scope (overloading).
Copy link
Contributor

Choose a reason for hiding this comment

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

This is currently not supported outside the global scope. We have an agreement that methods can only be defined in the global scope, so this seems fine to me. If that design decision has changed please let me know.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is it "currently not supported" as-in:

  1. The language implementation doesn't support it but the language deisgn itself allows it (kind like missing feature)
  2. Language doesn't allow this but we could? (just by relaxing some rule)
  3. We won't allow this unless there's significant change in the design?

For now I've noted this as the current implementation limitation, can change if needed.

Copy link
Contributor

Choose a reason for hiding this comment

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

Currently it's a tentative 2. There are technical obstacles given the current way method lookup is performed in the interpreter, but also there would be some typechecking obstacles to doing it which I'm a little unclear on given I'm somewhat divorced from that work right now. The design currently forbids, it, and we'd have to solve these technical challenges to allow it.

It is allowed only for method overloads that differ in the type of the `this`
parameter. This limitation may be relaxed in the future, if proper motivating use-cases are found.

The identifier is always accessible scope-wide, both before and after the line
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't something that is (or can be) handled at the moment. Additionally, it doesn't make sense. The definition of the desugaring of monadic contexts (in terms of bind) introduces an ordering dependency. If we want to distinguish between expressions in Pure and lift those into mutually recursive let blocks, that is a whole other kettle of fish that will require the typechecker.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From what I've understood from Wojciech's description:

  1. we don't support this in the near-term
  2. eventually we want this to work (at least so language design assumes)

I've added the description to the document.
Basicallt to avoid out-of-order variable usage, special rewrite rule is used that relies on the fix function. (that tricky thing from Haskell that you likely understand better than me. )Its implementation is specific to the monadic context of the code block.

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah we definitely want it to work eventually, but this is very much eventually.

Some other constructs seemingly introduce scope (like function definitions) but
this is because they are desugared into some construct that introduces scope (like lambdas).

TODO: Consider if there are any special rules for signatures on definitions, or
Copy link
Contributor

Choose a reason for hiding this comment

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

The identifiers defined in a signature are available in the body of the function, and vice-versa.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The vice-versa part looks tricky to me and not consistent with other rules. But generally I want to defer specifying the type ascription (as it won't be implemented for a while), and focus on other parts of the language.
For now I just try to record more important design questions to be addressed.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's fair.

And yes, it is tricky, but it's also necessary for the way we're planning on handling dependency in type ascription. We want the ability to be able to define a type function foo in the body that can then be used in the signature.


Details will follow with description of these operators.

// TODO What about `case … of` ? Are there any other pattern-introducing constructs?
Copy link
Contributor

Choose a reason for hiding this comment

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

The scrutinee of a case expression is not a pattern context, but the left hand side of the battern branches is.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Clarified.

```

Therefore, only `value` will be introduced into the parent scope. `Some` and
`get_opt` must be defined, the former being an atom with at least single field.
Copy link
Contributor

Choose a reason for hiding this comment

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

You should explain why you say "at least" here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding is that the language allows matching constructors with "missing" trailing fields. (as if there were arbitrary needed number of _ following)
I've clarified, though it gets little beyond the scope of this document.


TODO: Open question: does empty type (`Void`) exists in the language?

TODO signatures and their relation with scoping. Difference for root and
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you expand on this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The example below shows some questions. Other were mentioned before, e.g. how and why scoping for identifiers introduced in a signature works for the body and vice-versa. Likely that should be a consequence of some more generals rules and desugaring.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see what you mean. I think I've addressed it with other comments, but let me know if things are unclear.

will be unified with other uses of `a` in other definitions.
* or, actually, we want this to happen only in the root scope. When in
definition body, the `a` actually should be unified between signatures.
Doesn't sound that clean though.
Copy link
Contributor

Choose a reason for hiding this comment

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

Not clean at all.

Doesn't sound that clean though.
* Does argument-introduced `a` shadows the signature-introduced `a`?

TODO: `b:A` — does this add constraint to `a` or just `b` ?
Copy link
Contributor

Choose a reason for hiding this comment

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

Complex question of inference that can't easily be answered at this stage given how nebulous the type system is. Does it matter for the purposes of IDE right now?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Not at all. We disregard all type ascriptions for now.
But since I've created a section for them, I thought it was something worth asking.

IDE can assume that all extension methods will be introduced using the
`Type.name` syntax sugar.

// TODO what if non-first argument is named `this` ? Is the magic happening only
Copy link
Contributor

Choose a reason for hiding this comment

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

It is an error to define this at any position other than the first in the argument list.


// TODO what if non-first argument is named `this` ? Is the magic happening only
for this particular name? Is it sensitive for its position in the arguments list?
// TODO What happens if the `this`-taking function in defined in the root scope
Copy link
Contributor

Choose a reason for hiding this comment

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

This will also be an error.


## Out of order variable usage in block
If within a block an identifier is used in the line before it is assigned, the
`fix` function appropriate for the block's monadic context will be introduced.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't know how performantly we can do this without a typechecker. The implementation doesn't currently support it, and I'll need to talk to Marcin about it when he's back.

@iamrecursion iamrecursion changed the base branch from master to main June 15, 2020 17:53
Base automatically changed from main to develop February 2, 2021 05:08
@farmaazon farmaazon requested a review from iamrecursion April 15, 2021 09:45
@farmaazon
Copy link
Collaborator

@iamrecursion could you please look at this document again? It was written before removing UFCS and likely outdated in many places.

@wdanilo
Copy link
Member

wdanilo commented Jun 2, 2021

What is the status of this ?

@farmaazon
Copy link
Collaborator

What is the status of this ?

It waits for @iamrecursion after-UFCS-check. See my comment above. And because we have other priorities right now, it seem properly frozen in icebox.

@MichaelMauderer MichaelMauderer marked this pull request as draft September 16, 2021 16:47
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Category: Controllers The Application layer not bound to visual part Category: Documentation Documentation Difficulty: Core Contributor Should only be attempted by a core contributor Priority: Highest Should be completed ASAP Type: Enhancement An enhancement to the current state of Enso IDE
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants