Fix array reference
This commit is contained in:
180
SMILEBASIC/VM.d
180
SMILEBASIC/VM.d
@@ -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,87 +1915,87 @@ 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)))
|
|
||||||
{
|
{
|
||||||
|
refitem1.integerReference.swap(refitem2.integerReference);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (refitem1.type == ValueType.IntegerReference && refitem2.type == ValueType.DoubleReference)
|
||||||
|
{
|
||||||
|
refitem1.integerReference.swap(refitem2.doubleReference);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (refitem1.type == ValueType.DoubleReference && refitem2.type == ValueType.IntegerReference)
|
||||||
|
{
|
||||||
|
refitem1.doubleReference.swap(refitem2.integerReference);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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();
|
throw new TypeMismatch();
|
||||||
}
|
}
|
||||||
import std.algorithm.mutation : swap;
|
|
||||||
if (sp1)
|
|
||||||
{
|
|
||||||
swap(*sp1, *sp2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (ip1 && ip2)
|
|
||||||
{
|
|
||||||
swap(*ip1, *ip2);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (dp1 && dp2)
|
|
||||||
{
|
|
||||||
swap(*dp1, *dp2);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PushVarRefExpression : Code
|
class PushVarRefExpression : Code
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user