1
0

Implement SPFUNC

This commit is contained in:
otya128
2016-12-31 11:35:32 +09:00
parent ffa140e0dc
commit 0899286b1f
4 changed files with 98 additions and 6 deletions

View File

@@ -60,7 +60,33 @@ class VMSlot
int backtrace;
}
ExecData execData;
//This value is changed each time slot is used.
size_t unique;
}
enum CallbackType
{
none,
label,
function_,
}
struct Callback
{
CallbackType type;
Function func;
VMSlot slot;
size_t slotUnique;
int label;
bool isCallable()
{
if (type == CallbackType.label)
return slot.unique == slotUnique;
if (type == CallbackType.function_)
return func.isDead;
return false;
}
}
class VM
{
VMSlot[5] slots;
@@ -119,9 +145,9 @@ class VM
{
if (f.isCommon)
{
f.isDead = true;
commonFunctions.remove(f.name);
}
f.isDead = true;
}
auto s = this.slots[slot];
s.hasExecReturnAddress = false;
@@ -148,7 +174,9 @@ class VM
s.globalData = otya.smilebasic.type.Data(gdt, 0);
s.globalLabel = globalLabel;
s.debugInfo = dinfo;
s.unique = unique++;
}
int unique;
Code getCurrent()
{
return currentSlot.code[pc];
@@ -400,9 +428,9 @@ class VM
{
slot = currentSlot;
}
if (label in slot.globalLabel)
if (name.name in slot.globalLabel)
return true;
if (currentFunction && label in currentFunction.label)
if (currentFunction && name.name in currentFunction.label)
return true;
return false;
}
@@ -422,9 +450,9 @@ class VM
{
slot = currentSlot;
}
if (var in slot.globalTable)
if (name.name in slot.globalTable)
return true;
if (currentFunction && var in currentFunction.variable)
if (currentFunction && name.name in currentFunction.variable)
return true;
return false;
}
@@ -432,6 +460,47 @@ class VM
{
return slot >= 0 && slot < slotSize;
}
Callback createCallback(wstring funcOrLabel)
{
Callback result;
result.type = CallbackType.none;
import otya.smilebasic.builtinfunctions;
auto name = parse(funcOrLabel);
VMSlot slot;
if (name.hasSlot)
{
if (!checkSlotNumber(name.slot))
{
return result;
}
slot = slots[name.slot];
}
else
{
slot = currentSlot;
}
result.slot = slot;
result.slotUnique = slot.unique;
Function func;
func = slot.functions.get(name.name, null);
if (func is null)
func = commonFunctions.get(name.name, null);
if (func)
{
result.type = CallbackType.function_;
result.func = func;
return result;
}
//global only
int label = slot.globalLabel.get(name.name, int.min);
if (label == int.min)
{
return result;
}
result.type = CallbackType.label;
result.label = label;
return result;
}
}
enum CodeType
{

View File

@@ -1883,6 +1883,22 @@ class BuiltinFunction
}
return p.sprite.spused(id);
}
static void SPFUNC(PetitComputer p, int id, wstring func)
{
if (!p.sprite.isValidSpriteId(id))
{
throw new OutOfRange("SPFUNC", 1);
}
/*
if (!p.sprite.isSpriteDefined(id))
{
throw new IllegalFunctionCall("SPFUNC", 1);
}*/
auto callback = p.vm.createCallback(func);
if (callback.type == CallbackType.none)
throw new IllegalFunctionCall("SPFUNC"/*, 2*/);
p.sprite.spfunc(id, callback);
}
static void BGMSTOP(PetitComputer p)
{
writeln("NOTIMPL:BGMSTOP");

View File

@@ -98,7 +98,7 @@ class Function
Scope scope_;
bool isCommon;
VMSlot slot;
bool isDead;/*common function*/
bool isDead;
/**
0:bp
1:pc

View File

@@ -1,6 +1,7 @@
module otya.smilebasic.sprite;
import otya.smilebasic.petitcomputer;
import otya.smilebasic.error;
import otya.smilebasic.vm;
import derelict.sdl2.sdl;
import derelict.opengl3.gl;
enum SpriteAttr
@@ -191,6 +192,7 @@ struct SpriteData
double scalex;
double scaley;
double r;
Callback callback;
this(int id)
{
this.id = id;
@@ -1184,4 +1186,9 @@ class Sprite
id = spid(id);
return sprites[id].define;
}
void spfunc(int id, Callback callback)
{
id = spid(id);
sprites[id].callback = callback;
}
}