From e9c94f5bbd4e5fa270f7a89bec04092211704aca Mon Sep 17 00:00:00 2001 From: otya128 Date: Wed, 31 Aug 2016 16:46:11 +0900 Subject: [PATCH] =?UTF-8?q?CALL=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/TEST.txt | 16 +++--- SMILEBASIC/VM.d | 108 +++++++++++++++++++++++++++++++++++++ SMILEBASIC/compiler.d | 14 ++++- SMILEBASIC/parser.d | 4 +- SMILEBASIC/petitcomputer.d | 2 +- 5 files changed, 132 insertions(+), 12 deletions(-) diff --git a/SMILEBASIC/TEST.txt b/SMILEBASIC/TEST.txt index 088081d..29ff2f1 100644 --- a/SMILEBASIC/TEST.txt +++ b/SMILEBASIC/TEST.txt @@ -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) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index c49af27..645f80d 100644 --- a/SMILEBASIC/VM.d +++ b/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 { diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 0e5ff66..f3d3c66 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -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) diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index f75dbe1..fb2df03 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -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(); diff --git a/SMILEBASIC/petitcomputer.d b/SMILEBASIC/petitcomputer.d index 9481959..bcfdf7e 100644 --- a/SMILEBASIC/petitcomputer.d +++ b/SMILEBASIC/petitcomputer.d @@ -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