-
Notifications
You must be signed in to change notification settings - Fork 332
Semi-formal specification for method resolution #13961
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
base: develop
Are you sure you want to change the base?
Conversation
RFC engine and libs team (@JaroslavTulach , @jdunkerley , @4e6 , @hubertp , @GregoryTravis ): Do you consider this kind of semi-formal specification for method resolution and method evaluation useful? Is it better than looking at our tests or in our code base? Do you want me to finish it? Do you have any other suggestions how to improve it? Note that this PR is WIP, obviously. |
docs/types/dynamic-dispatch.md
Outdated
- 1.4. If `Receiver` is a polyglot object, go to step 5. | ||
- 1.5. If there is no `Receiver`, go to step 6. | ||
|
||
2. **`Receiver` is a type. This call site is a _static method call_:** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To play devil's advocate:
- Isn't it all a bit different?
- The 1st step is to find a
Type
for the receiver- for
Atom
the type is its constructor defining type - for module the type is its associated type
- for a
Type
it is its eigen type - etc.?
- for
- then lookup the method in the pool of that type or
- its
getSupertype
pool and so on
- its
- if a method is found, invoke it with
self
being set to the receiver - 00577f7 documents/tests the chain of types and shows how we want to use
allTypes
method - if no such a method is found, consider static invocation of instance method!?
and somewhere here my thoughts dry out...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and somewhere here my thoughts dry out...
- 00577f7 documents/tests the chain of types and shows how we want to use
allTypes
method
- I am still relatively satisfied with 00577f7
- e.g. there are no "static" methods - those are instance methods on
Type.getEigentype()
- e.g. there are no "static" methods - those are instance methods on
- the only problem is the "duality of methods from Any"
- and I believe it is sufficiently solved by saying that:
- each method found on
Any
hasself
argument defaulted to the receiver - but it can be changed by
self=whatever
- each method found on
- at the end this sounds like a consistent set of rules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have simplified the Method resolution specs in 5f6fdaa according to your suggestions, which makes sense:
- Determine type of the
Receiver
- Symbol lookup on the determined type.
docs/types/dynamic-dispatch.md
Outdated
- Every type has an implicit parent type `Any`. | ||
- Except for `Number` which is a special builtin case with a deeper hierarchy. | ||
- `Any` has no parent type. | ||
- 2.2. No parent type is present. Raise `No_Such_Method` panic and stop. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- 2.2. No parent type is present. Raise `No_Such_Method` panic and stop. | |
- 2.2. No parent type is present. Raise `No_Such_Method` panic and terminate. |
|
||
### Lexical scope lookup | ||
|
||
- If `symbol` is defined in the current lexical scope, select it and stop. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- This is not really a "dynamic dispatch"
- but it is an interesting topic
- and complicated - e.g. term like all transitively imported modules sounds scary
- I'd move it to its own "lexical dispatch" document
docs/types/dynamic-dispatch.md
Outdated
[Method Resolution](#method-resolution) process, that is defined as | ||
`method [self] [parName=[defaultValue]]* = <body expression>`. | ||
|
||
If `self` parameter is specified, we call it an _instance method_, otherwise, we |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I'd say this is wrong:
self
argument is always the first argument of each method- at least for each method that can be found in a lookup table of a type
- this is an important step towards Try to register only static methods during compilation #11686
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self argument is always the first argument of each method
It is, but from the engine perspective. From the engine perspective, every method has either a single self
argument, or two self
arguments. However, from the language perspective, you cannot declare self
argument on, for example, module methods, neither can you specify self
argument when you call such methods.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
two
self
arguments
- I don't understand why should there be two
self
arguments?- I heard about type of self and
self
itself - I am not sure what that would be good for?
- I heard about type of self and
- I don't even know when has a method two such arguments?
neither can you specify self argument when you call such module methods.
That would have little sense. self
argument is type checked and there is only a singleton of a module associated type. E.g. specifying any other self
to a module method would have to yield Type_Error
.
Co-authored-by: Jaroslav Tulach <jaroslav.tulach@enso.org>
Co-authored-by: Jaroslav Tulach <jaroslav.tulach@enso.org>
Algorithm according to #13962 (review)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Section 2, 3, 4 seem to be correct.
- `self` argument cannot be specified explicitly | ||
- Go to [Arguments evaluation](#argument-evaluation) to evaluate `argValue`s and | ||
bind them to `argName`s. | ||
### Example (a) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Instead of examples in the documentation, put them into a test case and link from here. Maybe?
- Documentation full of examples has only one future: to get outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added as a checklist point in #13962.
Co-authored-by: Jaroslav Tulach <jaroslav.tulach@enso.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another update. Let's differentiate:
- instance invocation syntax has no
self=
named argument - static syntax for invoking instance method has first argument
self=
- the decision what to search is thus done on syntactic level
- by presence/absence of the
self=
argument
var all = raw.allTypes(ctx.ensoContext()); | ||
|
||
var exp1 = any.getEigentype(); | ||
assertArrayEquals("Any.type only", new Object[] {exp1}, all); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrong
- this is the snapshot of current type hierarchy
- is it good or bad, @Akirathan?
- this should mean that when typing
Any.to_text
to perform an instance method invocation- the type of
Any
isAny.type
- which isAny
's eigentype - if
to_text
is registered inAny
's eigentype (No, it is not! it is registered inAny
as instance method!) - then it will be found during instance method invocation
- the type of
- thus
Any.to_text
should yield"Any"
Correct
After a discussion with @Akirathan we concluded, that the current behavior is wrong and it should be
assertArrayEquals("Any.type only", new Object[] {exp1}, all); | |
var exp1 = any.getEigentype(); | |
var exp2 = ctx.ensoContext().getBuiltins().any(); | |
assertArrayEquals("Any.type and Any", new Object[] {exp1, exp2}, all); |
that way the instance method dispatch should work for Any.to_text
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is bad. On develop, to_text
is registered both on Any
and on Any.type
. But ideally, it should be registered only on Any
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe that the correct semantics should be:
allTypes(Any.type) == [Any.type, Any]
allTypes(Any) == [Any]
allTypes(Text) == [Text, Any]
allTypes(Text.type) == [Text.type, Any]
allTypes(Integer) == [Integer, Number, Any]
...ion-tests/src/test/java/org/enso/interpreter/node/expression/builtin/meta/TypeChainTest.java
Show resolved
Hide resolved
This diff is more important than #13961 (comment) and it’s 7b58937 as it shows the diff against current behavior. Can we make it less red? |
Pull Request Description
Semi-formal spec for method invocation. Documents the desired behavior that is being implemented in #13962.
Important Notes
Checklist
Please ensure that the following checklist has been satisfied before submitting the PR:
Scala,
Java,
TypeScript,
and
Rust
style guides. In case you are using a language not listed above, follow the Rust style guide.
or the Snowflake database integration, a run of the Extra Tests has been scheduled.