CALLを実装
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
TABSTEP=4
|
||||
FOR i=0 TO 20
|
||||
?"A","B",
|
||||
NEXT
|
||||
SPSET 0,1206
|
||||
SPANIM 0,"I",-90,1209,0
|
||||
WHILE 1
|
||||
WEND
|
||||
DEF CALLTEST(V)
|
||||
RETURN V
|
||||
END
|
||||
CALL "SPDEF",1192 OUT A,B
|
||||
|
||||
ASSERT__ A==464, "CALLTEST"
|
||||
ASSERT__ B==384, "CALLTEST"
|
||||
ASSERT__ CALL("CALLTEST", TRUE), "CALLTEST"
|
||||
DEF TESST X,A$
|
||||
IF Y<0 THEN Y=28
|
||||
IF X<0 THEN X=20-(LEN(A$)/2)
|
||||
|
||||
108
SMILEBASIC/VM.d
108
SMILEBASIC/VM.d
@@ -1124,6 +1124,114 @@ class CallFunctionCode : Code
|
||||
return "callfunc " ~ name.to!string;
|
||||
}
|
||||
}
|
||||
class CallFunctionS : Code
|
||||
{
|
||||
int argCount;
|
||||
int outArgCount;
|
||||
this(int argCount, int outArgCount)
|
||||
{
|
||||
this.argCount = argCount;
|
||||
this.outArgCount = outArgCount;
|
||||
}
|
||||
void callBuintinFunc(BuiltinFunction func, VM vm)
|
||||
{
|
||||
Value[] arg;
|
||||
Value[] oldresult;
|
||||
Value[] result;
|
||||
arg = vm.stack[vm.stacki - argCount..vm.stacki];
|
||||
result = vm.stack[vm.stacki/* - argcount */+ 1..vm.stacki + 1/* - argcount */+ outArgCount];//雑;
|
||||
oldresult = result;
|
||||
if (argCount != func.argments.length && func.hasSkipArgument)
|
||||
{
|
||||
auto newarg = new Value[func.argments.length];
|
||||
newarg[$ - argCount .. $] = arg[0..$];
|
||||
arg = newarg;
|
||||
}
|
||||
if (outArgCount != func.results.length)
|
||||
{
|
||||
auto newarg = new Value[func.results.length];
|
||||
newarg[$ - outArgCount .. $] = result[0..$];
|
||||
result = newarg;
|
||||
}
|
||||
func.func(vm.petitcomputer, arg, result);
|
||||
if(func.variadic)
|
||||
{
|
||||
vm.stacki -= argCount;
|
||||
}
|
||||
else
|
||||
{
|
||||
vm.stacki -= func.argments.length;// - outcount;
|
||||
}
|
||||
////vm.stacki += outcount;
|
||||
//vm.stacki = old;
|
||||
for(int i = 0; i < outArgCount; i++)
|
||||
{
|
||||
vm.push(result[i]);
|
||||
}
|
||||
}
|
||||
void callFunc(Function func, VM vm)
|
||||
{
|
||||
if(func.argCount != this.argCount)
|
||||
{
|
||||
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.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
Value vname;
|
||||
vm.pop(vname);
|
||||
if (!vname.isString)
|
||||
{
|
||||
throw new TypeMismatch();
|
||||
}
|
||||
auto name = vname.castString;
|
||||
Function func = vm.currentSlot.functions.get(name, null);
|
||||
if(!func)
|
||||
{
|
||||
auto bfuncs = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(name, null);
|
||||
if (!bfuncs)
|
||||
{
|
||||
throw new SyntaxError(name);
|
||||
}
|
||||
|
||||
auto bfunc = bfuncs.overloadResolution(argCount, outArgCount);
|
||||
/* if(bfunc.argments.length >= argCount)
|
||||
{
|
||||
auto k = bfunc.argments.length - argCount;
|
||||
foreach(l;0..k)
|
||||
{
|
||||
vm.push(Value(ValueType.Void));
|
||||
}
|
||||
}*/
|
||||
callBuintinFunc(bfunc, vm);
|
||||
return;
|
||||
}
|
||||
callFunc(func, vm);
|
||||
}
|
||||
override string toString(VM vm)
|
||||
{
|
||||
return "callfuncS " ~ argCount.to!string ~ "," ~ outArgCount.to!string;
|
||||
}
|
||||
}
|
||||
import otya.smilebasic.builtinfunctions;
|
||||
class CallBuiltinFunction : Code
|
||||
{
|
||||
|
||||
@@ -496,9 +496,16 @@ class Compiler
|
||||
{
|
||||
genCode(new CallBuiltinFunction(bfun, cast(int)func.args.length, 1));
|
||||
}
|
||||
else if (func.name == "CALL")
|
||||
{
|
||||
if (func.args.length < 1)
|
||||
{
|
||||
throw new SyntaxError();
|
||||
}
|
||||
genCode(new CallFunctionS((cast(int)func.args.length) - 1, 1));
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln(func.name);
|
||||
genCode(new CallFunctionCode(func.name, cast(int)func.args.length));
|
||||
}
|
||||
}
|
||||
@@ -911,9 +918,12 @@ class Compiler
|
||||
{
|
||||
genCode(new CallBuiltinFunction(bfun, cast(int)func.args.length, cast(int)bfun.results.length));//func.outVariable.length));
|
||||
}
|
||||
else if (func.name == "CALL")
|
||||
{
|
||||
genCode(new CallFunctionS((cast(int)func.args.length) - 1, cast(int)func.outVariable.length));
|
||||
}
|
||||
else
|
||||
{
|
||||
writeln(func.name);
|
||||
genCode(new CallFunctionCode(func.name, cast(int)func.args.length, cast(int)func.outVariable.length));
|
||||
}
|
||||
if(bfun)
|
||||
|
||||
@@ -74,6 +74,7 @@ class Lexical
|
||||
reserved["INPUT"] = TokenType.Input;
|
||||
reserved["TRUE"] = TokenType.True;
|
||||
reserved["FALSE"] = TokenType.False;
|
||||
reserved["CALL"] = TokenType.Call;
|
||||
reserved.rehash();
|
||||
}
|
||||
this(wstring input)
|
||||
@@ -184,7 +185,7 @@ class Lexical
|
||||
}
|
||||
if(r != TokenType.Unknown)
|
||||
{
|
||||
token = Token(r);
|
||||
token = Token(r, Value(iden));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1522,6 +1523,7 @@ class Parser
|
||||
version(none)stdout.flush();
|
||||
node = new Constant(token.value, lex.location);
|
||||
break;
|
||||
case TokenType.Call:
|
||||
case TokenType.Iden:
|
||||
if(!lex.empty())
|
||||
lex.popFront();
|
||||
|
||||
@@ -1175,7 +1175,7 @@ class PetitComputer
|
||||
//デバッグ用
|
||||
version(NDirectMode)
|
||||
{
|
||||
slot[0].load(readText("./SYS/EX8TECDEMO.TXT").to!wstring);
|
||||
slot[0].load(readText("./TEST.TXT").to!wstring);
|
||||
version(none)
|
||||
parser = new Parser(
|
||||
//readText("./SYS/GAME6TALK.TXT").to!wstring
|
||||
|
||||
Reference in New Issue
Block a user