1
0

Implement CALL SPRITE

This commit is contained in:
otya128
2016-12-31 13:40:44 +09:00
parent 803538d358
commit 4eb6a1fc98
7 changed files with 190 additions and 61 deletions

View File

@@ -85,6 +85,22 @@ struct Callback
return !func.isDead; return !func.isDead;
return false; return false;
} }
void opCall(VM vm)
{
if (!isCallable)
return;
if (type == CallbackType.label)
{
vm.pushBackTrace("");
vm.pushpc;
vm.setCurrentSlot(slot.index);
vm.pc = label - 1;
}
if (type == CallbackType.function_)
{
vm.call(func, 0, 0);
}
}
} }
class VM class VM
@@ -501,6 +517,42 @@ class VM
result.label = label; result.label = label;
return result; return result;
} }
void call(Function func, int argCount, int outArgCount)
{
alias vm = this;
if(func.argCount != argCount)
{
throw new IllegalFunctionCall(func.name.to!string);
}
if(func.outArgCount != outArgCount)
{
throw new IllegalFunctionCall(func.name.to!string);
}
vm.pushBackTrace(func.name);
//TODO:args
auto bp = vm.stacki;
vm.push(Value(vm.currentFunction));
vm.currentFunction = func;
vm.push(Value(vm.currentData));
vm.currentData.index = 0;
vm.currentData.table = func.scope_.data;
vm.push(Value(vm.bp));
vm.pushpc;//vm.push(Value(vm.pc));
vm.bp = bp;
vm.pc = func.address - 1;
vm.stacki += func.variableIndex - 1;
foreach(wstring k, VMVariable v ; func.variable)
{
if(v.index > 0)
{
vm.stack[bp + v.index] = Value(v.type);
}
}
if (func.isCommon)
{
vm.setCurrentSlot(func.slot.index);
}
}
} }
enum CodeType enum CodeType
{ {
@@ -1612,38 +1664,7 @@ class CallFunctionCode : Code
{ {
resolve(vm); resolve(vm);
} }
if(func.argCount != this.argCount) vm.call(func, this.argCount, this.outArgCount);
{
throw new IllegalFunctionCall(name.to!string);
}
if(func.outArgCount != this.outArgCount)
{
throw new IllegalFunctionCall(name.to!string);
}
vm.pushBackTrace(name);
//TODO:args
auto bp = vm.stacki;
vm.push(Value(vm.currentFunction));
vm.currentFunction = func;
vm.push(Value(vm.currentData));
vm.currentData.index = 0;
vm.currentData.table = func.scope_.data;
vm.push(Value(vm.bp));
vm.pushpc;//vm.push(Value(vm.pc));
vm.bp = bp;
vm.pc = func.address - 1;
vm.stacki += func.variableIndex - 1;
foreach(wstring k, VMVariable v ; func.variable)
{
if(v.index > 0)
{
vm.stack[bp + v.index] = Value(v.type);
}
}
if (func.isCommon)
{
vm.setCurrentSlot(func.slot.index);
}
} }
override string toString(VM vm) override string toString(VM vm)
{ {
@@ -1690,34 +1711,7 @@ class CallFunctionS : Code
} }
void callFunc(Function func, VM vm) void callFunc(Function func, VM vm)
{ {
if(func.argCount != this.argCount) vm.call(func, argCount, outArgCount);
{
throw new IllegalFunctionCall(func.name.to!string);
}
if(func.outArgCount != this.outArgCount)
{
throw new IllegalFunctionCall(func.name.to!string);
}
//TODO:args
auto bp = vm.stacki;
vm.push(Value(vm.currentFunction));
vm.currentFunction = func;
vm.push(Value(vm.currentData));
vm.currentData.index = 0;
vm.currentData.table = func.scope_.data;
vm.push(Value(vm.bp));
vm.pushpc;
vm.bp = bp;
vm.pc = func.address - 1;
vm.stacki += func.variableIndex - 1;
foreach(wstring k, VMVariable v ; func.variable)
{
if(v.index > 0)
{
vm.stack[bp + v.index] = Value(v.type);
}
}
vm.setCurrentSlot(func.slot.index);
} }
override void execute(VM vm) override void execute(VM vm)
{ {
@@ -1759,7 +1753,6 @@ class CallFunctionS : Code
callBuintinFunc(bfunc, vm); callBuintinFunc(bfunc, vm);
return; return;
} }
vm.pushBackTrace(name.name);
callFunc(func, vm); callFunc(func, vm);
} }
override string toString(VM vm) override string toString(VM vm)
@@ -2683,3 +2676,70 @@ class ConvertBool : Code
top.type = ValueType.Integer; top.type = ValueType.Integer;
} }
} }
/+
SPFUNC 0,@A
FOR I=1TO 511
SPFUNC I,@B
NEXT
CALL SPRITE
END
@A
?"BEFORE CALL BG",CALLIDX
CALL BG
?"AFTER CALL BG",CALLIDX
RETUERN
@B
?CALLIDX
RETURN
RESULT
BEFORE CALL BG 0
AFTER CALL BG 4
=>SPFUNC 1~511 is not called
+/
class InitCallback : Code
{
override void execute(VM vm)
{
vm.petitcomputer.callidx = -1;
vm.petitcomputer.callback = true;
}
}
class CallSprite : Code
{
override void execute(VM vm)
{
vm.petitcomputer.callidx++;
if (!vm.petitcomputer.callback)
{
return;
}
if (!vm.petitcomputer.sprite.isValidSpriteId(vm.petitcomputer.callidx))
{
vm.petitcomputer.callback = false;
return;
}
auto callback = vm.petitcomputer.sprite.getCallback(vm.petitcomputer.callidx);
vm.pc--;
if (!callback.isCallable)
{
return;
}
callback(vm);
}
}
class CallBG : Code
{
override void execute(VM vm)
{
if (!vm.petitcomputer.callback)
{
vm.petitcomputer.callidx++;
return;
}
vm.petitcomputer.callidx++;
}
}

