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
{
VMSlot[5] slots;
int slotSize = 4;
Function[wstring] commonFunctions;
int slot;
VMSlot currentSlot;
@@ -132,8 +133,8 @@ class VM
if (f.name in commonFunctions)
throw new DuplicateFunction(slot, dinfo.getLocationByAddress(f.address));
commonFunctions[f.name] = f;
f.slot = s;
}
f.slot = s;
}
s.globalData = otya.smilebasic.type.Data(gdt, 0);
s.globalLabel = globalLabel;
@@ -318,14 +319,54 @@ class VM
{
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)
{
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;
if (func in BuiltinFunction.builtinFunctions)
if (name.name in BuiltinFunction.builtinFunctions)
return true;
if (func in commonFunctions)
if (name.name in commonFunctions)
return true;
return false;
}
@@ -345,6 +386,10 @@ class VM
return true;
return false;
}
bool checkSlotNumber(int slot)
{
return slot >= 0 && slot < slotSize;
}
}
enum CodeType
{
@@ -1538,7 +1583,7 @@ class CallFunctionS : Code
vm.currentData.index = 0;
vm.currentData.table = func.scope_.data;
vm.push(Value(vm.bp));
vm.pushpc;//vm.push(Value(vm.pc));
vm.pushpc;
vm.bp = bp;
vm.pc = func.address - 1;
vm.stacki += func.variableIndex - 1;
@@ -1549,10 +1594,7 @@ class CallFunctionS : Code
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)
{
@@ -1562,25 +1604,39 @@ class CallFunctionS : Code
{
throw new TypeMismatch();
}
auto name = vname.castDString.toUpper;
Function func = vm.currentSlot.functions.get(name, null);
auto name = VM.parse(vname.castDString.toUpper);
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)
{
func = vm.commonFunctions.get(name, null);
func = vm.commonFunctions.get(name.name, null);
}
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)
{
throw new SyntaxError(name);
throw new UndefinedFunction(name.name);
}
auto bfunc = bfuncs.overloadResolution(argCount, outArgCount);
callBuintinFunc(bfunc, vm);
return;
}
vm.pushBackTrace(name);
vm.pushBackTrace(name.name);
callFunc(func, vm);
}
override string toString(VM vm)

View File

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

View File

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