From f6557d2e9ad400bb05587b9919af85bccea9b49d Mon Sep 17 00:00:00 2001 From: otya128 Date: Wed, 31 Aug 2016 23:16:44 +0900 Subject: [PATCH] =?UTF-8?q?INC/DEC=E3=82=92=E9=85=8D=E5=88=97=E3=81=AB?= =?UTF-8?q?=E5=AF=BE=E5=BF=9C=E3=81=95=E3=81=9B=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- SMILEBASIC/VM.d | 191 ++++++++++++++++++++++++++++++++++++++++++ SMILEBASIC/compiler.d | 89 ++++++++++++++++++-- SMILEBASIC/node.d | 4 +- SMILEBASIC/parser.d | 6 +- SMILEBASIC/type.d | 46 ++++++++-- 5 files changed, 316 insertions(+), 20 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 645f80d..4407ffa 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -346,6 +346,22 @@ class PushG : Code return "pushglobal " ~ vm.getGlobalVarName(var).to!string; } } +class PushGRef : Code +{ + int var; + this(int var) + { + this.var = var; + } + override void execute(VM vm) + { + vm.push(Value(&vm.currentSlot.global[var])); + } + override string toString(VM vm) + { + return "pushglobalref " ~ vm.getGlobalVarName(var).to!string; + } +} class PopG : Code { int var; @@ -402,6 +418,22 @@ class PushL : Code return "pushlocal " ~ var.to!string; } } +class PushLRef : Code +{ + int var; + this(int var) + { + this.var = var; + } + override void execute(VM vm) + { + vm.push(Value(&vm.stack[vm.bp + var])); + } + override string toString(VM vm) + { + return "pushlocalref " ~ var.to!string; + } +} class PopL : Code { int var; @@ -951,6 +983,70 @@ class PushArray : Code return "pusharray " ~ dim.to!string; } } +class PushArrayRef : Code +{ + int dim; + this(int dim) + { + this.dim = dim; + } + override void execute(VM vm) + { + int[4] index; + for(int i = 0; i < dim; i++) + { + Value v; + vm.pop(v); + if(v.type == ValueType.Integer) + { + index[i] = v.integerValue; + continue; + } + if(v.type == ValueType.Double) + { + index[i] = cast(int)v.doubleValue; + continue; + } + throw new TypeMismatch(); + } + Value array; + vm.pop(array); + if(!array.isArray) + { + throw new TypeMismatch(); + } + if(array.type == ValueType.IntegerArray) + { + vm.push(Value(&array.integerArray[index[0..dim]])); + return; + } + if(array.type == ValueType.DoubleArray) + { + vm.push(Value(&array.doubleArray[index[0..dim]])); + return; + } + if(array.type == ValueType.StringArray) + { + vm.push(Value(&array.stringArray[index[0..dim]])); + return; + } + if(array.type == ValueType.String) + { + if(dim != 1) + { + //TODO:syntaxError + throw new TypeMismatch(); + } + //String? + throw new TypeMismatch(); + } + throw new TypeMismatch(); + } + override string toString(VM vm) + { + return "pusharrayref " ~ dim.to!string; + } +} class PopArray : Code { int var; @@ -1639,3 +1735,98 @@ class DecSP : Code vm.decSP; } } +class PopRererence : Code +{ + override void execute(VM vm) + { + Value refv, value; + vm.pop(refv); + vm.pop(value); + if (refv.type == ValueType.Reference) + { + //TODO:型チェック? + *refv.reference = value; + return; + } + if (refv.type == ValueType.IntegerReference) + { + if (!value.isNumber) + { + throw new TypeMismatch(); + } + *refv.integerReference = value.castInteger; + return; + } + if (refv.type == ValueType.DoubleReference) + { + if (!value.isNumber) + { + throw new TypeMismatch(); + } + *refv.doubleReference = value.castDouble; + return; + } + if (refv.type == ValueType.StringReference) + { + if (!value.isString) + { + throw new TypeMismatch(); + } + *refv.stringReference = value.castString; + return; + } + } +} +class IncRef : Code +{ + //TODO:文字列INCの挙動 + override void execute(VM vm) + { + Value refv; + vm.pop(refv); + Value v; + vm.pop(v); + if (refv.type == ValueType.Reference) + { + if (refv.reference.isNumber && v.isNumber) + { + if (refv.reference.isDouble) + { + refv.reference.doubleValue += v.castDouble; + return; + } + if (refv.reference.isInteger) + { + refv.reference.integerValue += v.castInteger; + return; + } + } + if (refv.reference.isString && v.isString) + { + refv.reference.stringValue~= v.stringValue; + return; + } + } + + if (refv.type == ValueType.IntegerReference && v.isNumber) + { + *refv.integerReference += v.castInteger; + return; + } + if (refv.type == ValueType.DoubleReference && v.isNumber) + { + *refv.doubleReference += v.castDouble; + return; + } + if (refv.type == ValueType.StringReference && v.isString) + { + *refv.stringReference ~= v.castString; + return; + } + throw new TypeMismatch(); + } + override string toString(VM vm) + { + return "incref"; + } +} diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index dff12ac..6573b88 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -280,6 +280,34 @@ class Compiler } code ~= new PushG(getGlobalVarIndex(name)); } + void genCodePushVarRef(wstring name, Scope sc) + { + if(sc.func) + { + auto local = sc.func.hasLocalVarIndex(name); + if(local) + { + code ~= new PushLRef(local); + return; + } + } + auto global = hasGlobalVarIndex(name); + if(global) + { + if(global < 0) + { + throw new SyntaxError(); + } + code ~= new PushGRef(global); + return; + } + if(sc.func) + { + code ~= new PushLRef(sc.func.getLocalVarIndex(name, this)); + return; + } + code ~= new PushGRef(getGlobalVarIndex(name)); + } void genCodePopVar(wstring name, Scope sc) { if(sc.func) @@ -527,6 +555,56 @@ class Compiler break; } } + void compilePushReference(Expression exp, Scope sc) + { + if(!exp) + { + genCodeImm(Value(ValueType.Void)); + return; + } + switch(exp.type) + { + case NodeType.BinaryOperator: + { + auto binop = cast(BinaryOperator)exp; + compileExpression(binop.item1, sc); + compileExpression(binop.item2, sc); + if(binop.operator == TokenType.LBracket) + { + IndexExpressions ie = cast(IndexExpressions)binop.item2; + if(ie) + { + genCode(new PushArrayRef(cast(int)ie.expressions.length)); + } + else + { + genCode(new PushArrayRef(1)); + } + break; + } + } + break; + case NodeType.Variable: + auto var = cast(Variable)exp; + genCodePushVarRef(var.name, sc); + break; + case NodeType.IndexExpressions://[expr,expr,expr,expr]用 + { + auto index = cast(IndexExpressions)exp; + int count = 0; + foreach_reverse(Expression i; index.expressions) + { + compileExpression(i, sc); + count++; + if(count >= 4) break;//念のため + } + } + break; + default: + stderr.writeln("Compile:NotImpl ", exp.type); + break; + } + } void compilePopVar(Expression expr, Scope sc) { switch(expr.type) @@ -684,15 +762,8 @@ class Compiler void compileInc(Inc node, Scope sc) { compileExpression(node.expression, sc); - int index = sc.func ? sc.func.hasLocalVarIndex(node.name) : 0; - if(index) - { - genCode(new IncCodeL(index)); - } - else - { - genCode(new IncCodeG(this.getGlobalVarIndex(node.name))); - } + compilePushReference(node.name, sc); + genCode(new IncRef()); } void compileStatements(Statements statements, Scope sc) { diff --git a/SMILEBASIC/node.d b/SMILEBASIC/node.d index 82c3aac..dcc0e7d 100644 --- a/SMILEBASIC/node.d +++ b/SMILEBASIC/node.d @@ -474,9 +474,9 @@ class While : Statement } class Inc : Statement { - wstring name; + Expression name; Expression expression; - this(wstring name, Expression expr, SourceLocation loc) + this(Expression name, Expression expr, SourceLocation loc) { super.location = loc; this.type = NodeType.Inc; diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index b42600e..40009ab 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -1151,14 +1151,12 @@ class Parser bool dec = token.type == TokenType.Dec; lex.popFront(); token = lex.front(); - if(token.type != TokenType.Iden) + Expression var = expression(); + if(!isLValue(var)) { syntaxError(); return null; } - wstring var = token.value.stringValue; - //TODO:Array - lex.popFront(); token = lex.front(); Expression expr; if(token.type == TokenType.Comma) diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index dfa5ca8..1e55475 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -12,6 +12,10 @@ enum ValueType : byte StringArray, InternalAddress, InternalSlotAddress, + Reference, + IntegerReference, + DoubleReference, + StringReference, } struct VMAddress { @@ -31,6 +35,10 @@ struct Value Array!double doubleArray; Array!wstring stringArray; VMAddress internalAddress; + Value* reference; + int* integerReference; + double* doubleReference; + wstring* stringReference; } this(int value) { @@ -55,6 +63,26 @@ struct Value stringValue = ""; } } + this(Value* r) + { + this.type = ValueType.Reference; + reference = r; + } + this(int* r) + { + this.type = ValueType.IntegerReference; + integerReference = r; + } + this(double* r) + { + this.type = ValueType.DoubleReference; + doubleReference = r; + } + this(wstring* r) + { + this.type = ValueType.StringReference; + stringReference = r; + } void castOp(ValueType type) { switch(type) @@ -94,6 +122,14 @@ struct Value { return this.type == ValueType.Integer || this.type == ValueType.Double; } + bool isInteger() + { + return this.type == ValueType.Integer; + } + bool isDouble() + { + return this.type == ValueType.Double; + } bool isString() { return this.type == ValueType.String; @@ -240,7 +276,7 @@ class Array(T) throw new RangeError(); } } - T opIndex(int[] dim) + ref T opIndex(int[] dim) { import core.exception; switch(dim.length) @@ -257,25 +293,25 @@ class Array(T) throw new RangeError(); } } - T opIndex(int i1) + ref T opIndex(int i1) { if(dimCount != 1) throw new SyntaxError(); if(i1 >= dim[0]) throw new SubscriptOutOfRange(); return array[i1]; } - T opIndex(int i1, int i2) + ref T opIndex(int i1, int i2) { if(dimCount != 2) throw new SyntaxError(); if(i1 >= dim[0] && i2 >= dim[1]) throw new SubscriptOutOfRange(); return array[i1 * dim[0] + i2]; } - T opIndex(int i1, int i2, int i3) + ref T opIndex(int i1, int i2, int i3) { if(dimCount != 3) throw new SyntaxError(); if(i1 >= dim[0] && i2 >= dim[1] && i3 >= dim[2]) throw new SubscriptOutOfRange(); return array[i1 * dim[0] * dim[1] + i2 * dim[1] + i3]; } - T opIndex(int i1, int i2, int i3, int i4) + ref T opIndex(int i1, int i2, int i3, int i4) { if(dimCount != 4) throw new SyntaxError(); if(i1 >= dim[0] && i2 >= dim[1] && i3 >= dim[2] && i4 >= dim[3]) throw new SubscriptOutOfRange();