1
0

ON GOTO,GOSUB実装.

This commit is contained in:
otya128
2015-08-19 00:11:19 +09:00
parent edbbcf3250
commit b259ee9d27
6 changed files with 190 additions and 2 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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