# 變數與指定陳述

December 18, 2021

Toy Lang 是動態定型語言，變數本身並沒有型態資訊，只是用來對應至值或物件。

## Toy 語法

``````n = 10
n = 'Justin'
``````

``````println(x)
``````

`x` 變數不存在，會出現以下錯誤訊息：

``````ReferenceError: x is not defined
at println(x) (/main.toy:1)
``````

`=` 是個指定陳述，除了它之外，還有 `+=``-=``*=``/=``%=``&=``|=``>>`=、`<<=` 等指定陳述，與其他語言的指定陳述作用相同。例如：

``````x = 10
x += 2 # 相當於 x = x + 2
x -= 3 # 相當於 x = x - 3
``````

## Toy 實作

``````class Variable {
constructor(name) {
this.name = name;
}

evaluate(context) {
return context.lookUpVariable(this.name);
}
}
``````

``````class VariableAssign {
constructor(variable, value) {
this.variable = variable;
this.value = value;
}

evaluate(context) {
return context.assign(this.variable.name, value);
}
}
``````

``````x = 10
``````

``````const variableAssign = new VariableAssign(new Variable('x'), new Primitive(10))
``````

``````class Context {
constructor(variables = new Map()) {
this.variables = variables;
}

assign(variable, value) {
this.variables.set(variable, value);
return this;
}

lookUpVariable(name) {
return this.variables.get(name);
}
}

const context = new Context();
variableAssign.evaluate(context);
``````

（如果實作的是函數式語言，像指定陳述的執行結果，會是產生一個新的環境物件，內含指定陳述之後的結果。）

``````class StmtSequence {
constructor(firstStmt, secondStmt) {
this.firstStmt = firstStmt;
this.secondStmt = secondStmt;
}

evaluate(context) {
return this.secondStmt.evaluate(this.firstStmt.evaluate(context));
}
}
``````

``````x = 10
y = x + 20
``````

``````new StmtSequence(
new VariableAssign(
new Variable('x'),
new Primitive(10)
),
new VariableAssign(
new Variable('y'),
new Variable('x'),
new Primitive(20)
)
)
)
``````

``````new RegExp(`^(\${VARIABLE_REGEX.source})\\s*=\\s*(.*)\$`)]
``````

``````function createAssign(tokenableLines, clzNode, target, operatorTokenable, assignedTokenable) {
return new StmtSequence(
new clzNode(
target,
EXPR_PARSER.parse(assignedTokenable),
operatorTokenable.value
),
LINE_PARSER.parse(tokenableLines.slice(1)),
tokenableLines[0].lineNumber
);
}
``````

`createAssign` 不會去關心 `=` 右邊的事，這部份被交給了 `EXPR_PARSER`，也就是運算式剖析器，`EXPR_PARSER` 會對右邊剖析，建立相對應的運算式各語法節點。

``````StmtSequence.EMPTY = {
lineCount : 0,
// We don't care about emtpy statements so the lineNumber 0 is enough.
lineNumber : 0,
evaluate(context) {
return context;
}
};
``````