ON GOTO,GOSUB実装.
This commit is contained in:
@@ -34,6 +34,51 @@ DEF GOTOTEST
|
|||||||
ASSERT__ 0, "LOCAL LABEL"
|
ASSERT__ 0, "LOCAL LABEL"
|
||||||
@LOCAL
|
@LOCAL
|
||||||
END
|
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_1
|
||||||
DATA "A",1,2,3,4
|
DATA "A",1,2,3,4
|
||||||
LOCATE 10,
|
LOCATE 10,
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ enum CodeType
|
|||||||
GotoTrue,
|
GotoTrue,
|
||||||
GosubS,
|
GosubS,
|
||||||
ReturnSubroutine,
|
ReturnSubroutine,
|
||||||
|
OnS,
|
||||||
}
|
}
|
||||||
abstract class Code
|
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;
|
skip.address = this.code.length;
|
||||||
this.functions[func.name] = func;
|
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)
|
void compileStatement(Statement i, Scope s)
|
||||||
{
|
{
|
||||||
switch(i.type)
|
switch(i.type)
|
||||||
@@ -697,6 +702,9 @@ class Compiler
|
|||||||
s.data.addData(j);
|
s.data.addData(j);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case NodeType.On:
|
||||||
|
compileOn(cast(On)i, s);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
stderr.writeln("Compile:NotImpl ", i.type);
|
stderr.writeln("Compile:NotImpl ", i.type);
|
||||||
}
|
}
|
||||||
@@ -739,6 +747,30 @@ class Compiler
|
|||||||
code[i] = new GosubAddr(globalLabel[label.label]);
|
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);
|
return new VM(code, globalIndex + 1, global, functions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,12 +451,15 @@ class Data : Statement
|
|||||||
}
|
}
|
||||||
class On : Statement
|
class On : Statement
|
||||||
{
|
{
|
||||||
|
Expression condition;
|
||||||
bool isGosub;
|
bool isGosub;
|
||||||
wstring[] labels;
|
wstring[] labels;
|
||||||
this(bool isgosub)
|
this(Expression expr, bool isgosub)
|
||||||
{
|
{
|
||||||
|
this.condition = expr;
|
||||||
this.isGosub = isgosub;
|
this.isGosub = isgosub;
|
||||||
this.labels = new wstring[0];
|
this.labels = new wstring[0];
|
||||||
|
this.type = NodeType.On;
|
||||||
}
|
}
|
||||||
void addLabel(wstring label)
|
void addLabel(wstring label)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ class Lexical
|
|||||||
reserved["DATA"] = TokenType.Data;
|
reserved["DATA"] = TokenType.Data;
|
||||||
reserved["READ"] = TokenType.Read;
|
reserved["READ"] = TokenType.Read;
|
||||||
reserved["RESTORE"] = TokenType.Restore;
|
reserved["RESTORE"] = TokenType.Restore;
|
||||||
|
reserved["ON"] = TokenType.On;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
line = 1;
|
line = 1;
|
||||||
}
|
}
|
||||||
@@ -785,6 +786,9 @@ class Parser
|
|||||||
return incStatement();
|
return incStatement();
|
||||||
case TokenType.Data:
|
case TokenType.Data:
|
||||||
return dataStatement();
|
return dataStatement();
|
||||||
|
case TokenType.On:
|
||||||
|
node = onStatement();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
syntaxError();
|
syntaxError();
|
||||||
break;
|
break;
|
||||||
@@ -792,6 +796,42 @@ class Parser
|
|||||||
lex.popFront();
|
lex.popFront();
|
||||||
return node;
|
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 dataStatement()
|
||||||
{
|
{
|
||||||
Data data = new Data();
|
Data data = new Data();
|
||||||
|
|||||||
@@ -424,7 +424,7 @@ class PetitComputer
|
|||||||
renderConsoleGL();
|
renderConsoleGL();
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
auto renderticks = (SDL_GetTicks() - profile);
|
auto renderticks = (SDL_GetTicks() - profile);
|
||||||
if(!renderprofile) writeln(renderticks);
|
if(renderprofile) writeln(renderticks);
|
||||||
while (SDL_PollEvent(&event))
|
while (SDL_PollEvent(&event))
|
||||||
{
|
{
|
||||||
switch (event.type)
|
switch (event.type)
|
||||||
|
|||||||
Reference in New Issue
Block a user