From d05166a3b9b2a0bb98010ad332f49f642d16a46f Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 29 Aug 2015 13:38:03 +0900 Subject: [PATCH] =?UTF-8?q?GOTO=20expr,GOSUB=20expr=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/VM.d | 48 ++++++++++++++++++++++++++++++++++++++++++- SMILEBASIC/compiler.d | 23 ++++++++++++++++++--- SMILEBASIC/node.d | 12 +++++++++++ SMILEBASIC/parser.d | 12 +++++++---- SMILEBASIC/sprite.d | 2 -- 5 files changed, 87 insertions(+), 10 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 0bbf836..877e26f 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -40,9 +40,11 @@ class VM Value[] global; VMVariable[wstring] globalTable; Function[wstring] functions; + int[wstring] globalLabel; int bp; PetitComputer petitcomputer; - this(Code[] code, int len, VMVariable[wstring] globalTable, Function[wstring] functions, DataTable gdt/*GNU Debugging Tools*/) + this(Code[] code, int len, VMVariable[wstring] globalTable, Function[wstring] functions, DataTable gdt/*GNU Debugging Tools*/, + int[wstring] globalLabel) { this.code = code; this.stack = new Value[16384]; @@ -55,6 +57,7 @@ class VM } this.functions = functions; this.globalDataTable = gdt; + this.globalLabel = globalLabel; } Code getCurrent() { @@ -638,6 +641,27 @@ class GotoFalse : Code return "gotofalse " ~ address.to!string(16); } } +class GotoExpr : Code +{ + Scope sc; + this(Scope sc) + { + this.sc = sc; + } + override void execute(VM vm) + { + Value label; + vm.pop(label); + if(!label.isString) + { + vm.pc = vm.globalLabel[label.castString] - 1; + } + else + { + throw new TypeMismatch(); + } + } +} class GosubAddr : Code { int address; @@ -671,6 +695,28 @@ class GosubS : Code stderr.writeln("can't execute (compiler bug?)"); } } +class GosubExpr : Code +{ + Scope sc; + this(Scope sc) + { + this.sc = sc; + } + override void execute(VM vm) + { + Value label; + vm.pop(label); + if(!label.isString) + { + vm.push(Value(vm.pc)); + vm.pc = vm.globalLabel[label.castString] - 1; + } + else + { + throw new TypeMismatch(); + } + } +} class ReturnSubroutine : Code { this() diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index f7929bf..c146ef2 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -737,7 +737,16 @@ class Compiler break; case NodeType.Goto: { - genCodeGoto((cast(Goto)i).label, s); + auto gotou = cast(Goto)i; + if(!gotou.label) + { + compileExpression(gotou.labelexpr, s); + genCode(new GotoExpr(s)); + } + else + { + genCodeGoto(gotou.label, s); + } } break; case NodeType.If: @@ -749,7 +758,15 @@ class Compiler case NodeType.Gosub: { auto gosub = cast(Gosub)i; - genCodeGosub(gosub.label, s); + if(gosub.label) + { + genCodeGosub(gosub.label, s); + } + else + { + compileExpression(gosub.labelexpr, s); + genCode(new GosubExpr(s)); + } } break; case NodeType.Return: @@ -969,7 +986,7 @@ class Compiler code[i] = new RestoreCode(s.data.label[restore.label], s.data); } } - return new VM(code, globalIndex + 1, global, functions, s.data); + return new VM(code, globalIndex + 1, global, functions, s.data, globalLabel); } } diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index c6885f8..6490540 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -222,6 +222,12 @@ class Goto : Statement this.type = NodeType.Goto; this.label = name; } + Expression labelexpr; + this(Expression expr) + { + this.type = NodeType.Goto; + this.labelexpr = expr; + } } class If : Statement { @@ -271,6 +277,12 @@ class Gosub : Statement this.type = NodeType.Gosub; this.label = name; } + Expression labelexpr; + this(Expression expr) + { + this.type = NodeType.Gosub; + this.labelexpr = expr; + } } class Return : Statement { diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 6eb14f0..eee0d1e 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -825,8 +825,10 @@ class Parser node = new Goto(token.value.stringValue); else { - writeln("NotImpl"); - syntaxError(); + auto e = expression(); + if(!e) + syntaxError(); + node = new Goto(e); } break; case TokenType.Gosub: @@ -836,8 +838,10 @@ class Parser node = new Gosub(token.value.stringValue); else { - writeln("NotImpl"); - syntaxError(); + auto e = expression(); + if(!e) + syntaxError(); + node = new Gosub(e); } break; case TokenType.If: diff --git a/SMILEBASIC/sprite.d b/SMILEBASIC/sprite.d index f26c825..3d818e7 100644 --- a/SMILEBASIC/sprite.d +++ b/SMILEBASIC/sprite.d @@ -172,8 +172,6 @@ struct SpriteCollision return true; if(x <= x2 && y <= y2 + h2 && x + w >= x2 && y + h >= y2 + h2) return true; - //if(x2 <= x && y2 <= y && x2 + (data.w * data.scalex) >= x && y + (data.h * data.scaley) >= y) - // return true; return false; } }