1
0
forked from Mirror/wren
Files
wren/doc/receiver-less calls 2.txt
2014-02-16 11:28:56 -06:00

147 lines
4.2 KiB
Plaintext

var baz = "top level"
class Foo {
bar {
baz
_baz
}
baz { "getter" }
_baz { "private getter" }
this {
_baz = "field"
}
}
Given `_foo`, how do we tell if it is:
1. A call to a private getter
2. Accessing a private field
3. Tearing off a reference to a private method
It's not 3 because of arity overloading. Wren doesn't really have method
tear-off because of this.)
This is hard because the getter may not be defined yet. One option is:
It's always a call to a private getter. After the class is defined, we see if
there are any private getters that were not implemented and define implicit
getters for them that return fields.
That's weird if you take into account setters, though. Consider:
class Foo {
a { IO.write(_prop) }
_prop = value { ... }
}
For first reference to `_prop`, compile it to getter call. Then see setter
defined for it, so we no longer implicitly make a field. But there's no getter,
so now the above call will fail.
Probably do want call to fail here, so that may be OK.
---
Given `_foo(arg)`, how do we tell if it is:
1. A call to a private method
2. A call to a private getter, which returns a field that's a fn, and invoking
it.
Since arity is part of the name, the answer here is 1.
---
Given `foo(arg)` inside a class, how do we tell if it is:
1. A call to a method on this.
2. Accessing a field `foo` on this, which returns a fn, and invoking it.
3. Calling a getter `foo` on this, which returns a fn, and invoking it.
4. A call to a top-level fn.
Let's just dismiss 3. Since arity affects naming, `foo(arg)` and `(foo)(arg)`
are really different things in Wren. The parentheses and args are effectively
part of the name.
That covers 2 as well. If we ditch top level fns, we're left with 1. This is
good, I think. It means the common case of calling methods on yourself is nice
and terse.
---
Given `foo` inside a class, how do we tell if it is:
1. Accessing a field on this.
2. Calling a getter on this.
3. Accessing a global variable.
4. Accessing a top-level getter.
5. Accessing a local variable.
We can probably ditch 4. We can ditch 1 because Wren doesn't have public fields.
Because both getters and global variables can be used before they are defined,
we can't determine statically (in a single pass compiler) if there is a global
variable or getter named `foo` in order to disambiguate. Even if we could, we'd
still have to answer the ambiguous case where it's both.
If we assume it's a global and the user wants a getter, they can always do
`this.foo` to be explicit. If we assume it's getter, how would they indicate a
global?
One option is to have a different naming convention for globals, like a
capitalized initial variable. That lines up with class names at the top level
anyway. It just means if we have variables for imported modules, we'll want to
capitalize those.
We still have to distinguish locals, but since those are declared before use, we
can determine that statically. I.e. locals will shadow implicit getters.
---
OK, so here's one proposal:
class MyClass {
method {
_foo // access field
_foo(arg) // not valid
foo // local var or getter on this
foo(arg) // method on this
Foo // global variable
}
}
This is simple, and straightforward to compile. Using capitalization for globals
is a bit weird, and not having private methods is a bummer, but maybe simplicity
is the right answer.
Here's another:
class MyClass {
method {
_foo // private getter on this
_foo(arg) // private method on this
foo // local var or getter on this
foo(arg) // method on this
Foo // global variable
}
}
To get rid of the weird capitalization rule for globals, one option is to not
allow forward references to globals. That would break mutually recursive
references to classes, though:
class A {
foo { B.new }
}
class B {
foo { A.new }
}
So, not a fan of that.
Ignoring that, the main difference between the two proposals is the second has
private methods. Since the first proposal is practically a subset of the second,
let's start with that one first.