Field Resolution in Whiley
An interesting issue has arisen as a result of my recent decision to move away from a declared-type model. The issue is essentially about scope resolution of fields and local variables. For example, consider the following:
define MyProc as process { int f }
void MyProc::m(int x):
f = x
Now, m(int)
is a method acting on a process of type MyProc
. Thus, the special variable this
has type MyProc
(much like it would in Java). So, the question is: does the assignment f = x
create a new local variable, or update field f
in the process referred to by this
? In Java, this problem wouldn’t arise since we would have to have declared variable f
, in order for it to be treated as a local.
There are a few different ways this could be resolved:
We always default to a field if one of the given name exists.
We always default to a local variable if one of the given name exists, and always for assignments.
The problem with (1) is that it means a later change to the fields of some type may affect the meaning of methods declared elsewhere in subtle, and hard-to-track ways. This is because we might add a new field to some existing type, and that field now clashes with what was a local variable in some method (which, following (1), would now refer to the new field). For this reason, I prefer option (2). Thus, in the above example, the assignment creates a new local variable which will subsequently be the default scope for variables named f
.
If we want to update the field f
in the process referred to by this
, we need to be explicit:
define MyProc as process { int f }
void MyProc::m(int x):
this.f = x
Thus, only in the case that a matching local variable does not exist will the system infer that a variable is, in fact, a field access. The following example illustrates:
void System::main([string] args):
out.println("Hello World")
Here, out
does not correspond to a local variable and, since System
is a process type with a field out
, it is automatically expanded to the following:
void System::main([string] args):
this.out.println("Hello World")
Anyway, this seems to be the best way to resolve this particular issue … I guess time will tell!