break,continue実装,var,dim実装中
This commit is contained in:
@@ -5,6 +5,19 @@ import otya.smilebasic.vm;
|
|||||||
import otya.smilebasic.type;
|
import otya.smilebasic.type;
|
||||||
import otya.smilebasic.error;
|
import otya.smilebasic.error;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
class Scope
|
||||||
|
{
|
||||||
|
GotoAddr breakAddr;
|
||||||
|
GotoAddr continueAddr;
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
this(GotoAddr breakAddr, GotoAddr continueAddr)
|
||||||
|
{
|
||||||
|
this.breakAddr = breakAddr;
|
||||||
|
this.continueAddr = continueAddr;
|
||||||
|
}
|
||||||
|
}
|
||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
Statements statements;
|
Statements statements;
|
||||||
@@ -139,19 +152,19 @@ class Compiler
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void compileIf(If node)
|
void compileIf(If node, Scope sc)
|
||||||
{
|
{
|
||||||
compileExpression(node.condition);
|
compileExpression(node.condition);
|
||||||
//条件式がfalseならendif or elseに飛ぶ
|
//条件式がfalseならendif or elseに飛ぶ
|
||||||
auto else_ = genCodeGotoFalse();
|
auto else_ = genCodeGotoFalse();
|
||||||
compileStatements(node.then);
|
compileStatements(node.then, sc);
|
||||||
//もしelseもあるのならば、endifに飛ぶ
|
//もしelseもあるのならば、endifに飛ぶ
|
||||||
GotoAddr then;
|
GotoAddr then;
|
||||||
if(node.hasElse)
|
if(node.hasElse)
|
||||||
{
|
{
|
||||||
then = genCodeGoto();
|
then = genCodeGoto();
|
||||||
else_.address = code.length;
|
else_.address = code.length;
|
||||||
compileStatements(node.else_);
|
compileStatements(node.else_, sc);
|
||||||
then.address = code.length;
|
then.address = code.length;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -160,9 +173,9 @@ class Compiler
|
|||||||
else_.address = code.length;
|
else_.address = code.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void compileFor(For node)
|
void compileFor(For node, Scope s)
|
||||||
{
|
{
|
||||||
compileStatement(node.initExpression);
|
compileStatement(node.initExpression, s);
|
||||||
auto forstart = code.length;
|
auto forstart = code.length;
|
||||||
compileExpression(node.stepExpression);
|
compileExpression(node.stepExpression);
|
||||||
genCodeImm(Value(0));
|
genCodeImm(Value(0));
|
||||||
@@ -194,7 +207,9 @@ class Compiler
|
|||||||
genCodeOP(TokenType.Less);
|
genCodeOP(TokenType.Less);
|
||||||
genCode(breakAddr);
|
genCode(breakAddr);
|
||||||
forAddr.address = code.length;
|
forAddr.address = code.length;
|
||||||
compileStatements(node.statements);
|
s = new Scope(new GotoAddr(-1), new GotoAddr(-1));
|
||||||
|
compileStatements(node.statements, s);
|
||||||
|
s.continueAddr.address = code.length;
|
||||||
//counterに加算する
|
//counterに加算する
|
||||||
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
|
genCodePushGlobal(getGlobalVarIndex(node.initExpression.name));
|
||||||
compileExpression(node.stepExpression);
|
compileExpression(node.stepExpression);
|
||||||
@@ -202,16 +217,17 @@ class Compiler
|
|||||||
genCodePopGlobal(getGlobalVarIndex(node.initExpression.name));
|
genCodePopGlobal(getGlobalVarIndex(node.initExpression.name));
|
||||||
genCodeGoto(forstart);
|
genCodeGoto(forstart);
|
||||||
breakAddr.address = code.length;
|
breakAddr.address = code.length;
|
||||||
|
s.breakAddr.address = code.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void compileStatements(Statements statements)
|
void compileStatements(Statements statements, Scope sc)
|
||||||
{
|
{
|
||||||
foreach(Statement s ; statements.statements)
|
foreach(Statement s ; statements.statements)
|
||||||
{
|
{
|
||||||
compileStatement(s);
|
compileStatement(s, sc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void compileStatement(Statement i)
|
void compileStatement(Statement i, Scope s)
|
||||||
{
|
{
|
||||||
switch(i.type)
|
switch(i.type)
|
||||||
{
|
{
|
||||||
@@ -257,10 +273,10 @@ class Compiler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NodeType.If:
|
case NodeType.If:
|
||||||
compileIf(cast(If)i);
|
compileIf(cast(If)i, s);
|
||||||
break;
|
break;
|
||||||
case NodeType.For:
|
case NodeType.For:
|
||||||
compileFor(cast(For)i);
|
compileFor(cast(For)i, s);
|
||||||
break;
|
break;
|
||||||
case NodeType.Gosub:
|
case NodeType.Gosub:
|
||||||
{
|
{
|
||||||
@@ -282,15 +298,32 @@ class Compiler
|
|||||||
case NodeType.End:
|
case NodeType.End:
|
||||||
genCode(new EndVM());
|
genCode(new EndVM());
|
||||||
break;
|
break;
|
||||||
|
case NodeType.Break:
|
||||||
|
if(s.breakAddr is null)
|
||||||
|
{
|
||||||
|
//syntax-error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
genCode(s.breakAddr);
|
||||||
|
break;
|
||||||
|
case NodeType.Continue:
|
||||||
|
if(s.continueAddr is null)
|
||||||
|
{
|
||||||
|
//syntax-error
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
genCode(s.continueAddr);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
stderr.writeln("Compile:NotImpl ", i.type);
|
stderr.writeln("Compile:NotImpl ", i.type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
VM compile()
|
VM compile()
|
||||||
{
|
{
|
||||||
|
Scope s = new Scope();
|
||||||
foreach(Statement i ; statements.statements)
|
foreach(Statement i ; statements.statements)
|
||||||
{
|
{
|
||||||
compileStatement(i);
|
compileStatement(i, s);
|
||||||
}
|
}
|
||||||
foreach(int i, Code c; code)
|
foreach(int i, Code c; code)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ NEXT
|
|||||||
?(1 OR 2 XOR 3)
|
?(1 OR 2 XOR 3)
|
||||||
?(1 OR 2 XOR 3 OR 4)
|
?(1 OR 2 XOR 3 OR 4)
|
||||||
?@HELLOWORLD
|
?@HELLOWORLD
|
||||||
|
FOR I=0 TO 10
|
||||||
|
IF I==4 THEN BREAK
|
||||||
|
IF I==1 THEN CONTINUE
|
||||||
|
?I
|
||||||
|
NEXT
|
||||||
GOSUB @A
|
GOSUB @A
|
||||||
END
|
END
|
||||||
@A
|
@A
|
||||||
|
|||||||
@@ -26,6 +26,10 @@ enum NodeType
|
|||||||
Gosub,
|
Gosub,
|
||||||
Return,
|
Return,
|
||||||
End,
|
End,
|
||||||
|
Break,
|
||||||
|
Continue,
|
||||||
|
DefineVariable,
|
||||||
|
DefineArray,
|
||||||
}
|
}
|
||||||
abstract class Node
|
abstract class Node
|
||||||
{
|
{
|
||||||
@@ -273,4 +277,39 @@ class End : Statement
|
|||||||
this.type = NodeType.End;
|
this.type = NodeType.End;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class Break : Statement
|
||||||
|
{
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
this.type = NodeType.Break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Continue : Statement
|
||||||
|
{
|
||||||
|
this()
|
||||||
|
{
|
||||||
|
this.type = NodeType.Continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class DefineVariable : Statement
|
||||||
|
{
|
||||||
|
wstring name;
|
||||||
|
Expression expression;
|
||||||
|
this(wstring name, Expression expr)
|
||||||
|
{
|
||||||
|
this.type = NodeType.DefineVariable;
|
||||||
|
this.name = name;
|
||||||
|
this.expression = expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class DefineArray : Statement
|
||||||
|
{
|
||||||
|
wstring name;
|
||||||
|
int[] dim;
|
||||||
|
this(wstring name, int[] dim)
|
||||||
|
{
|
||||||
|
this.type = NodeType.DefineArray;
|
||||||
|
this.name = name;
|
||||||
|
this.dim = dim;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -52,6 +52,10 @@ class Lexical
|
|||||||
reserved["GOSUB"] = TokenType.Gosub;
|
reserved["GOSUB"] = TokenType.Gosub;
|
||||||
reserved["RETURN"] = TokenType.Return;
|
reserved["RETURN"] = TokenType.Return;
|
||||||
reserved["END"] = TokenType.End;
|
reserved["END"] = TokenType.End;
|
||||||
|
reserved["BREAK"] = TokenType.Break;
|
||||||
|
reserved["CONTINUE"] = TokenType.Continue;
|
||||||
|
reserved["VAR"] = TokenType.Var;
|
||||||
|
reserved["DIM"] = TokenType.Var;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
line = 1;
|
line = 1;
|
||||||
}
|
}
|
||||||
@@ -521,6 +525,16 @@ class Parser
|
|||||||
case TokenType.End:
|
case TokenType.End:
|
||||||
node = new End();
|
node = new End();
|
||||||
break;
|
break;
|
||||||
|
case TokenType.Break:
|
||||||
|
node = new Break();
|
||||||
|
break;
|
||||||
|
case TokenType.Continue:
|
||||||
|
node = new Continue();
|
||||||
|
break;
|
||||||
|
case TokenType.Var:
|
||||||
|
lex.popFront();
|
||||||
|
node = var();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
syntaxError();
|
syntaxError();
|
||||||
break;
|
break;
|
||||||
@@ -528,6 +542,34 @@ class Parser
|
|||||||
lex.popFront();
|
lex.popFront();
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
Statement var()
|
||||||
|
{
|
||||||
|
Token token = lex.front();
|
||||||
|
if(token.type != TokenType.Iden)
|
||||||
|
{
|
||||||
|
//TODO:VAR("A")の実装
|
||||||
|
syntaxError();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
wstring name = token.value.stringValue;
|
||||||
|
lex.popFront();
|
||||||
|
token = lex.front();
|
||||||
|
Expression expr;
|
||||||
|
//VAR iden=expr
|
||||||
|
if(token.type == TokenType.Equal)
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
expr = expression();
|
||||||
|
}
|
||||||
|
DefineVariable node = new DefineVariable(name, expr);
|
||||||
|
//VARの評価順は順番通り
|
||||||
|
//VAR iden[=expr],
|
||||||
|
if(token.type == TokenType.Comma)
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
}
|
||||||
|
return node;
|
||||||
|
}
|
||||||
For forStatement()
|
For forStatement()
|
||||||
{
|
{
|
||||||
For node;
|
For node;
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ enum TokenType
|
|||||||
Gosub,
|
Gosub,
|
||||||
Return,
|
Return,
|
||||||
End,
|
End,
|
||||||
|
Break,
|
||||||
|
Continue,
|
||||||
|
Var,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ struct Value
|
|||||||
int integerValue;
|
int integerValue;
|
||||||
double doubleValue;
|
double doubleValue;
|
||||||
wstring stringValue;
|
wstring stringValue;
|
||||||
int[] intArray;
|
Array!int intArray;
|
||||||
}
|
}
|
||||||
this(int value)
|
this(int value)
|
||||||
{
|
{
|
||||||
@@ -70,3 +70,47 @@ struct Value
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class Array(T)
|
||||||
|
{
|
||||||
|
T[] array;
|
||||||
|
//最大要素数2^^31
|
||||||
|
//4次元配列
|
||||||
|
int[4] dim;
|
||||||
|
int dimCount;
|
||||||
|
this(int len)
|
||||||
|
{
|
||||||
|
dim[0] = len;
|
||||||
|
dim[1] = 0;
|
||||||
|
dim[2] = 0;
|
||||||
|
dim[3] = 0;
|
||||||
|
array = new T[len];
|
||||||
|
dimCount = 1;
|
||||||
|
}
|
||||||
|
this(int[] dim)
|
||||||
|
{
|
||||||
|
int len = 1;
|
||||||
|
foreach(int i; dim)
|
||||||
|
{
|
||||||
|
len *= i;
|
||||||
|
}
|
||||||
|
array = new T[len];
|
||||||
|
dimCount = dim.length;
|
||||||
|
}
|
||||||
|
T opIndex(int i1)
|
||||||
|
{
|
||||||
|
return array[i1];
|
||||||
|
}
|
||||||
|
T opIndex(int i1, int i2)
|
||||||
|
{
|
||||||
|
return array[i1 * dim[0] + i2];
|
||||||
|
}
|
||||||
|
T opIndex(int i1, int i2, int i3)
|
||||||
|
{
|
||||||
|
return array[i1 * dim[0] * dim[1] + i2 * dim[1] + i3];
|
||||||
|
}
|
||||||
|
T opIndex(int i1, int i2, int i3, int i4)
|
||||||
|
{
|
||||||
|
return array[i1];//array[i1 * dim[0] * dim[1] * dim[2] + i2 * dim[1] + i3];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user