1
0

Implement CALL(x:FUNC)

This commit is contained in:
otya128
2016-12-29 15:37:28 +09:00
parent 692c7907e9
commit 5c6ec3e9e0
3 changed files with 84 additions and 16 deletions

View File

@@ -55,6 +55,7 @@ class VMSlot
class VM class VM
{ {
VMSlot[5] slots; VMSlot[5] slots;
int slotSize = 4;
Function[wstring] commonFunctions; Function[wstring] commonFunctions;
int slot; int slot;
VMSlot currentSlot; VMSlot currentSlot;
@@ -132,8 +133,8 @@ class VM
if (f.name in commonFunctions) if (f.name in commonFunctions)
throw new DuplicateFunction(slot, dinfo.getLocationByAddress(f.address)); throw new DuplicateFunction(slot, dinfo.getLocationByAddress(f.address));
commonFunctions[f.name] = f; commonFunctions[f.name] = f;
f.slot = s;
} }
f.slot = s;
} }
s.globalData = otya.smilebasic.type.Data(gdt, 0); s.globalData = otya.smilebasic.type.Data(gdt, 0);
s.globalLabel = globalLabel; s.globalLabel = globalLabel;
@@ -318,14 +319,54 @@ class VM
{ {
return backTraceStack[0..traceI]; return backTraceStack[0..traceI];
} }
struct Name
{
bool hasSlot;
int slot;
wstring name;
}
static Name parse(wstring input)
{
import std.array;
int index = input.indexOf(':');
if (index == -1)
{
return Name(false, -1, input);
}
if (!input[0].isNumber)
{
return Name(false, -1, input);
}
auto slot = .parse!int(input);
if (input[0] != ':')
{
return Name(false, -1, input);
}
input.popFront();
return Name(true, slot, input);
}
bool chkcall(wstring func) bool chkcall(wstring func)
{ {
import otya.smilebasic.builtinfunctions; import otya.smilebasic.builtinfunctions;
if (func in currentSlot.functions) auto name = parse(func);
VMSlot slot;
if (name.hasSlot)
{
if (!checkSlotNumber(name.slot))
{
return false;
}
slot = slots[name.slot];
}
else
{
slot = currentSlot;
}
if (name.name in slot.functions)
return true; return true;
if (func in BuiltinFunction.builtinFunctions) if (name.name in BuiltinFunction.builtinFunctions)
return true; return true;
if (func in commonFunctions) if (name.name in commonFunctions)
return true; return true;
return false; return false;
} }
@@ -345,6 +386,10 @@ class VM
return true; return true;
return false; return false;
} }
bool checkSlotNumber(int slot)
{
return slot >= 0 && slot < slotSize;
}
} }
enum CodeType enum CodeType
{ {
@@ -1538,7 +1583,7 @@ class CallFunctionS : Code
vm.currentData.index = 0; vm.currentData.index = 0;
vm.currentData.table = func.scope_.data; vm.currentData.table = func.scope_.data;
vm.push(Value(vm.bp)); vm.push(Value(vm.bp));
vm.pushpc;//vm.push(Value(vm.pc)); vm.pushpc;
vm.bp = bp; vm.bp = bp;
vm.pc = func.address - 1; vm.pc = func.address - 1;
vm.stacki += func.variableIndex - 1; vm.stacki += func.variableIndex - 1;
@@ -1549,11 +1594,8 @@ class CallFunctionS : Code
vm.stack[bp + v.index] = Value(v.type); vm.stack[bp + v.index] = Value(v.type);
} }
} }
if (func.isCommon)
{
vm.setCurrentSlot(func.slot.index); vm.setCurrentSlot(func.slot.index);
} }
}
override void execute(VM vm) override void execute(VM vm)
{ {
Value vname; Value vname;
@@ -1562,25 +1604,39 @@ class CallFunctionS : Code
{ {
throw new TypeMismatch(); throw new TypeMismatch();
} }
auto name = vname.castDString.toUpper; auto name = VM.parse(vname.castDString.toUpper);
Function func = vm.currentSlot.functions.get(name, null); VMSlot slot;
if (name.hasSlot)
{
if (!vm.checkSlotNumber(name.slot))
throw new UndefinedFunction(name.name);
slot = vm.slots[name.slot];
}
else
{
slot = vm.currentSlot;
}
Function func = slot.functions.get(name.name, null);
//CHKCALL("0:CHR$")=>TRUE
//CHKCALL("0:COMMONDEF")=>TRUE
//CHKCALL("1:COMMONDEF")=>TRUE
if (!func) if (!func)
{ {
func = vm.commonFunctions.get(name, null); func = vm.commonFunctions.get(name.name, null);
} }
if(!func) if(!func)
{ {
auto bfuncs = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(name, null); auto bfuncs = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(name.name, null);
if (!bfuncs) if (!bfuncs)
{ {
throw new SyntaxError(name); throw new UndefinedFunction(name.name);
} }
auto bfunc = bfuncs.overloadResolution(argCount, outArgCount); auto bfunc = bfuncs.overloadResolution(argCount, outArgCount);
callBuintinFunc(bfunc, vm); callBuintinFunc(bfunc, vm);
return; return;
} }
vm.pushBackTrace(name); vm.pushBackTrace(name.name);
callFunc(func, vm); callFunc(func, vm);
} }
override string toString(VM vm) override string toString(VM vm)

View File

@@ -97,7 +97,7 @@ class Function
int outArgCount; int outArgCount;
Scope scope_; Scope scope_;
bool isCommon; bool isCommon;
VMSlot slot;/*common function*/ VMSlot slot;
bool isDead;/*common function*/ bool isDead;/*common function*/
/** /**
0:bp 0:bp

View File

@@ -149,6 +149,18 @@ class UndefinedVariable : SmileBasicError
super("Undefined variable"); super("Undefined variable");
} }
} }
class UndefinedFunction : SmileBasicError
{
this()
{
this.errnum = 16;
super("Undefined function");
}
this(wstring name)
{
this();
}
}
class DuplicateVariable : SmileBasicError class DuplicateVariable : SmileBasicError
{ {
this() this()