Link class is for evaluating links. A link is a statement in form of
a.b.c
, where all expressions after dots (in this case
b
and c
) are either identifiers1,
indexes2 or invocations3.
Expression before the dot is anything, even the ternary operator. These
expressions are link children.
Links are resolved iteratively, starting from the first expression. Every evaluated expression returns a property (a type or a primitive). But the first child might be a name of an imported file, therefore it is resolved differently from all the next children.
During dynamic creation of a class it is important to know what parts of the link are assigned. For example:
class Start {
= mid.end.endProperty // a is not assigned until mid, end and endProperty are
a = Middle()
mid .end.addedEndProperty = "anotherEndValue" /** it is applicable for
mid left hand-side of assignment too. mid and end need to be assigned first
**/
}
class Middle {
= End()
end }
class End {
= "endValue"
endProperty }
For convenience, I added these properties to the link instance:
index
: index of currently resolved childcurrentVariable
: value of currently resolved childcurrentParent
: previously resolved childtable
: symbolTable with currentVariable
as
variableTable
initialTable
: symbolTable before link evaluation, used
to resolve function arguments. It is useful in the following code:class A {
= 0
a = B()
b fun aFunction() {
.bFun(a, b) /** here table will change variableTable to B instance, therefore a and b
b properties will not be found for bFun call. That's why invocation arguments are resolved
using initialTable
**/
}
}
class B {
fun bFun(arg1,arg2) {
// do something
}
}
These variables are cleared after the end of the evaluation. However, I didn’t think about recursive functions:
class A {
= if(iter < 5) A() else Nothing()
a = if(parent == 0) 0 else parent.iter /** parent is a special property.
iter It returns an instance from which this instance is created or 0 **/
fun str() {return "iter, " + a.str()}
}
class Nothing() {
fun str() { return "end" }
}
In that case, when calling str()
, variable values
weren’t cleared. I might’ve come up with some hack, but again, I knew
that was bad solution. Link represents a token, it is not a place to
store evaluation values. So I moved state to function arguments. Link is
still a poorly written class that has bugs. I work on fixing them and
refactoring Link.
Identifier is a word, starting with a letter. All other symbols are letters, underscores or numbers↩︎
Index is a token for getting a value from string, array
or dictionary. It is an identifier with square brackets. Square brackets
contain index (or a key, if identifier is a name of a dictionary).
arrayName[2]
, dictionaryName["key"]
↩︎
Invocation is a function call or a class constructor.
call(a+b, someArgument=value)
,
ClassA(propertyName=value)
↩︎