View File

@@ -227,6 +227,7 @@ class Compiler
addSystemVariable("HARDWARE", new Hardware()); addSystemVariable("HARDWARE", new Hardware());
addSystemVariable("MILLISEC", new MilliSecond()); addSystemVariable("MILLISEC", new MilliSecond());
addSystemVariable("PRGSLOT", new ProgramSlot()); addSystemVariable("PRGSLOT", new ProgramSlot());
addSystemVariable("CALLIDX", new CallIndex());
} }
void addSystemVariable(wstring name, SystemVariable var) void addSystemVariable(wstring name, SystemVariable var)
{ {
@@ -970,6 +971,16 @@ class Compiler
genCode(new otya.smilebasic.vm.Linput); genCode(new otya.smilebasic.vm.Linput);
compilePopVar(linput.expression, sc); compilePopVar(linput.expression, sc);
} }
void compileCallSprite(otya.smilebasic.node.CallSprite call, Scope sc)
{
genCode(new InitCallback);
genCode(new otya.smilebasic.vm.CallSprite);
}
void compileCallBG(otya.smilebasic.node.CallBG call, Scope sc)
{
genCode(new InitCallback);
genCode(new otya.smilebasic.vm.CallBG);
}
void compileStatement(Statement i, Scope s) void compileStatement(Statement i, Scope s)
{ {
switch(i.type) switch(i.type)
@@ -1247,6 +1258,12 @@ class Compiler
case NodeType.Linput: case NodeType.Linput:
compileLinput(cast(otya.smilebasic.node.Linput)i, s); compileLinput(cast(otya.smilebasic.node.Linput)i, s);
break; break;
case NodeType.CallSprite:
compileCallSprite(cast(otya.smilebasic.node.CallSprite)i, s);
break;
case NodeType.CallBG:
compileCallBG(cast(otya.smilebasic.node.CallBG)i, s);
break;
default: default:
stderr.writeln("Compile:NotImpl ", i.type); stderr.writeln("Compile:NotImpl ", i.type);
} }

View File

@@ -51,6 +51,8 @@ enum NodeType
Exec, Exec,
Use, Use,
Linput, Linput,
CallSprite,
CallBG,
} }
abstract class Node abstract class Node
{ {
@@ -697,3 +699,19 @@ class Linput : Statement
this.expression = expr; this.expression = expr;
} }
} }
class CallSprite : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.CallSprite;
}
}
class CallBG : Statement
{
this(SourceLocation loc)
{
super.location = loc;
this.type = NodeType.CallBG;
}
}

View File

@@ -939,6 +939,23 @@ class Parser
} }
} }
lex.popFront(); lex.popFront();
if (token.type == TokenType.Call)
{
if (lex.front.type == TokenType.Iden)
{
auto arg = std.uni.toUpper(lex.front.value.castString);
if (arg == "SPRITE")
{
node = new CallSprite(lex.location);
break;
}
if (arg == "BG")
{
node = new CallBG(lex.location);
break;
}
}
}
//命令呼び出し //命令呼び出し
auto func = new CallFunctionStatement(name, lex.location); auto func = new CallFunctionStatement(name, lex.location);
node = func; node = func;

View File

@@ -1695,6 +1695,9 @@ class PetitComputer
SDL_SetClipboardText(ws.to!string.toStringz); SDL_SetClipboardText(ws.to!string.toStringz);
} }
bool callback;
int callidx = 0;
//プチコン内部表現はRGB5_A1 //プチコン内部表現はRGB5_A1
static uint toGLColor(GLenum format, ubyte r, ubyte g, ubyte b, ubyte a) static uint toGLColor(GLenum format, ubyte r, ubyte g, ubyte b, ubyte a)
{ {

View File

@@ -1191,4 +1191,8 @@ class Sprite
id = spid(id); id = spid(id);
sprites[id].callback = callback; sprites[id].callback = callback;
} }
Callback getCallback(int id)
{
return sprites[spid(id)].callback;
}
} }

View File

@@ -10,6 +10,9 @@ class SystemVariable
@property @property
void value(Value value) void value(Value value)
{ {
//v3.3.2
//TIME$=1,TIME$="1"=>Type mismatch(runtime)
//MAINCNT=1,MAINCNT="1"=>Syntax error(runtime)
throw new TypeMismatch(); throw new TypeMismatch();
} }
} }
@@ -139,3 +142,10 @@ class ProgramSlot : SystemVariable
return Value(vm.petitcomputer.program.currentSlot); return Value(vm.petitcomputer.program.currentSlot);
} }
} }
class CallIndex : SystemVariable
{
@property override Value value()
{
return Value(vm.petitcomputer.callidx);
}
}