GOSUB実�
This commit is contained in:
@@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
node = new Goto(token.value.stringValue);
|
if(token.type == TokenType.Label)
|
||||||
|
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の実装
|
||||||
|
|||||||
@@ -44,6 +44,9 @@ enum TokenType
|
|||||||
LogicalAnd,//&&
|
LogicalAnd,//&&
|
||||||
LogicalOr,//||
|
LogicalOr,//||
|
||||||
IntDiv,//DIV
|
IntDiv,//DIV
|
||||||
|
Gosub,
|
||||||
|
Return,
|
||||||
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user