From 0899286b1f7fcbc3d745e2b221334699174b8529 Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 31 Dec 2016 11:35:32 +0900 Subject: [PATCH] Implement SPFUNC --- SMILEBASIC/VM.d | 79 ++++++++++++++++++++++++++++++++--- SMILEBASIC/builtinfunctions.d | 16 +++++++ SMILEBASIC/compiler.d | 2 +- SMILEBASIC/sprite.d | 7 ++++ 4 files changed, 98 insertions(+), 6 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 84184f4..9c40505 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -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 { diff --git a/SMILEBASIC/builtinfunctions.d b/SMILEBASIC/builtinfunctions.d index c1839ee..d000632 100644 --- a/SMILEBASIC/builtinfunctions.d +++ b/SMILEBASIC/builtinfunctions.d @@ -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"); diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 0c9cd88..d6ac11a 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -98,7 +98,7 @@ class Function Scope scope_; bool isCommon; VMSlot slot; - bool isDead;/*common function*/ + bool isDead; /** 0:bp 1:pc diff --git a/SMILEBASIC/sprite.d b/SMILEBASIC/sprite.d index a3fb5ac..629cf4d 100644 --- a/SMILEBASIC/sprite.d +++ b/SMILEBASIC/sprite.d @@ -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; + } }