From 2ec03c0d450987cb556f83b145fa6a27d8b1a43d Mon Sep 17 00:00:00 2001 From: otya128 Date: Sat, 17 Dec 2016 14:34:53 +0900 Subject: [PATCH] Fix array reference --- SMILEBASIC/VM.d | 166 ++++++++++++++++++++++++---------------------- SMILEBASIC/type.d | 87 ++++++++++++++++++++++-- 2 files changed, 169 insertions(+), 84 deletions(-) diff --git a/SMILEBASIC/VM.d b/SMILEBASIC/VM.d index 96fcb27..03d1e3f 100644 --- a/SMILEBASIC/VM.d +++ b/SMILEBASIC/VM.d @@ -1150,17 +1150,17 @@ class PushArrayRef : Code } if(array.type == ValueType.IntegerArray) { - vm.push(Value(&array.integerArray[index[0..dim]])); + vm.push(Value(array.integerArray.reference(index[0..dim]))); return; } if(array.type == ValueType.DoubleArray) { - vm.push(Value(&array.doubleArray[index[0..dim]])); + vm.push(Value(array.doubleArray.reference(index[0..dim]))); return; } if(array.type == ValueType.StringArray) { - vm.push(Value(&array.stringArray[index[0..dim]])); + vm.push(Value(array.stringArray.reference(index[0..dim]))); return; } if(array.type == ValueType.String) @@ -1170,8 +1170,8 @@ class PushArrayRef : Code //TODO:syntaxError throw new TypeMismatch(); } - //String? - throw new TypeMismatch(); + vm.push(Value(array.stringValue.reference(index[0..dim]))); + return; } throw new TypeMismatch(); } @@ -1826,7 +1826,7 @@ class PopRererence : Code { throw new TypeMismatch(); } - *refv.integerReference = value.castInteger; + refv.integerReference = value.castInteger; return; } if (refv.type == ValueType.DoubleReference) @@ -1835,7 +1835,16 @@ class PopRererence : Code { throw new TypeMismatch(); } - *refv.doubleReference = value.castDouble; + refv.doubleReference = value.castDouble; + return; + } + if (refv.type == ValueType.StringArrayReference) + { + if (!value.isString) + { + throw new TypeMismatch(); + } + refv.stringArrayReference = value.castString; return; } if (refv.type == ValueType.StringReference) @@ -1844,9 +1853,10 @@ class PopRererence : Code { throw new TypeMismatch(); } - *refv.stringReference = value.castString; + refv.stringReference = value.castString; return; } + throw new TypeMismatch(); } } class IncRef : Code @@ -1882,17 +1892,17 @@ class IncRef : Code if (refv.type == ValueType.IntegerReference && v.isNumber) { - *refv.integerReference += v.castInteger; + refv.integerReference += v.castInteger; return; } if (refv.type == ValueType.DoubleReference && v.isNumber) { - *refv.doubleReference += v.castDouble; + refv.doubleReference += v.castDouble; return; } - if (refv.type == ValueType.StringReference && v.isString) + if (refv.type == ValueType.StringArrayReference && v.isString) { - *refv.stringReference ~= v.castString; + refv.stringArrayReference ~= v.castString; return; } throw new TypeMismatch(); @@ -1905,86 +1915,86 @@ class IncRef : Code class SwapCode : Code { - void getPointer(ref Value v, out int* ip, out double* dp, out Array!(wchar)* sp) - { - ip = null; - dp = null; - sp = null; - if (v.type == ValueType.Reference) - { - if(v.reference.type == ValueType.Integer) - { - ip = &v.reference.integerValue; - return; - } - if(v.reference.type == ValueType.Double) - { - dp = &v.reference.doubleValue; - return; - } - if(v.reference.type == ValueType.String) - { - sp = &v.reference.stringValue; - return; - } - } - if (v.type == ValueType.IntegerReference) - { - ip = v.integerReference; - return; - } - if (v.type == ValueType.DoubleReference) - { - dp = v.doubleReference; - return; - } - if (v.type == ValueType.StringReference) - { - sp = v.stringReference; - return; - } - throw new TypeMismatch(); - } override void execute(VM vm) { + import std.algorithm.mutation : swap; Value refitem2, refitem1; vm.pop(refitem2); vm.pop(refitem1); - double* dp1, dp2; - int* ip1, ip2; - Array!(wchar)* sp1, sp2; - getPointer(refitem1, ip1, dp1, sp1); - getPointer(refitem2, ip2, dp2, sp2); - if ((sp1 && (dp2 || ip2)) || (sp2 && (dp1 || ip1))) + if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.IntegerReference) { - throw new TypeMismatch(); - } - import std.algorithm.mutation : swap; - if (sp1) - { - swap(*sp1, *sp2); + refitem1.integerReference.swap(refitem2.integerReference); return; } - if (ip1 && ip2) + if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.DoubleReference) { - swap(*ip1, *ip2); + refitem1.integerReference.swap(refitem2.doubleReference); return; } - if (dp1 && dp2) + if (refitem1.type == ValueType.DoubleReference && refitem2.type == ValueType.IntegerReference) { - swap(*dp1, *dp2); + refitem1.doubleReference.swap(refitem2.integerReference); return; } - double num1 = ip1 ? *ip1 : *dp1; - double num2 = ip2 ? *ip2 : *dp2; - if (ip2) - *ip2 = cast(int)num1; - else - *dp2 = num1; - if (ip1) - *ip1 = cast(int)num2; - else - *dp1 = num2; + if (refitem1.type == ValueType.DoubleReference && refitem2.type == ValueType.DoubleReference) + { + refitem1.doubleReference.swap(refitem2.doubleReference); + return; + } + int integer; + double double_; + + if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.Reference) + { + integer = refitem2.reference.castInteger; + refitem1.integerReference.swap(integer); + if (refitem2.reference.type == ValueType.Integer) + { + refitem2.reference.integerValue = integer; + } + if (refitem2.reference.type == ValueType.Double) + { + refitem2.reference.doubleValue = integer; + } + return; + } + if (refitem1.type == ValueType.DoubleReference && refitem2.type == ValueType.Reference) + { + double_ = refitem2.reference.castDouble; + refitem1.doubleReference.swap(double_); + if (refitem2.reference.type == ValueType.Integer) + { + refitem2.reference.integerValue = cast(int)double_; + } + if (refitem2.reference.type == ValueType.Double) + { + refitem2.reference.doubleValue = double_; + } + return; + } + if (refitem1.type == ValueType.Reference && refitem2.type == ValueType.Reference) + { + if (refitem1.reference.type == refitem2.reference.type) + { + swap(*refitem1.reference, *refitem2.reference); + return; + } + if (refitem1.reference.type == ValueType.Integer && refitem2.reference.type == ValueType.Double) + { + integer = refitem2.reference.castInteger; + refitem2.reference.doubleValue = refitem1.reference.castDouble; + refitem1.reference.integerValue = integer; + return; + } + if (refitem1.reference.type == ValueType.Double && refitem2.reference.type == ValueType.Integer) + { + integer = refitem2.reference.castInteger; + refitem2.reference.integerValue = refitem1.reference.integerValue; + refitem1.reference.doubleValue = integer; + return; + } + } + throw new TypeMismatch(); } } diff --git a/SMILEBASIC/type.d b/SMILEBASIC/type.d index 67080b3..7d98cd6 100644 --- a/SMILEBASIC/type.d +++ b/SMILEBASIC/type.d @@ -16,6 +16,7 @@ enum ValueType : byte IntegerReference, DoubleReference, StringReference, + StringArrayReference, } struct VMAddress { @@ -36,9 +37,10 @@ struct Value Array!(Array!wchar) stringArray; VMAddress internalAddress; Value* reference; - int* integerReference; - double* doubleReference; - Array!(wchar)* stringReference; + ArrayReference!int integerReference; + ArrayReference!double doubleReference; + ArrayReference!wchar stringReference; + ArrayReference!(Array!wchar) stringArrayReference; } this(int value) { @@ -78,21 +80,26 @@ struct Value this.type = ValueType.Reference; reference = r; } - this(int* r) + this(ArrayReference!int r) { this.type = ValueType.IntegerReference; integerReference = r; } - this(double* r) + this(ArrayReference!double r) { this.type = ValueType.DoubleReference; doubleReference = r; } - this(Array!(wchar)* r) + this(ArrayReference!wchar r) { this.type = ValueType.StringReference; stringReference = r; } + this(ArrayReference!(Array!wchar) r) + { + this.type = ValueType.StringArrayReference; + stringArrayReference = r; + } void castOp(ValueType type) { switch(type) @@ -459,5 +466,73 @@ class Array(T) dim[0] = array.length; return this; } + int calcIndex(int[] index) + { + if(dimCount != index.length) throw new SyntaxError(); + import core.exception; + switch(index.length) + { + case 1: + return index[0]; + default: + throw new RangeError(); + } + } + ArrayReference!T reference(int[] index) + { + auto i = calcIndex(index); + return ArrayReference!T(this, i); + } + void insert(Array!T ary, int index) + { + if(dimCount != 1 || ary.dimCount != 1 ) throw new SyntaxError(); + if (length == 0) + { + throw new SubscriptOutOfRange(); + } + array = array[0..index] ~ ary.array ~ array[index + 1..$]; + dim[0] = array.length; + } } +struct ArrayReference(T) +{ + Array!T reference; + int index; + T opAssign(T v) + { + return reference.array[index] = v; + } + static if (is(T == wchar)) + { + void opAssign(Array!T ary) + { + reference.insert(ary, index); + } + } + T opOpAssign(string op)(T v) + { + mixin("return reference.array[index]" ~ op ~ "=v;"); + } + T opBinary(string op)(T v) + { + mixin("return reference.array[index]" ~ op ~ "v;"); + } + T2 opCast(T2)() + { + return cast(T2)reference.array[index]; + } + void swap(T2)(ArrayReference!T2 t2) + { + T temp = reference.array[index]; + reference.array[index] = cast(T)t2; + t2 = cast(T2)temp; + } + void swap(T2)(ref T2 t2) + if (!is(T2 T3 == ArrayReference!T3)) + { + T temp = reference.array[index]; + reference.array[index] = cast(T)t2; + t2 = cast(T2)temp; + } +}