ローカル変数の参照,定義を実�
This commit is contained in:
129
SMILEBASIC/VM.d
129
SMILEBASIC/VM.d
@@ -7,6 +7,16 @@ import std.uni;
|
|||||||
import std.utf;
|
import std.utf;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
struct VMVariable
|
||||||
|
{
|
||||||
|
int index;
|
||||||
|
ValueType type;
|
||||||
|
this(int index, ValueType type)
|
||||||
|
{
|
||||||
|
this.index = index;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
class VM
|
class VM
|
||||||
{
|
{
|
||||||
Code[] code;
|
Code[] code;
|
||||||
@@ -14,33 +24,18 @@ class VM
|
|||||||
int pc;
|
int pc;
|
||||||
Value[] stack;
|
Value[] stack;
|
||||||
Value[] global;
|
Value[] global;
|
||||||
int[wstring] globalTable;
|
VMVariable[wstring] globalTable;
|
||||||
Function[wstring] functions;
|
Function[wstring] functions;
|
||||||
int bp;
|
int bp;
|
||||||
ValueType getType(wstring name)
|
this(Code[] code, int len, VMVariable[wstring] globalTable, Function[wstring] functions)
|
||||||
{
|
|
||||||
wchar s = name[name.length - 1];
|
|
||||||
switch(s)
|
|
||||||
{
|
|
||||||
case '$':
|
|
||||||
return ValueType.String;
|
|
||||||
case '#':
|
|
||||||
return ValueType.Double;
|
|
||||||
case '%':
|
|
||||||
return ValueType.Integer;
|
|
||||||
default:
|
|
||||||
return ValueType.Double;//DEFINT時
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this(Code[] code, int len, int[wstring] globalTable, Function[wstring] functions)
|
|
||||||
{
|
{
|
||||||
this.code = code;
|
this.code = code;
|
||||||
this.stack = new Value[16384];
|
this.stack = new Value[16384];
|
||||||
this.global = new Value[len];
|
this.global = new Value[len];
|
||||||
this.globalTable = globalTable;
|
this.globalTable = globalTable;
|
||||||
foreach(wstring k, int v ; globalTable)
|
foreach(wstring k, VMVariable v ; globalTable)
|
||||||
{
|
{
|
||||||
this.global[v] = Value(getType(k));
|
this.global[v.index] = Value(v.type);
|
||||||
}
|
}
|
||||||
this.functions = functions;
|
this.functions = functions;
|
||||||
}
|
}
|
||||||
@@ -79,7 +74,7 @@ class VM
|
|||||||
}
|
}
|
||||||
Value testGetGlobalVariable(wstring name)
|
Value testGetGlobalVariable(wstring name)
|
||||||
{
|
{
|
||||||
return global[globalTable[name]];
|
return global[globalTable[name].index];
|
||||||
}
|
}
|
||||||
void end()
|
void end()
|
||||||
{
|
{
|
||||||
@@ -90,12 +85,14 @@ enum CodeType
|
|||||||
{
|
{
|
||||||
Push,
|
Push,
|
||||||
PushG,
|
PushG,
|
||||||
|
PushL,
|
||||||
Operate,
|
Operate,
|
||||||
Return,
|
Return,
|
||||||
Goto,
|
Goto,
|
||||||
Gosub,
|
Gosub,
|
||||||
Print,
|
Print,
|
||||||
PopG,
|
PopG,
|
||||||
|
PopL,
|
||||||
GotoS,
|
GotoS,
|
||||||
GotoFalse,
|
GotoFalse,
|
||||||
GotoTrue,
|
GotoTrue,
|
||||||
@@ -193,7 +190,7 @@ class PopG : Code
|
|||||||
vm.global[var] = Value(cast(int)v.doubleValue);
|
vm.global[var] = Value(cast(int)v.doubleValue);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(v.type == ValueType.Void)
|
if(g.type == ValueType.Void)
|
||||||
{
|
{
|
||||||
vm.global[var] = v;
|
vm.global[var] = v;
|
||||||
return;
|
return;
|
||||||
@@ -205,6 +202,54 @@ class PopG : Code
|
|||||||
vm.global[var] = v;
|
vm.global[var] = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class PushL : Code
|
||||||
|
{
|
||||||
|
int var;
|
||||||
|
this(int var)
|
||||||
|
{
|
||||||
|
this.type = CodeType.PushL;
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
vm.push(vm.stack[vm.bp + var]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class PopL : Code
|
||||||
|
{
|
||||||
|
int var;
|
||||||
|
this(int var)
|
||||||
|
{
|
||||||
|
this.type = CodeType.PopL;
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
Value v;
|
||||||
|
Value g = vm.stack[vm.bp + var];
|
||||||
|
vm.pop(v);
|
||||||
|
if(v.type == ValueType.Integer && g.type == ValueType.Double)
|
||||||
|
{
|
||||||
|
vm.stack[vm.bp + var] = Value(cast(double)v.integerValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(g.type == ValueType.Integer && v.type == ValueType.Double)
|
||||||
|
{
|
||||||
|
vm.stack[vm.bp + var] = Value(cast(int)v.doubleValue);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(g.type == ValueType.Void)
|
||||||
|
{
|
||||||
|
vm.stack[vm.bp + var] = v;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(v.type != g.type)
|
||||||
|
{
|
||||||
|
throw new TypeMismatch();
|
||||||
|
}
|
||||||
|
vm.stack[vm.bp + var] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
class Operate : Code
|
class Operate : Code
|
||||||
{
|
{
|
||||||
TokenType operator;
|
TokenType operator;
|
||||||
@@ -518,15 +563,13 @@ class EndVM : Code
|
|||||||
class NewArray : Code
|
class NewArray : Code
|
||||||
{
|
{
|
||||||
ValueType type;
|
ValueType type;
|
||||||
int index;
|
|
||||||
int size;
|
int size;
|
||||||
int[] dim;
|
int[] dim;
|
||||||
this(ValueType type, int size, int index)
|
this(ValueType type, int size)
|
||||||
{
|
{
|
||||||
dim = new int[size];
|
dim = new int[size];
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.index = index;
|
|
||||||
}
|
}
|
||||||
override void execute(VM vm)
|
override void execute(VM vm)
|
||||||
{
|
{
|
||||||
@@ -546,24 +589,26 @@ class NewArray : Code
|
|||||||
}
|
}
|
||||||
throw new TypeMismatch();
|
throw new TypeMismatch();
|
||||||
}
|
}
|
||||||
|
Value array;
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case ValueType.Integer:
|
case ValueType.Integer:
|
||||||
vm.global[index].type = ValueType.IntegerArray;
|
array.type = ValueType.IntegerArray;
|
||||||
vm.global[index].integerArray = new Array!int(dim);
|
array.integerArray = new Array!int(dim);
|
||||||
break;
|
break;
|
||||||
case ValueType.Double:
|
case ValueType.Double:
|
||||||
vm.global[index].type = ValueType.DoubleArray;
|
array.type = ValueType.DoubleArray;
|
||||||
vm.global[index].doubleArray = new Array!double(dim);
|
array.doubleArray = new Array!double(dim);
|
||||||
break;
|
break;
|
||||||
case ValueType.String:
|
case ValueType.String:
|
||||||
vm.global[index].type = ValueType.StringArray;
|
array.type = ValueType.StringArray;
|
||||||
vm.global[index].stringArray = new Array!wstring(dim);
|
array.stringArray = new Array!wstring(dim);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new TypeMismatch();
|
throw new TypeMismatch();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
vm.push(array);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class PushArray : Code
|
class PushArray : Code
|
||||||
@@ -626,18 +671,28 @@ class PushArray : Code
|
|||||||
throw new TypeMismatch();
|
throw new TypeMismatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class PopGArray : Code
|
class PopArray : Code
|
||||||
{
|
{
|
||||||
int var;
|
int var;
|
||||||
int dim;
|
int dim;
|
||||||
this(int var, int dim)
|
bool local;
|
||||||
|
this(int var, int dim, bool local)
|
||||||
{
|
{
|
||||||
this.var = var;
|
this.var = var;
|
||||||
this.dim = dim;
|
this.dim = dim;
|
||||||
|
this.local = local;
|
||||||
}
|
}
|
||||||
override void execute(VM vm)
|
override void execute(VM vm)
|
||||||
{
|
{
|
||||||
Value array = vm.global[var];
|
Value array;
|
||||||
|
if(local)
|
||||||
|
{
|
||||||
|
array = vm.stack[vm.bp + var];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
array = vm.global[var];
|
||||||
|
}
|
||||||
if(!array.isArray)
|
if(!array.isArray)
|
||||||
{
|
{
|
||||||
throw new TypeMismatch();
|
throw new TypeMismatch();
|
||||||
@@ -745,5 +800,13 @@ class CallFunctionCode : Code
|
|||||||
vm.push(Value(vm.pc));
|
vm.push(Value(vm.pc));
|
||||||
vm.bp = bp;
|
vm.bp = bp;
|
||||||
vm.pc = func.address - 1;
|
vm.pc = func.address - 1;
|
||||||
|
vm.stacki += func.variableIndex - 1;
|
||||||
|
foreach(wstring k, VMVariable v ; func.variable)
|
||||||
|
{
|
||||||
|
if(v.index > 0)
|
||||||
|
{
|
||||||
|
vm.stack[bp + v.index] = Value(v.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,10 +13,11 @@ class Scope
|
|||||||
this()
|
this()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
this(GotoAddr breakAddr, GotoAddr continueAddr)
|
this(GotoAddr breakAddr, GotoAddr continueAddr, Scope parent)
|
||||||
{
|
{
|
||||||
this.breakAddr = breakAddr;
|
this.breakAddr = breakAddr;
|
||||||
this.continueAddr = continueAddr;
|
this.continueAddr = continueAddr;
|
||||||
|
this.func = parent.func;
|
||||||
}
|
}
|
||||||
this(Function func)
|
this(Function func)
|
||||||
{
|
{
|
||||||
@@ -30,7 +31,7 @@ class Function
|
|||||||
int argCount;
|
int argCount;
|
||||||
int argumentIndex;
|
int argumentIndex;
|
||||||
int variableIndex;
|
int variableIndex;
|
||||||
int[wstring] variable;
|
VMVariable[wstring] variable;
|
||||||
int[wstring] label;
|
int[wstring] label;
|
||||||
bool returnExpr;
|
bool returnExpr;
|
||||||
this(int address, wstring name, bool returnExpr, int argCount)
|
this(int address, wstring name, bool returnExpr, int argCount)
|
||||||
@@ -41,23 +42,28 @@ class Function
|
|||||||
this.argCount = argCount;
|
this.argCount = argCount;
|
||||||
this.variableIndex = 1;//0,bp,1,pc
|
this.variableIndex = 1;//0,bp,1,pc
|
||||||
}
|
}
|
||||||
int getLocalVarIndex(wstring name)
|
int getLocalVarIndex(wstring name, Compiler c)
|
||||||
{
|
{
|
||||||
int var = this.variable.get(name, 0);
|
int var = this.variable.get(name, VMVariable()).index;
|
||||||
if(var == 0)
|
if(var == 0)
|
||||||
{
|
{
|
||||||
//local変数をあたる
|
//local変数をあたる
|
||||||
//それでもだめならOPTION STRICTならエラー
|
//それでもだめならOPTION STRICTならエラー
|
||||||
this.variable[name] = var = ++variableIndex;
|
this.variable[name] = VMVariable(var = ++variableIndex, c.getType(name));
|
||||||
}
|
}
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
int defineLocalVarIndex(wstring name)
|
int hasLocalVarIndex(wstring name)
|
||||||
{
|
{
|
||||||
int var = this.variable.get(name, 0);
|
int var = this.variable.get(name, VMVariable()).index;
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
int defineLocalVarIndex(wstring name, Compiler c)
|
||||||
|
{
|
||||||
|
int var = this.variable.get(name, VMVariable()).index;
|
||||||
if(var == 0)
|
if(var == 0)
|
||||||
{
|
{
|
||||||
this.variable[name] = var = ++variableIndex;
|
this.variable[name] = VMVariable(var = ++variableIndex, c.getType(name));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -66,12 +72,12 @@ class Function
|
|||||||
}
|
}
|
||||||
return var;
|
return var;
|
||||||
}
|
}
|
||||||
int defineArgumentIndex(wstring name)
|
int defineArgumentIndex(wstring name, Compiler c)
|
||||||
{
|
{
|
||||||
int var = this.variable.get(name, 0);
|
int var = this.variable.get(name, VMVariable()).index;
|
||||||
if(var == 0)
|
if(var == 0)
|
||||||
{
|
{
|
||||||
this.variable[name] = var = --argumentIndex;
|
this.variable[name] = VMVariable(var = --argumentIndex, c.getType(name));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -106,7 +112,7 @@ class Compiler
|
|||||||
}
|
}
|
||||||
|
|
||||||
Code[] code;
|
Code[] code;
|
||||||
int[wstring] global;
|
VMVariable[wstring] global;
|
||||||
int[wstring] globalLabel;
|
int[wstring] globalLabel;
|
||||||
Function[wstring] functions;
|
Function[wstring] functions;
|
||||||
int globalIndex = 0;
|
int globalIndex = 0;
|
||||||
@@ -126,6 +132,36 @@ class Compiler
|
|||||||
{
|
{
|
||||||
code ~= new PopG(ind);
|
code ~= new PopG(ind);
|
||||||
}
|
}
|
||||||
|
void genCodePushVar(wstring name, Scope sc)
|
||||||
|
{
|
||||||
|
auto global = hasGlobalVarIndex(name);
|
||||||
|
if(global)
|
||||||
|
{
|
||||||
|
code ~= new PushG(global);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(sc.func)
|
||||||
|
{
|
||||||
|
code ~= new PushL(sc.func.getLocalVarIndex(name, this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
code ~= new PushG(getGlobalVarIndex(name));
|
||||||
|
}
|
||||||
|
void genCodePopVar(wstring name, Scope sc)
|
||||||
|
{
|
||||||
|
auto global = hasGlobalVarIndex(name);
|
||||||
|
if(global)
|
||||||
|
{
|
||||||
|
code ~= new PopG(global);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(sc.func)
|
||||||
|
{
|
||||||
|
code ~= new PopL(sc.func.getLocalVarIndex(name, this));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
code ~= new PopG(getGlobalVarIndex(name));
|
||||||
|
}
|
||||||
void genCodeOP(TokenType op)
|
void genCodeOP(TokenType op)
|
||||||
{
|
{
|
||||||
code ~= new Operate(op);
|
code ~= new Operate(op);
|
||||||
@@ -164,10 +200,36 @@ class Compiler
|
|||||||
}
|
}
|
||||||
int defineGlobalVarIndex(wstring name)
|
int defineGlobalVarIndex(wstring name)
|
||||||
{
|
{
|
||||||
int global = this.global.get(name, 0);
|
int global = this.global.get(name, VMVariable()).index;
|
||||||
if(global == 0)
|
if(global == 0)
|
||||||
{
|
{
|
||||||
this.global[name] = global = ++globalIndex;
|
this.global[name] = VMVariable(global = ++globalIndex, getType(name));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//error:二重定義
|
||||||
|
throw new DuplicateVariable();
|
||||||
|
}
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
int defineVarIndex(wstring name, Scope sc)
|
||||||
|
{
|
||||||
|
if(sc.func)
|
||||||
|
{
|
||||||
|
return sc.func.defineLocalVarIndex(name, this);
|
||||||
|
}
|
||||||
|
return defineGlobalVarIndex(name);
|
||||||
|
}
|
||||||
|
int defineVarIndexVoid(wstring name, Scope sc)
|
||||||
|
{
|
||||||
|
if(sc.func)
|
||||||
|
{
|
||||||
|
return sc.func.defineLocalVarIndex(name, this);
|
||||||
|
}
|
||||||
|
int global = this.global.get(name, VMVariable()).index;
|
||||||
|
if(global == 0)
|
||||||
|
{
|
||||||
|
this.global[name] = VMVariable(global = ++globalIndex, ValueType.Void);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -178,16 +240,32 @@ class Compiler
|
|||||||
}
|
}
|
||||||
int getGlobalVarIndex(wstring name)
|
int getGlobalVarIndex(wstring name)
|
||||||
{
|
{
|
||||||
int global = this.global.get(name, 0);
|
int global = this.global.get(name, VMVariable()).index;
|
||||||
if(global == 0)
|
if(global == 0)
|
||||||
{
|
{
|
||||||
//local変数をあたる
|
//local変数をあたる
|
||||||
//それでもだめならOPTION STRICTならエラー
|
//それでもだめならOPTION STRICTならエラー
|
||||||
this.global[name] = global = ++globalIndex;
|
this.global[name] = VMVariable(global = ++globalIndex, getType(name));
|
||||||
}
|
}
|
||||||
return global;
|
return global;
|
||||||
}
|
}
|
||||||
void compileExpression(Expression exp)
|
int hasGlobalVarIndex(wstring name)
|
||||||
|
{
|
||||||
|
int global = this.global.get(name, VMVariable()).index;
|
||||||
|
return global;
|
||||||
|
}
|
||||||
|
int getLocalVarIndex(wstring name, Scope sc)
|
||||||
|
{
|
||||||
|
if(sc.func)
|
||||||
|
{
|
||||||
|
int global = hasGlobalVarIndex(name);
|
||||||
|
if(global) return global;
|
||||||
|
int local = sc.func.getLocalVarIndex(name, this);
|
||||||
|
return local;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void compileExpression(Expression exp, Scope sc)
|
||||||
{
|
{
|
||||||
if(!exp)
|
if(!exp)
|
||||||
{
|
{
|
||||||
@@ -202,8 +280,8 @@ class Compiler
|
|||||||
case NodeType.BinaryOperator:
|
case NodeType.BinaryOperator:
|
||||||
{
|
{
|
||||||
auto binop = cast(BinaryOperator)exp;
|
auto binop = cast(BinaryOperator)exp;
|
||||||
compileExpression(binop.item1);
|
compileExpression(binop.item1, sc);
|
||||||
compileExpression(binop.item2);
|
compileExpression(binop.item2, sc);
|
||||||
if(binop.operator == TokenType.LBracket)
|
if(binop.operator == TokenType.LBracket)
|
||||||
{
|
{
|
||||||
IndexExpressions ie = cast(IndexExpressions)binop.item2;
|
IndexExpressions ie = cast(IndexExpressions)binop.item2;
|
||||||
@@ -223,20 +301,20 @@ class Compiler
|
|||||||
case NodeType.UnaryOperator:
|
case NodeType.UnaryOperator:
|
||||||
{
|
{
|
||||||
auto una = cast(UnaryOperator)exp;
|
auto una = cast(UnaryOperator)exp;
|
||||||
compileExpression(una.item);
|
compileExpression(una.item, sc);
|
||||||
genCodeOP(una.operator);
|
genCodeOP(una.operator);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NodeType.Variable:
|
case NodeType.Variable:
|
||||||
auto var = cast(Variable)exp;
|
auto var = cast(Variable)exp;
|
||||||
genCodePushGlobal(getGlobalVarIndex(var.name));
|
genCodePushVar(var.name, sc);
|
||||||
break;
|
break;
|
||||||
case NodeType.CallFunction:
|
case NodeType.CallFunction:
|
||||||
{
|
{
|
||||||
auto func = cast(CallFunction)exp;
|
auto func = cast(CallFunction)exp;
|
||||||
foreach_reverse(Expression i ; func.args)
|
foreach_reverse(Expression i ; func.args)
|
||||||
{
|
{
|
||||||
compileExpression(i);
|
compileExpression(i, sc);
|
||||||
}
|
}
|
||||||
genCode(new CallFunctionCode(func.name, func.args.length));
|
genCode(new CallFunctionCode(func.name, func.args.length));
|
||||||
}
|
}
|
||||||
@@ -247,7 +325,7 @@ class Compiler
|
|||||||
int count = 0;
|
int count = 0;
|
||||||
foreach_reverse(Expression i; index.expressions)
|
foreach_reverse(Expression i; index.expressions)
|
||||||
{
|
{
|
||||||
compileExpression(i);
|
compileExpression(i, sc);
|
||||||
count++;
|
count++;
|
||||||
if(count >= 4) break;//念のため
|
if(count >= 4) break;//念のため
|
||||||
}
|
}
|
||||||
@@ -260,7 +338,7 @@ class Compiler
|
|||||||
}
|
}
|
||||||
void compileIf(If node, Scope sc)
|
void compileIf(If node, Scope sc)
|
||||||
{
|
{
|
||||||
compileExpression(node.condition);
|
compileExpression(node.condition, sc);
|
||||||
//条件式がfalseならendif or elseに飛ぶ
|
//条件式がfalseならendif or elseに飛ぶ
|
||||||
auto else_ = genCodeGotoFalse();
|
auto else_ = genCodeGotoFalse();
|
||||||
compileStatements(node.then, sc);
|
compileStatements(node.then, sc);
|
||||||
@@ -283,7 +361,7 @@ class Compiler
|
|||||||
{
|
{
|
||||||
compileStatement(node.initExpression, s);
|
compileStatement(node.initExpression, s);
|
||||||
auto forstart = code.length;
|
auto forstart = code.length;
|
||||||
compileExpression(node.stepExpression);
|
compileExpression(node.stepExpression, s);
|
||||||
genCodeImm(Value(0));
|
genCodeImm(Value(0));
|
||||||
//step>=0
|
//step>=0
|
||||||
genCodeOP(TokenType.GreaterEqual);
|
genCodeOP(TokenType.GreaterEqual);
|
||||||
@@ -296,8 +374,8 @@ class Compiler
|
|||||||
//FOR I=0 TO -1 STEP -1
|
//FOR I=0 TO -1 STEP -1
|
||||||
//-1>0 false
|
//-1>0 false
|
||||||
//1>0 true
|
//1>0 true
|
||||||
compileExpression(node.toExpression);
|
compileExpression(node.toExpression, s);
|
||||||
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
|
genCodePushVar(node.initExpression.name, s);
|
||||||
genCodeOP(TokenType.Greater);
|
genCodeOP(TokenType.Greater);
|
||||||
auto breakAddr = genCodeGotoTrue();
|
auto breakAddr = genCodeGotoTrue();
|
||||||
auto forAddr = genCodeGoto();
|
auto forAddr = genCodeGoto();
|
||||||
@@ -308,19 +386,19 @@ class Compiler
|
|||||||
//0<0 false
|
//0<0 false
|
||||||
//1<0 false
|
//1<0 false
|
||||||
//0<1 true break
|
//0<1 true break
|
||||||
compileExpression(node.toExpression);
|
compileExpression(node.toExpression, s);
|
||||||
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
|
genCodePushVar(node.initExpression.name, s);
|
||||||
genCodeOP(TokenType.Less);
|
genCodeOP(TokenType.Less);
|
||||||
genCode(breakAddr);
|
genCode(breakAddr);
|
||||||
forAddr.address = code.length;
|
forAddr.address = code.length;
|
||||||
s = new Scope(new GotoAddr(-1), new GotoAddr(-1));
|
s = new Scope(new GotoAddr(-1), new GotoAddr(-1), s);
|
||||||
compileStatements(node.statements, s);
|
compileStatements(node.statements, s);
|
||||||
s.continueAddr.address = code.length;
|
s.continueAddr.address = code.length;
|
||||||
//counterに加算する
|
//counterに加算する
|
||||||
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
|
genCodePushVar(node.initExpression.name, s);
|
||||||
compileExpression(node.stepExpression);
|
compileExpression(node.stepExpression, s);
|
||||||
genCodeOP(TokenType.Plus);
|
genCodeOP(TokenType.Plus);
|
||||||
genCodePopGlobal(getGlobalVarIndex(node.initExpression.name));
|
genCodePopVar(node.initExpression.name, s);
|
||||||
genCodeGoto(forstart);
|
genCodeGoto(forstart);
|
||||||
breakAddr.address = code.length;
|
breakAddr.address = code.length;
|
||||||
s.breakAddr.address = code.length;
|
s.breakAddr.address = code.length;
|
||||||
@@ -332,8 +410,7 @@ class Compiler
|
|||||||
if(v.type == NodeType.DefineVariable)
|
if(v.type == NodeType.DefineVariable)
|
||||||
{
|
{
|
||||||
DefineVariable var = cast(DefineVariable)v;
|
DefineVariable var = cast(DefineVariable)v;
|
||||||
//TODO:local variable
|
defineVarIndex(var.name, sc);
|
||||||
defineGlobalVarIndex(var.name);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(v.type == NodeType.DefineArray)
|
if(v.type == NodeType.DefineArray)
|
||||||
@@ -342,12 +419,14 @@ class Compiler
|
|||||||
int siz = 0;
|
int siz = 0;
|
||||||
foreach_reverse(Expression expr; var.dim.expressions)
|
foreach_reverse(Expression expr; var.dim.expressions)
|
||||||
{
|
{
|
||||||
compileExpression(expr);
|
compileExpression(expr, sc);
|
||||||
siz++;
|
siz++;
|
||||||
if(siz == 4)
|
if(siz == 4)
|
||||||
break;//4次元まで(パーサーで除去するけど万が一に備えて
|
break;//4次元まで(パーサーで除去するけど万が一に備えて
|
||||||
}
|
}
|
||||||
genCode(new NewArray(getType(var.name), var.dim.expressions.length, defineGlobalVarIndex(var.name)));
|
defineVarIndexVoid(var.name, sc);
|
||||||
|
genCode(new NewArray(getType(var.name), var.dim.expressions.length));
|
||||||
|
genCodePopVar(var.name, sc);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -366,7 +445,7 @@ class Compiler
|
|||||||
Scope sc = new Scope(func);
|
Scope sc = new Scope(func);
|
||||||
foreach(wstring arg; node.arguments)
|
foreach(wstring arg; node.arguments)
|
||||||
{
|
{
|
||||||
func.defineArgumentIndex(arg);
|
func.defineArgumentIndex(arg, this);
|
||||||
}
|
}
|
||||||
compileStatements(node.functionBody, sc);
|
compileStatements(node.functionBody, sc);
|
||||||
skip.address = this.code.length;
|
skip.address = this.code.length;
|
||||||
@@ -384,7 +463,7 @@ class Compiler
|
|||||||
switch(j.type)
|
switch(j.type)
|
||||||
{
|
{
|
||||||
case PrintArgumentType.Expression:
|
case PrintArgumentType.Expression:
|
||||||
compileExpression(j.expression);
|
compileExpression(j.expression, s);
|
||||||
break;
|
break;
|
||||||
case PrintArgumentType.Line:
|
case PrintArgumentType.Line:
|
||||||
genCodeImm(Value("\n"));
|
genCodeImm(Value("\n"));
|
||||||
@@ -402,8 +481,8 @@ class Compiler
|
|||||||
case NodeType.Assign:
|
case NodeType.Assign:
|
||||||
{
|
{
|
||||||
auto assign = cast(Assign)i;
|
auto assign = cast(Assign)i;
|
||||||
compileExpression(assign.expression);
|
compileExpression(assign.expression, s);
|
||||||
genCodePopGlobal(getGlobalVarIndex(assign.name));
|
genCodePopVar(assign.name, s);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NodeType.Label:
|
case NodeType.Label:
|
||||||
@@ -444,7 +523,7 @@ class Compiler
|
|||||||
//値を返せる関数
|
//値を返せる関数
|
||||||
if(s.func.returnExpr)
|
if(s.func.returnExpr)
|
||||||
{
|
{
|
||||||
compileExpression(ret.expression);
|
compileExpression(ret.expression, s);
|
||||||
genCode(new ReturnFunction(s.func));
|
genCode(new ReturnFunction(s.func));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -480,9 +559,9 @@ class Compiler
|
|||||||
case NodeType.ArrayAssign:
|
case NodeType.ArrayAssign:
|
||||||
{
|
{
|
||||||
auto assign = cast(ArrayAssign)i;
|
auto assign = cast(ArrayAssign)i;
|
||||||
compileExpression(assign.assignExpression);
|
compileExpression(assign.assignExpression, s);
|
||||||
compileExpression(assign.indexExpression);
|
compileExpression(assign.indexExpression, s);
|
||||||
genCode(new PopGArray(getGlobalVarIndex(assign.name), assign.indexExpression.expressions.length));
|
genCode(new PopArray(getGlobalVarIndex(assign.name), assign.indexExpression.expressions.length, !(s.func is null)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -70,7 +70,9 @@ DEF A()
|
|||||||
RETURN 1
|
RETURN 1
|
||||||
END
|
END
|
||||||
DEF B(A,B[],C)
|
DEF B(A,B[],C)
|
||||||
?\"FUNCTION B\"
|
LOCAL=123
|
||||||
|
?\"FUNCTION B\",A,B,C
|
||||||
|
?LOCAL
|
||||||
RETURN -1
|
RETURN -1
|
||||||
END
|
END
|
||||||
");
|
");
|
||||||
|
|||||||
Reference in New Issue
Block a user