CALLを実装
This commit is contained in:
@@ -1,11 +1,11 @@
|
|||||||
TABSTEP=4
|
DEF CALLTEST(V)
|
||||||
FOR i=0 TO 20
|
RETURN V
|
||||||
?"A","B",
|
END
|
||||||
NEXT
|
CALL "SPDEF",1192 OUT A,B
|
||||||
SPSET 0,1206
|
|
||||||
SPANIM 0,"I",-90,1209,0
|
ASSERT__ A==464, "CALLTEST"
|
||||||
WHILE 1
|
ASSERT__ B==384, "CALLTEST"
|
||||||
WEND
|
ASSERT__ CALL("CALLTEST", TRUE), "CALLTEST"
|
||||||
DEF TESST X,A$
|
DEF TESST X,A$
|
||||||
IF Y<0 THEN Y=28
|
IF Y<0 THEN Y=28
|
||||||
IF X<0 THEN X=20-(LEN(A$)/2)
|
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;
|
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;
|
import otya.smilebasic.builtinfunctions;
|
||||||
class CallBuiltinFunction : Code
|
class CallBuiltinFunction : Code
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -496,9 +496,16 @@ class Compiler
|
|||||||
{
|
{
|
||||||
genCode(new CallBuiltinFunction(bfun, cast(int)func.args.length, 1));
|
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
|
else
|
||||||
{
|
{
|
||||||
writeln(func.name);
|
|
||||||
genCode(new CallFunctionCode(func.name, cast(int)func.args.length));
|
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));
|
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
|
else
|
||||||
{
|
{
|
||||||
writeln(func.name);
|
|
||||||
genCode(new CallFunctionCode(func.name, cast(int)func.args.length, cast(int)func.outVariable.length));
|
genCode(new CallFunctionCode(func.name, cast(int)func.args.length, cast(int)func.outVariable.length));
|
||||||
}
|
}
|
||||||
if(bfun)
|
if(bfun)
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ class Lexical
|
|||||||
reserved["INPUT"] = TokenType.Input;
|
reserved["INPUT"] = TokenType.Input;
|
||||||
reserved["TRUE"] = TokenType.True;
|
reserved["TRUE"] = TokenType.True;
|
||||||
reserved["FALSE"] = TokenType.False;
|
reserved["FALSE"] = TokenType.False;
|
||||||
|
reserved["CALL"] = TokenType.Call;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
}
|
}
|
||||||
this(wstring input)
|
this(wstring input)
|
||||||
@@ -184,7 +185,7 @@ class Lexical
|
|||||||
}
|
}
|
||||||
if(r != TokenType.Unknown)
|
if(r != TokenType.Unknown)
|
||||||
{
|
{
|
||||||
token = Token(r);
|
token = Token(r, Value(iden));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1522,6 +1523,7 @@ class Parser
|
|||||||
version(none)stdout.flush();
|
version(none)stdout.flush();
|
||||||
node = new Constant(token.value, lex.location);
|
node = new Constant(token.value, lex.location);
|
||||||
break;
|
break;
|
||||||
|
case TokenType.Call:
|
||||||
case TokenType.Iden:
|
case TokenType.Iden:
|
||||||
if(!lex.empty())
|
if(!lex.empty())
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
|
|||||||
@@ -1175,7 +1175,7 @@ class PetitComputer
|
|||||||
//デバッグ用
|
//デバッグ用
|
||||||
version(NDirectMode)
|
version(NDirectMode)
|
||||||
{
|
{
|
||||||
slot[0].load(readText("./SYS/EX8TECDEMO.TXT").to!wstring);
|
slot[0].load(readText("./TEST.TXT").to!wstring);
|
||||||
version(none)
|
version(none)
|
||||||
parser = new Parser(
|
parser = new Parser(
|
||||||
//readText("./SYS/GAME6TALK.TXT").to!wstring
|
//readText("./SYS/GAME6TALK.TXT").to!wstring
|
||||||
|
|||||||
Reference in New Issue
Block a user