mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 06:08:41 +01:00
Some design notes.
This commit is contained in:
55
doc/beta-style inner.txt
Normal file
55
doc/beta-style inner.txt
Normal file
@ -0,0 +1,55 @@
|
||||
class Base {
|
||||
foo {
|
||||
io.write("a")
|
||||
inner
|
||||
io.write("b")
|
||||
}
|
||||
}
|
||||
|
||||
class Mid is Base {}
|
||||
|
||||
class Derived is Mid {
|
||||
foo {
|
||||
io.write("c")
|
||||
}
|
||||
}
|
||||
|
||||
var d = Derived.new
|
||||
d.foo
|
||||
|
||||
// find base-most method "foo" (on Base)
|
||||
// invoke it
|
||||
// when inner is hit, walk down inheritance chain to find nearest override
|
||||
// (in Derived)
|
||||
// invoke it
|
||||
|
||||
|
||||
for every class, store two lists:
|
||||
|
||||
1. list of methods this class defines.
|
||||
2. mapping of method name to which method body should be invoked first for
|
||||
that method. this will be the base-most class's definition of a given
|
||||
method name.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// The method body to invoke. This will be the base-most definition of a
|
||||
// method for a given name.
|
||||
Method* method;
|
||||
|
||||
// If [method] calls `inner`, this is the class whose inner method is invoked.
|
||||
// If *that* method in turn calls `inner`, we look up the [inner] property of
|
||||
// this method on that class's dispatch table to chain to the next one.
|
||||
//
|
||||
// This is `NULL` if there is no inner method to call.
|
||||
ClassObj* inner;
|
||||
} Dispatch;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Dispatch dispatchTable[MAX_SYMBOLS];
|
||||
} ClassObj;
|
||||
|
||||
with normal overridding, can unify those. with inner(), need both.
|
||||
|
||||
whenever a method is invoked, look it up in 2, then call that method body.
|
||||
76
doc/receiver-less calls.txt
Normal file
76
doc/receiver-less calls.txt
Normal file
@ -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