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.