ON GOTO,GOSUB実装.
This commit is contained in:
@@ -34,6 +34,51 @@ DEF GOTOTEST
|
||||
ASSERT__ 0, "LOCAL LABEL"
|
||||
@LOCAL
|
||||
END
|
||||
|
||||
ON 1 GOTO @0,@1,@2,@3
|
||||
@0
|
||||
ASSERT__ 0, "ON GOTO"
|
||||
@2
|
||||
ASSERT__ 0, "ON GOTO"
|
||||
@3
|
||||
ASSERT__ 0, "ON GOTO"
|
||||
@1
|
||||
ONGOTOTEST
|
||||
DEF ONGOTOTEST
|
||||
ON 1 GOTO @0,@1,@2,@3
|
||||
@0
|
||||
ASSERT__ 0, "LOCAL ON GOTO"
|
||||
@2
|
||||
ASSERT__ 0, "LOCAL ON GOTO"
|
||||
@3
|
||||
ASSERT__ 0, "LOCAL ON GOTO"
|
||||
@1
|
||||
END
|
||||
ON 1 GOSUB @ONGOSUB0,@ONGOSUB1,@ONGOSUB2,@ONGOSUB3
|
||||
GOTO@ONGOSUB4
|
||||
@ONGOSUB0
|
||||
ASSERT__ 0, "ON GOSUB"
|
||||
@ONGOSUB2
|
||||
ASSERT__ 0, "ON GOSUB"
|
||||
@ONGOSUB3
|
||||
ASSERT__ 0, "ON GOSUB"
|
||||
@ONGOSUB1
|
||||
RETURN
|
||||
@ONGOSUB4
|
||||
ONGOSUBTEST
|
||||
DEF ONGOSUBTEST
|
||||
ON 1 GOTO @0,@1,@2,@3
|
||||
GOTO@4
|
||||
@0
|
||||
ASSERT__ 0, "ON ONGOSUB"
|
||||
@2
|
||||
ASSERT__ 0, "ON ONGOSUB"
|
||||
@3
|
||||
ASSERT__ 0, "ON ONGOSUB"
|
||||
@1
|
||||
RETURN
|
||||
@4
|
||||
END
|
||||
@DATA_1
|
||||
DATA "A",1,2,3,4
|
||||
LOCATE 10,
|
||||
|
||||
@@ -120,6 +120,7 @@ enum CodeType
|
||||
GotoTrue,
|
||||
GosubS,
|
||||
ReturnSubroutine,
|
||||
OnS,
|
||||
}
|
||||
abstract class Code
|
||||
{
|
||||
@@ -968,3 +969,70 @@ class IncCodeL : Code
|
||||
}
|
||||
}
|
||||
}
|
||||
class OnBase : Code
|
||||
{
|
||||
int[] labels;
|
||||
this(int[] labels)
|
||||
{
|
||||
this.labels = labels;
|
||||
}
|
||||
int on(VM vm)
|
||||
{
|
||||
Value value;
|
||||
vm.pop(value);
|
||||
if(!value.isNumber())
|
||||
{
|
||||
throw new TypeMismatch();
|
||||
}
|
||||
int index = value.castInteger();
|
||||
if(index < 0 || index >= labels.length)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return labels[index];
|
||||
}
|
||||
}
|
||||
class OnS : Code
|
||||
{
|
||||
wstring[] labels;
|
||||
bool isGosub;
|
||||
Scope sc;
|
||||
this(wstring[] labels, bool isGosub, Scope sc)
|
||||
{
|
||||
this.labels = labels;
|
||||
this.isGosub = isGosub;
|
||||
this.sc = sc;
|
||||
this.type = CodeType.OnS;
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
stderr.writeln("can't execute (compiler bug?)");
|
||||
}
|
||||
}
|
||||
class OnGoto : OnBase
|
||||
{
|
||||
this(int[] labels)
|
||||
{
|
||||
super(labels);
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
int index = on(vm);
|
||||
if(index < 0) return;
|
||||
vm.pc = index - 1;
|
||||
}
|
||||
}
|
||||
class OnGosub : OnBase
|
||||
{
|
||||
this(int[] labels)
|
||||
{
|
||||
super(labels);
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
int index = on(vm);
|
||||
if(index < 0) return;
|
||||
vm.push(Value(vm.pc));
|
||||
vm.pc = index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,6 +534,11 @@ class Compiler
|
||||
skip.address = this.code.length;
|
||||
this.functions[func.name] = func;
|
||||
}
|
||||
void compileOn(On on, Scope sc)
|
||||
{
|
||||
compileExpression(on.condition, sc);
|
||||
genCode(new OnS(on.labels, on.isGosub, sc));
|
||||
}
|
||||
void compileStatement(Statement i, Scope s)
|
||||
{
|
||||
switch(i.type)
|
||||
@@ -697,6 +702,9 @@ class Compiler
|
||||
s.data.addData(j);
|
||||
}
|
||||
break;
|
||||
case NodeType.On:
|
||||
compileOn(cast(On)i, s);
|
||||
break;
|
||||
default:
|
||||
stderr.writeln("Compile:NotImpl ", i.type);
|
||||
}
|
||||
@@ -739,6 +747,30 @@ class Compiler
|
||||
code[i] = new GosubAddr(globalLabel[label.label]);
|
||||
}
|
||||
}
|
||||
if(c.type == CodeType.OnS)
|
||||
{
|
||||
auto label = cast(OnS)c;
|
||||
int[] addresses = new int[label.labels.length];
|
||||
foreach(int index, wstring l; label.labels)
|
||||
{
|
||||
if(label.sc.func)
|
||||
{
|
||||
addresses[index] =label.sc.func.label[l];
|
||||
}
|
||||
else
|
||||
{
|
||||
addresses[index] = globalLabel[l];
|
||||
}
|
||||
}
|
||||
if(label.isGosub)
|
||||
{
|
||||
code[i] = new OnGosub(addresses);
|
||||
}
|
||||
else
|
||||
{
|
||||
code[i] = new OnGoto(addresses);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new VM(code, globalIndex + 1, global, functions);
|
||||
}
|
||||
|
||||
@@ -451,12 +451,15 @@ class Data : Statement
|
||||
}
|
||||
class On : Statement
|
||||
{
|
||||
Expression condition;
|
||||
bool isGosub;
|
||||
wstring[] labels;
|
||||
this(bool isgosub)
|
||||
this(Expression expr, bool isgosub)
|
||||
{
|
||||
this.condition = expr;
|
||||
this.isGosub = isgosub;
|
||||
this.labels = new wstring[0];
|
||||
this.type = NodeType.On;
|
||||
}
|
||||
void addLabel(wstring label)
|
||||
{
|
||||
|
||||
@@ -67,6 +67,7 @@ class Lexical
|
||||
reserved["DATA"] = TokenType.Data;
|
||||
reserved["READ"] = TokenType.Read;
|
||||
reserved["RESTORE"] = TokenType.Restore;
|
||||
reserved["ON"] = TokenType.On;
|
||||
reserved.rehash();
|
||||
line = 1;
|
||||
}
|
||||
@@ -785,6 +786,9 @@ class Parser
|
||||
return incStatement();
|
||||
case TokenType.Data:
|
||||
return dataStatement();
|
||||
case TokenType.On:
|
||||
node = onStatement();
|
||||
break;
|
||||
default:
|
||||
syntaxError();
|
||||
break;
|
||||
@@ -792,6 +796,42 @@ class Parser
|
||||
lex.popFront();
|
||||
return node;
|
||||
}
|
||||
On onStatement()
|
||||
{
|
||||
lex.popFront();
|
||||
auto cond = expression();
|
||||
if(!cond) return null;
|
||||
auto token = lex.front();
|
||||
On on;
|
||||
if(token.type == TokenType.Gosub)
|
||||
{
|
||||
on = new On(cond, true);//gosub
|
||||
}
|
||||
else if(token.type == TokenType.Goto)
|
||||
{
|
||||
on = new On(cond, false);//gosub
|
||||
}
|
||||
else
|
||||
{
|
||||
//GOTO/GOSUBいる
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
do
|
||||
{
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
if(token.type != TokenType.Label)
|
||||
{
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
on.addLabel(token.value.stringValue);
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
} while(token.type == TokenType.Comma);
|
||||
return on;
|
||||
}
|
||||
Data dataStatement()
|
||||
{
|
||||
Data data = new Data();
|
||||
|
||||
@@ -424,7 +424,7 @@ class PetitComputer
|
||||
renderConsoleGL();
|
||||
SDL_GL_SwapWindow(window);
|
||||
auto renderticks = (SDL_GetTicks() - profile);
|
||||
if(!renderprofile) writeln(renderticks);
|
||||
if(renderprofile) writeln(renderticks);
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
|
||||
Reference in New Issue
Block a user