1
0

break,continue実装,var,dim実装中

This commit is contained in:
otya128
2015-06-10 19:09:15 +09:00
parent 2e9e966f0b
commit 7c383dff1a
6 changed files with 180 additions and 14 deletions

View File

@@ -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)
{ {

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;

View File

@@ -47,6 +47,9 @@ enum TokenType
Gosub, Gosub,
Return, Return,
End, End,
Break,
Continue,
Var,
} }
struct Token struct Token

View File

@@ -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];
}
}