1
0

Fix array reference

This commit is contained in:
otya128
2016-12-17 14:34:53 +09:00
parent ae3a005601
commit 2ec03c0d45
2 changed files with 169 additions and 84 deletions

View File

@@ -1150,17 +1150,17 @@ class PushArrayRef : Code
} }
if(array.type == ValueType.IntegerArray) if(array.type == ValueType.IntegerArray)
{ {
vm.push(Value(&array.integerArray[index[0..dim]])); vm.push(Value(array.integerArray.reference(index[0..dim])));
return; return;
} }
if(array.type == ValueType.DoubleArray) if(array.type == ValueType.DoubleArray)
{ {
vm.push(Value(&array.doubleArray[index[0..dim]])); vm.push(Value(array.doubleArray.reference(index[0..dim])));
return; return;
} }
if(array.type == ValueType.StringArray) if(array.type == ValueType.StringArray)
{ {
vm.push(Value(&array.stringArray[index[0..dim]])); vm.push(Value(array.stringArray.reference(index[0..dim])));
return; return;
} }
if(array.type == ValueType.String) if(array.type == ValueType.String)
@@ -1170,8 +1170,8 @@ class PushArrayRef : Code
//TODO:syntaxError //TODO:syntaxError
throw new TypeMismatch(); throw new TypeMismatch();
} }
//String? vm.push(Value(array.stringValue.reference(index[0..dim])));
throw new TypeMismatch(); return;
} }
throw new TypeMismatch(); throw new TypeMismatch();
} }
@@ -1826,7 +1826,7 @@ class PopRererence : Code
{ {
throw new TypeMismatch(); throw new TypeMismatch();
} }
*refv.integerReference = value.castInteger; refv.integerReference = value.castInteger;
return; return;
} }
if (refv.type == ValueType.DoubleReference) if (refv.type == ValueType.DoubleReference)
@@ -1835,7 +1835,16 @@ class PopRererence : Code
{ {
throw new TypeMismatch(); 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; return;
} }
if (refv.type == ValueType.StringReference) if (refv.type == ValueType.StringReference)
@@ -1844,9 +1853,10 @@ class PopRererence : Code
{ {
throw new TypeMismatch(); throw new TypeMismatch();
} }
*refv.stringReference = value.castString; refv.stringReference = value.castString;
return; return;
} }
throw new TypeMismatch();
} }
} }
class IncRef : Code class IncRef : Code
@@ -1882,17 +1892,17 @@ class IncRef : Code
if (refv.type == ValueType.IntegerReference && v.isNumber) if (refv.type == ValueType.IntegerReference && v.isNumber)
{ {
*refv.integerReference += v.castInteger; refv.integerReference += v.castInteger;
return; return;
} }
if (refv.type == ValueType.DoubleReference && v.isNumber) if (refv.type == ValueType.DoubleReference && v.isNumber)
{ {
*refv.doubleReference += v.castDouble; refv.doubleReference += v.castDouble;
return; return;
} }
if (refv.type == ValueType.StringReference && v.isString) if (refv.type == ValueType.StringArrayReference && v.isString)
{ {
*refv.stringReference ~= v.castString; refv.stringArrayReference ~= v.castString;
return; return;
} }
throw new TypeMismatch(); throw new TypeMismatch();
@@ -1905,86 +1915,86 @@ class IncRef : Code
class SwapCode : 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) override void execute(VM vm)
{ {
import std.algorithm.mutation : swap;
Value refitem2, refitem1; Value refitem2, refitem1;
vm.pop(refitem2); vm.pop(refitem2);
vm.pop(refitem1); vm.pop(refitem1);
double* dp1, dp2; if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.IntegerReference)
int* ip1, ip2;
Array!(wchar)* sp1, sp2;
getPointer(refitem1, ip1, dp1, sp1);
getPointer(refitem2, ip2, dp2, sp2);
if ((sp1 && (dp2 || ip2)) || (sp2 && (dp1 || ip1)))
{ {
throw new TypeMismatch(); refitem1.integerReference.swap(refitem2.integerReference);
}
import std.algorithm.mutation : swap;
if (sp1)
{
swap(*sp1, *sp2);
return; return;
} }
if (ip1 && ip2) if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.DoubleReference)
{ {
swap(*ip1, *ip2); refitem1.integerReference.swap(refitem2.doubleReference);
return; return;
} }
if (dp1 && dp2) if (refitem1.type == ValueType.DoubleReference && refitem2.type == ValueType.IntegerReference)
{ {
swap(*dp1, *dp2); refitem1.doubleReference.swap(refitem2.integerReference);
return; return;
} }
double num1 = ip1 ? *ip1 : *dp1; if (refitem1.type == ValueType.DoubleReference && refitem2.type == ValueType.DoubleReference)
double num2 = ip2 ? *ip2 : *dp2; {
if (ip2) refitem1.doubleReference.swap(refitem2.doubleReference);
*ip2 = cast(int)num1; return;
else }
*dp2 = num1; int integer;
if (ip1) double double_;
*ip1 = cast(int)num2;
else if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.Reference)
*dp1 = num2; {
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();
} }
} }

View File

@@ -16,6 +16,7 @@ enum ValueType : byte
IntegerReference, IntegerReference,
DoubleReference, DoubleReference,
StringReference, StringReference,
StringArrayReference,
} }
struct VMAddress struct VMAddress
{ {
@@ -36,9 +37,10 @@ struct Value
Array!(Array!wchar) stringArray; Array!(Array!wchar) stringArray;
VMAddress internalAddress; VMAddress internalAddress;
Value* reference; Value* reference;
int* integerReference; ArrayReference!int integerReference;
double* doubleReference; ArrayReference!double doubleReference;
Array!(wchar)* stringReference; ArrayReference!wchar stringReference;
ArrayReference!(Array!wchar) stringArrayReference;
} }
this(int value) this(int value)
{ {
@@ -78,21 +80,26 @@ struct Value
this.type = ValueType.Reference; this.type = ValueType.Reference;
reference = r; reference = r;
} }
this(int* r) this(ArrayReference!int r)
{ {
this.type = ValueType.IntegerReference; this.type = ValueType.IntegerReference;
integerReference = r; integerReference = r;
} }
this(double* r) this(ArrayReference!double r)
{ {
this.type = ValueType.DoubleReference; this.type = ValueType.DoubleReference;
doubleReference = r; doubleReference = r;
} }
this(Array!(wchar)* r) this(ArrayReference!wchar r)
{ {
this.type = ValueType.StringReference; this.type = ValueType.StringReference;
stringReference = r; stringReference = r;
} }
this(ArrayReference!(Array!wchar) r)
{
this.type = ValueType.StringArrayReference;
stringArrayReference = r;
}
void castOp(ValueType type) void castOp(ValueType type)
{ {
switch(type) switch(type)
@@ -459,5 +466,73 @@ class Array(T)
dim[0] = array.length; dim[0] = array.length;
return this; 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;
}
}