diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index aae32e7..b07b355 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -551,3 +551,68 @@ class NewArray : Code } } } +class PopGArray : Code +{ + int var; + int dim; + this(int var, int dim) + { + this.var = var; + this.dim = dim; + } + override void execute(VM vm) + { + Value array = vm.global[var]; + if(!array.isArray) + { + throw new TypeMismatch(); + } + int[4] index; + for(int i = dim - 1; i >= 0; 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 assign; + vm.pop(assign); + if(array.type == ValueType.IntegerArray && assign.isNumber) + { + array.integerArray[index[0..dim]] = assign.castInteger(); + return; + } + if(array.type == ValueType.DoubleArray && assign.isNumber) + { + array.doubleArray[index[0..dim]] = assign.castDouble(); + return; + } + if(array.type == ValueType.StringArray && assign.type == ValueType.String) + { + array.stringArray[index[0..dim]] = assign.stringValue; + return; + } + if(array.type == ValueType.String && assign.type == ValueType.String) + { + if(dim != 1) + { + //TODO:syntaxError + throw new TypeMismatch(); + } + //TODO:文字列の挙動 + throw new TypeMismatch(); + //array.stringValue[index[0]] = assign.stringValue[0]; + return; + } + throw new TypeMismatch(); + } +} diff --git a/SMILEBASIC/compiler.d b/SMILEBASIC/compiler.d index 10bd1cc..74d3677 100644 --- a/SMILEBASIC/compiler.d +++ b/SMILEBASIC/compiler.d @@ -162,6 +162,18 @@ class Compiler } } break; + case NodeType.IndexExpressions://[expr,expr,expr,expr]用 + { + auto index = cast(IndexExpressions)exp; + int count = 0; + foreach_reverse(Expression i; index.expressions) + { + compileExpression(i); + count++; + if(count >= 4) break;//念のため + } + } + break; default: stderr.writeln("Compile:NotImpl ", exp.type); break; @@ -358,6 +370,13 @@ class Compiler case NodeType.Var: compileVar(cast(Var)i, s); break; + case NodeType.ArrayAssign: + { + auto assign = cast(ArrayAssign)i; + compileExpression(assign.assignExpression); + compileExpression(assign.indexExpression); + genCode(new PopGArray(getGlobalVarIndex(assign.name), assign.indexExpression.expressions.length)); + } default: stderr.writeln("Compile:NotImpl ", i.type); } diff --git a/SMILEBASIC/main.d b/SMILEBASIC/main.d index c15f0d3..01066e1 100644 --- a/SMILEBASIC/main.d +++ b/SMILEBASIC/main.d @@ -54,6 +54,7 @@ FOR I=0 TO 10 ?I NEXT VAR V[10] +V[0]=12 ?V[0] ?\"ABC\"[1][0] GOSUB @A diff --git a/SMILEBASIC/parser.d b/SMILEBASIC/parser.d index 1aeb981..6a8d7d9 100644 --- a/SMILEBASIC/parser.d +++ b/SMILEBASIC/parser.d @@ -554,13 +554,19 @@ class Parser IndexExpressions indexExpressions() { IndexExpressions ie = new IndexExpressions(); + int count = 0; while(true) { ie.addExpression(expression()); + count++; auto token = lex.front(); if(token.type == TokenType.Comma) { lex.popFront(); + if(count >= 4) + { + syntaxError(); + } continue; } if(token.type == TokenType.RBracket) @@ -589,7 +595,9 @@ class Parser syntaxError(); return null; } + lex.popFront(); auto expr = expression(); + token = lex.front(); auto node = new ArrayAssign(name, ie, expr); return node; } diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index d79e82b..491552d 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -17,6 +17,7 @@ struct Value { int integerValue; double doubleValue; + //TODO:Array!wchar stringValue;にしたい wstring stringValue; Array!int integerArray; Array!double doubleArray; @@ -71,6 +72,23 @@ struct Value return false; } } + bool isArray() + { + return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray || + this.type == ValueType.StringArray || this.type == ValueType.String; + } + bool isNumber() + { + return this.type == ValueType.Integer || this.type == ValueType.Double; + } + int castInteger() + { + return this.type == ValueType.Integer ? this.integerValue : (this.type == ValueType.Double ? cast(int)this.doubleValue : 0); + } + double castDouble() + { + return this.type == ValueType.Integer ? this.integerValue : (this.type == ValueType.Double ? this.doubleValue : 0); + } } class Array(T) { @@ -98,6 +116,40 @@ class Array(T) array = new T[len]; dimCount = dim.length; } + T opIndexAssign(T v, int[] dim) + { + import core.exception; + switch(dim.length) + { + case 1: + return this[dim[0]] = v; + case 2: + return this[dim[0], dim[1]] = v; + case 3: + return this[dim[0], dim[1], dim[2]] = v; + case 4: + return this[dim[0], dim[1], dim[2], dim[3]] = v; + default: + throw new RangeError(); + } + } + T opIndex(int[] dim) + { + import core.exception; + switch(dim.length) + { + case 1: + return this[dim[0]]; + case 2: + return this[dim[0], dim[1]]; + case 3: + return this[dim[0], dim[1], dim[2]]; + case 4: + return this[dim[0], dim[1], dim[2], dim[3]]; + default: + throw new RangeError(); + } + } T opIndex(int i1) { return array[i1]; @@ -114,5 +166,21 @@ class Array(T) { return array[i1];//array[i1 * dim[0] * dim[1] * dim[2] + i2 * dim[1] + i3]; } + T opIndexAssign(T v, int i1) + { + return array[i1] = v; + } + T opIndexAssign(T v, int i1, int i2) + { + return array[i1 * dim[0] + i2] = v; + } + T opIndexAssign(T v, int i1, int i2, int i3) + { + return array[i1 * dim[0] * dim[1] + i2 * dim[1] + i3] = v; + } + T opIndexAssign(T v, int i1, int i2, int i3, int i4) + { + return array[i1] = v;//array[i1 * dim[0] * dim[1] * dim[2] + i2 * dim[1] + i3] = v; + } }