docs: add design notes for inner method dispatch and receiver-less calls
Add two design documents exploring language semantics: - `beta-style inner.txt` outlines a dispatch mechanism for `inner` method calls using a two-list approach with method bodies and inheritance chain tracking - `receiver-less calls.txt` analyzes implicit receiver resolution for bare function calls, proposing they resolve to `this` and using leading "." for top-level module function calls
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
Q1: What does this resolve to:
|
||||
|
||||
foo(arg)
|
||||
|
||||
It could be:
|
||||
1. this.foo(bar)
|
||||
2. EnclosingClass.foo(bar) // i.e. a static method call
|
||||
3. a call to a top-level function foo()
|
||||
|
||||
If we adopt the idea that a module is just a class definition (with some
|
||||
syntactic differences) and classes can be nested, then 3 really means "a call
|
||||
to a static method on the class surrounding the enclosing class".
|
||||
|
||||
I *don't* think we want the answer to the question to vary based on the name
|
||||
in question. We can't rely on name resolution to disambiguate because we don't
|
||||
know the full set of surrounding names in a single pass compiler. Also, it's
|
||||
semantically squishier.
|
||||
|
||||
I think the right answer is 1, it's an implicit call on this. That's what you
|
||||
want most often, I think. For imported modules, we could import them with a
|
||||
"prefix" (really import them as objects bound to named variables), so calling
|
||||
a top-level function in another module would be something like:
|
||||
|
||||
someModule.foo(arg)
|
||||
|
||||
This leaves the question of how *do* you call top level functions in your own
|
||||
module? I.e., how do we call foo here:
|
||||
|
||||
def foo(arg) { io.write("called foo!") }
|
||||
|
||||
class SomeClass {
|
||||
bar {
|
||||
// Want to call foo here...
|
||||
}
|
||||
}
|
||||
|
||||
This is analogous to:
|
||||
|
||||
class SomeModule {
|
||||
static foo(arg) { io.write("called foo!") }
|
||||
|
||||
class SomeClass {
|
||||
bar {
|
||||
// Want to call foo here...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
The obvious solution is to use the class name:
|
||||
|
||||
class SomeModule {
|
||||
static foo(arg) { io.write("called foo!") }
|
||||
|
||||
class SomeClass {
|
||||
bar {
|
||||
SomeModule.foo(arg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Which just leaves the question of what the class name of a top-level "module
|
||||
class" is.
|
||||
|
||||
Idea: it's unnamed, so you just use a leading ".":
|
||||
|
||||
def foo(arg) { io.write("called foo!") }
|
||||
|
||||
class SomeClass {
|
||||
bar {
|
||||
.foo(arg)
|
||||
}
|
||||
}
|
||||
|
||||
This mirrors C++'s unnamed scope thing:
|
||||
|
||||
::foo(arg);
|
||||
Reference in New Issue
Block a user