1
0

GOSUB実�

This commit is contained in:
otya128
2015-06-07 20:56:34 +09:00
parent 628b259caf
commit f7c4f06eae
6 changed files with 157 additions and 6 deletions

View File

@@ -32,7 +32,7 @@ class VM
this(Code[] code, int len, int[wstring] globalTable) this(Code[] code, int len, int[wstring] globalTable)
{ {
this.code = code; this.code = code;
this.stack = new Value[1024 * 1024]; 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, int v ; globalTable)
@@ -68,6 +68,10 @@ class VM
{ {
return global[globalTable[name]]; return global[globalTable[name]];
} }
void end()
{
pc = code.length;
}
} }
enum CodeType enum CodeType
{ {
@@ -82,6 +86,8 @@ enum CodeType
GotoS, GotoS,
GotoFalse, GotoFalse,
GotoTrue, GotoTrue,
GosubS,
ReturnSubroutine,
} }
abstract class Code abstract class Code
{ {
@@ -420,7 +426,60 @@ class GotoFalse : Code
vm.pc = address - 1; vm.pc = address - 1;
} }
} }
class Gosub : Code class GosubAddr : Code
{ {
int address;
this(int addr)
{
this.type = CodeType.Gosub;
address = addr;
} }
override void execute(VM vm)
{
vm.push(Value(vm.pc));
vm.pc = address - 1;
}
}
class GosubS : Code
{
wstring label;
this(wstring label)
{
this.type = CodeType.GosubS;
this.label = label;
}
override void execute(VM vm)
{
stderr.writeln("can't execute");
}
}
class ReturnSubroutine : Code
{
this()
{
this.type = CodeType.ReturnSubroutine;
}
override void execute(VM vm)
{
Value pc;
vm.pop(pc);
if(pc.type != ValueType.Integer || pc.integerValue < 0 || pc.integerValue >= vm.code.length)
{
stderr.writeln("Internal error:Compiler bug?");
readln();
return;
}
vm.pc = pc.integerValue;
}
}
class EndVM : Code
{
this()
{
}
override void execute(VM vm)
{
vm.end();
}
}

View File

@@ -42,6 +42,10 @@ class Compiler
{ {
code ~= new GotoS(label); code ~= new GotoS(label);
} }
void genCodeGosub(wstring label)
{
code ~= new GosubS(label);
}
GotoAddr genCodeGoto() GotoAddr genCodeGoto()
{ {
auto c = new GotoAddr(-1); auto c = new GotoAddr(-1);
@@ -258,6 +262,26 @@ class Compiler
case NodeType.For: case NodeType.For:
compileFor(cast(For)i); compileFor(cast(For)i);
break; break;
case NodeType.Gosub:
{
auto gosub = cast(Gosub)i;
genCodeGosub(gosub.label);
}
break;
case NodeType.Return:
{
auto ret = cast(Return)i;
if(ret.expression is null)
genCode(new ReturnSubroutine());
else
{
//関数未実装:error
}
}
break;
case NodeType.End:
genCode(new EndVM());
break;
default: default:
stderr.writeln("Compile:NotImpl ", i.type); stderr.writeln("Compile:NotImpl ", i.type);
} }
@@ -274,6 +298,10 @@ class Compiler
{ {
code[i] = new GotoAddr(globalLabel[(cast(GotoS)c).label]); code[i] = new GotoAddr(globalLabel[(cast(GotoS)c).label]);
} }
if(c.type == CodeType.GosubS)
{
code[i] = new GosubAddr(globalLabel[(cast(GosubS)c).label]);
}
} }
return new VM(code, globalIndex + 1, global); return new VM(code, globalIndex + 1, global);
} }

View File

@@ -44,7 +44,12 @@ FOR I=0 TO 100
ENDIF ENDIF
ENDIF ENDIF
NEXT NEXT
?NOT 1,!!\"a\" ?@HELLOWORLD
GOSUB @A
END
@A
?\"SUBROUTINE TEST\"
RETURN
"); ");
version(none) auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring); version(none) auto parser = new Parser(readText("FIZZBUZZ.TXT").to!wstring);
auto vm = parser.compile(); auto vm = parser.compile();

View File

@@ -23,6 +23,9 @@ enum NodeType
Goto, Goto,
If, If,
For, For,
Gosub,
Return,
End,
} }
abstract class Node abstract class Node
{ {
@@ -245,3 +248,29 @@ class For : Statement
this.statements = statements; this.statements = statements;
} }
} }
class Gosub : Statement
{
wstring label;
this(wstring name)
{
this.type = NodeType.Gosub;
this.label = name;
}
}
class Return : Statement
{
Expression expression;
this(Expression expression)
{
this.type = NodeType.Return;
this.expression = expression;
}
}
class End : Statement
{
this()
{
this.type = NodeType.End;
}
}

View File

@@ -49,6 +49,9 @@ class Lexical
reserved["FOR"] = TokenType.For; reserved["FOR"] = TokenType.For;
reserved["NEXT"] = TokenType.Next; reserved["NEXT"] = TokenType.Next;
reserved["MOD"] = TokenType.Mod; reserved["MOD"] = TokenType.Mod;
reserved["GOSUB"] = TokenType.Gosub;
reserved["RETURN"] = TokenType.Return;
reserved["END"] = TokenType.End;
reserved.rehash(); reserved.rehash();
line = 1; line = 1;
} }
@@ -472,7 +475,24 @@ class Parser
case TokenType.Goto: case TokenType.Goto:
lex.popFront(); lex.popFront();
token = lex.front(); token = lex.front();
if(token.type == TokenType.Label)
node = new Goto(token.value.stringValue); node = new Goto(token.value.stringValue);
else
{
writeln("NotImpl");
syntaxError();
}
break;
case TokenType.Gosub:
lex.popFront();
token = lex.front();
if(token.type == TokenType.Label)
node = new Gosub(token.value.stringValue);
else
{
writeln("NotImpl");
syntaxError();
}
break; break;
case TokenType.If: case TokenType.If:
node = if_(); node = if_();
@@ -480,6 +500,13 @@ class Parser
case TokenType.For: case TokenType.For:
node = forStatement(); node = forStatement();
break; break;
case TokenType.Return:
lex.popFront();
node = new Return(expression());
return node;
case TokenType.End:
node = new End();
break;
default: default:
syntaxError(); syntaxError();
break; break;
@@ -741,7 +768,7 @@ class Parser
break; break;
case TokenType.Label://3.1 case TokenType.Label://3.1
//文字列リテラル //文字列リテラル
node = new Constant(token.value);
break; break;
case TokenType.Minus: case TokenType.Minus:
//TODO:UnaryOperatorの実装 //TODO:UnaryOperatorの実装

View File

@@ -44,6 +44,9 @@ enum TokenType
LogicalAnd,//&& LogicalAnd,//&&
LogicalOr,//|| LogicalOr,//||
IntDiv,//DIV IntDiv,//DIV
Gosub,
Return,
End,
} }
struct Token struct Token