240 lines
6.4 KiB
D
240 lines
6.4 KiB
D
module otya.smilebasic.type;
|
|
import otya.smilebasic.error;
|
|
enum ValueType : byte
|
|
{
|
|
Void,//DEF A()ENDの返り値とか未初期化の変数とか
|
|
Integer,
|
|
Double,
|
|
String,
|
|
Array,
|
|
IntegerArray,
|
|
DoubleArray,
|
|
StringArray,
|
|
}
|
|
struct Value
|
|
{
|
|
ValueType type;
|
|
union
|
|
{
|
|
int integerValue;
|
|
double doubleValue;
|
|
//TODO:Array!wchar stringValue;にしたい
|
|
wstring stringValue;
|
|
Array!int integerArray;
|
|
Array!double doubleArray;
|
|
Array!wstring stringArray;
|
|
}
|
|
this(int value)
|
|
{
|
|
this.type = ValueType.Integer;
|
|
integerValue = value;
|
|
}
|
|
this(double value)
|
|
{
|
|
this.type = ValueType.Double;
|
|
doubleValue = value;
|
|
}
|
|
this(wstring value)
|
|
{
|
|
this.type = ValueType.String;
|
|
stringValue = value;
|
|
}
|
|
this(ValueType type)
|
|
{
|
|
this.type = type;
|
|
if(type == ValueType.String)
|
|
{
|
|
stringValue = "";
|
|
}
|
|
}
|
|
void castOp(ValueType type)
|
|
{
|
|
switch(type)
|
|
{
|
|
case ValueType.Double:
|
|
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
bool boolValue()
|
|
{
|
|
switch(type)
|
|
{
|
|
case ValueType.Double:
|
|
return this.doubleValue != 0;
|
|
case ValueType.Integer:
|
|
return this.integerValue != 0;
|
|
case ValueType.String:
|
|
return true;//3.1現在では文字列はtrue(ただし!"A"などは動かない)
|
|
default:
|
|
//配列はtype mismatch
|
|
return false;
|
|
}
|
|
}
|
|
bool isArray()
|
|
{
|
|
return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray ||
|
|
this.type == ValueType.StringArray || this.type == ValueType.String;
|
|
}
|
|
bool isNumberArray()
|
|
{
|
|
return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray;
|
|
}
|
|
bool isNumber()
|
|
{
|
|
return this.type == ValueType.Integer || this.type == ValueType.Double;
|
|
}
|
|
bool isString()
|
|
{
|
|
return this.type == ValueType.String;
|
|
}
|
|
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);
|
|
}
|
|
wstring castString()
|
|
{
|
|
return this.type == ValueType.String ? this.stringValue : "";
|
|
}
|
|
string toString()
|
|
{
|
|
import std.conv;
|
|
switch(this.type)
|
|
{
|
|
case ValueType.Void:
|
|
return "void";
|
|
case ValueType.Integer:
|
|
return this.integerValue.to!string;
|
|
case ValueType.String:
|
|
return this.stringValue.to!string;
|
|
default:
|
|
return "default";
|
|
}
|
|
}
|
|
}
|
|
class Array(T)
|
|
{
|
|
T[] array;
|
|
//最大要素数2^^31
|
|
//4次元配列
|
|
int[4] dim;
|
|
int dimCount;
|
|
this(int len)
|
|
{
|
|
dim[0] = len;
|
|
dim[1] = 0;
|
|
dim[2] = 0;
|
|
dim[3] = 0;
|
|
array = new T[len];
|
|
static if(is(T == double))
|
|
{
|
|
array[] = 0;
|
|
}
|
|
dimCount = 1;
|
|
}
|
|
this(int[] dim)
|
|
{
|
|
int len = 1;
|
|
foreach(int i, j; dim)
|
|
{
|
|
len *= j;
|
|
this.dim[i] = dim[i];
|
|
}
|
|
array = new T[len];
|
|
static if(is(T == double))
|
|
{
|
|
array[] = 0;
|
|
}
|
|
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)
|
|
{
|
|
if(dimCount != 1) throw new SyntaxError();
|
|
if(i1 >= dim[0]) throw new SubscriptOutOfRange();
|
|
return array[i1];
|
|
}
|
|
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)
|
|
{
|
|
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)
|
|
{
|
|
if(dimCount != 4) throw new SyntaxError();
|
|
if(i1 >= dim[0] && i2 >= dim[1] && i3 >= dim[2] && i4 >= dim[3]) throw new SubscriptOutOfRange();
|
|
return array[i1];//array[i1 * dim[0] * dim[1] * dim[2] + i2 * dim[1] + i3];
|
|
}
|
|
T opIndexAssign(T v, int i1)
|
|
{
|
|
if(dimCount != 1) throw new SyntaxError();
|
|
if(i1 >= dim[0]) throw new SubscriptOutOfRange();
|
|
return array[i1] = v;
|
|
}
|
|
T opIndexAssign(T v, 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] = v;
|
|
}
|
|
T opIndexAssign(T v, 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] = v;
|
|
}
|
|
T opIndexAssign(T v, 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();
|
|
return array[i1] = v;//array[i1 * dim[0] * dim[1] * dim[2] + i2 * dim[1] + i3] = v;
|
|
}
|
|
|
|
}
|