1
0

XSCREENとSPDEFとDISPLAY実�

This commit is contained in:
otya128
2015-08-22 22:16:13 +09:00
parent 6a69ba1fb3
commit 8d4a9a2d13
8 changed files with 552 additions and 114 deletions

View File

@@ -1,3 +1,8 @@
ASSERT__ SUBST$("0123456789",0,"B")=="B","SUBST$"
ASSERT__ SUBST$("0123456789",0,4,"B")=="B456789","SUBST$"
ASSERT__ SUBST$("",0,4,"B")=="B","SUBST$"
WHILE 1
WEND
FOR I=0TO 511'-500 FOR I=0TO 511'-500
SPSET I,I'304'-I+304 SPSET I,I'304'-I+304
SPOFS I, (I*16) MOD 400, FLOOR((I*16)/400)*16 SPOFS I, (I*16) MOD 400, FLOOR((I*16)/400)*16

View File

@@ -49,6 +49,10 @@ class VM
this.functions = functions; this.functions = functions;
this.globalDataTable = gdt; this.globalDataTable = gdt;
} }
Code getCurrent()
{
return code[pc];
}
void run() void run()
{ {
bp = 0;//globalを実行なのでbaseは0(グローバル変数をスタックに取るようにしない限り)(挙動的にスタックに確保していなさそう) bp = 0;//globalを実行なのでbaseは0(グローバル変数をスタックに取るようにしない限り)(挙動的にスタックに確保していなさそう)
@@ -110,6 +114,38 @@ class VM
{ {
pc = code.length; pc = code.length;
} }
void dump()
{
foreach(i, c; code)
writefln("%04X:%s", i, c.toString(this));
}
wstring getGlobalVarName(int index)
{
foreach(k, v; globalTable)
{
if(v.index == index) return k;
}
return "undefined variable";
}
Value readData()
{
Value value;
this.globalDataTable.read(value, this);
return value;
}
void restoreData(wstring label)
{
this.globalDataTable.dataIndex = this.globalDataTable.label[label];
}
int olddti;
void pushDataIndex()
{
olddti = this.globalDataTable.dataIndex;
}
void popDataIndex()
{
this.globalDataTable.dataIndex = olddti;
}
} }
enum CodeType enum CodeType
{ {
@@ -135,6 +171,10 @@ abstract class Code
{ {
CodeType type; CodeType type;
abstract void execute(VM vm); abstract void execute(VM vm);
string toString(VM vm)
{
return super.toString();
}
} }
class PrintCode : Code class PrintCode : Code
{ {
@@ -174,6 +214,10 @@ class PrintCode : Code
} }
stdout.flush(); stdout.flush();
} }
override string toString(VM vm)
{
return "print";
}
} }
/* /*
* スタックにPush * スタックにPush
@@ -190,6 +234,10 @@ class Push : Code
{ {
vm.push(imm); vm.push(imm);
} }
override string toString(VM vm)
{
return "push " ~ imm.toString;
}
} }
class PushG : Code class PushG : Code
@@ -204,6 +252,10 @@ class PushG : Code
{ {
vm.push(vm.global[var]); vm.push(vm.global[var]);
} }
override string toString(VM vm)
{
return "pushglobal " ~ vm.getGlobalVarName(var).to!string;
}
} }
class PopG : Code class PopG : Code
{ {
@@ -239,6 +291,10 @@ class PopG : Code
} }
vm.global[var] = v; vm.global[var] = v;
} }
override string toString(VM vm)
{
return "popglobal " ~ vm.getGlobalVarName(var).to!string;
}
} }
class PushL : Code class PushL : Code
{ {
@@ -252,6 +308,10 @@ class PushL : Code
{ {
vm.push(vm.stack[vm.bp + var]); vm.push(vm.stack[vm.bp + var]);
} }
override string toString(VM vm)
{
return "pushlocal " ~ var.to!string;
}
} }
class PopL : Code class PopL : Code
{ {
@@ -287,6 +347,10 @@ class PopL : Code
} }
vm.stack[vm.bp + var] = v; vm.stack[vm.bp + var] = v;
} }
override string toString(VM vm)
{
return "poplocal " ~ var.to!string;
}
} }
class Operate : Code class Operate : Code
{ {
@@ -479,6 +543,10 @@ class Operate : Code
l.doubleValue = ld; l.doubleValue = ld;
vm.push(l); vm.push(l);
} }
override string toString(VM vm)
{
return "operate " ~ operator.to!string;
}
} }
class GotoAddr : Code class GotoAddr : Code
{ {
@@ -492,6 +560,10 @@ class GotoAddr : Code
{ {
vm.pc = address - 1; vm.pc = address - 1;
} }
override string toString(VM vm)
{
return "goto " ~ address.to!string(16);
}
} }
class GotoS : Code class GotoS : Code
{ {
@@ -523,6 +595,10 @@ class GotoTrue : Code
if(cond.boolValue) if(cond.boolValue)
vm.pc = address - 1; vm.pc = address - 1;
} }
override string toString(VM vm)
{
return "gototrue " ~ address.to!string(16);
}
} }
class GotoFalse : Code class GotoFalse : Code
{ {
@@ -539,6 +615,10 @@ class GotoFalse : Code
if(!cond.boolValue) if(!cond.boolValue)
vm.pc = address - 1; vm.pc = address - 1;
} }
override string toString(VM vm)
{
return "gotofalse " ~ address.to!string(16);
}
} }
class GosubAddr : Code class GosubAddr : Code
{ {
@@ -553,6 +633,10 @@ class GosubAddr : Code
vm.push(Value(vm.pc)); vm.push(Value(vm.pc));
vm.pc = address - 1; vm.pc = address - 1;
} }
override string toString(VM vm)
{
return "gosub " ~ address.to!string(16);
}
} }
class GosubS : Code class GosubS : Code
{ {
@@ -591,6 +675,10 @@ class ReturnSubroutine : Code
} }
vm.pc = pc.integerValue; vm.pc = pc.integerValue;
} }
override string toString(VM vm)
{
return "returnsubroutine ";
}
} }
class EndVM : Code class EndVM : Code
{ {
@@ -601,6 +689,10 @@ class EndVM : Code
{ {
vm.end(); vm.end();
} }
override string toString(VM vm)
{
return "endvm";
}
} }
class NewArray : Code class NewArray : Code
{ {
@@ -652,6 +744,10 @@ class NewArray : Code
} }
vm.push(array); vm.push(array);
} }
override string toString(VM vm)
{
return "newarray " ~ dim.to!string;
}
} }
class PushArray : Code class PushArray : Code
{ {
@@ -712,6 +808,10 @@ class PushArray : Code
} }
throw new TypeMismatch(); throw new TypeMismatch();
} }
override string toString(VM vm)
{
return "pusharray " ~ dim.to!string;
}
} }
class PopArray : Code class PopArray : Code
{ {
@@ -787,6 +887,10 @@ class PopArray : Code
} }
throw new TypeMismatch(); throw new TypeMismatch();
} }
override string toString(VM vm)
{
return "poparray " ~ dim.to!string ~ ", " ~ var.to!string ~ ", " ~ local.to!string;
}
} }
class ReturnFunction : Code class ReturnFunction : Code
{ {
@@ -823,6 +927,10 @@ class ReturnFunction : Code
vm.pc = pc.integerValue; vm.pc = pc.integerValue;
vm.bp = bp.integerValue; vm.bp = bp.integerValue;
} }
override string toString(VM vm)
{
return "returnfunc " ~ func.name.to!string;
}
} }
class CallFunctionCode : Code class CallFunctionCode : Code
{ {
@@ -846,15 +954,15 @@ class CallFunctionCode : Code
Function func = vm.functions.get(name, null); Function func = vm.functions.get(name, null);
if(!func) if(!func)
{ {
throw new SyntaxError(); throw new SyntaxError(name);
} }
if(func.argCount != this.argCount) if(func.argCount != this.argCount)
{ {
throw new IllegalFunctionCall(); throw new IllegalFunctionCall(name.to!string);
} }
if(func.outArgCount != this.outArgCount) if(func.outArgCount != this.outArgCount)
{ {
throw new IllegalFunctionCall(); throw new IllegalFunctionCall(name.to!string);
} }
//TODO:args //TODO:args
auto bp = vm.stacki; auto bp = vm.stacki;
@@ -871,6 +979,10 @@ class CallFunctionCode : Code
} }
} }
} }
override string toString(VM vm)
{
return "callfunc " ~ name.to!string;
}
} }
import otya.smilebasic.builtinfunctions; import otya.smilebasic.builtinfunctions;
class CallBuiltinFunction : Code class CallBuiltinFunction : Code
@@ -914,6 +1026,10 @@ class CallBuiltinFunction : Code
vm.push(result[i]); vm.push(result[i]);
} }
} }
override string toString(VM vm)
{
return "callbuiltin " ~ func.name.to!string;
}
} }
class IncCodeG : Code class IncCodeG : Code
{ {
@@ -952,6 +1068,10 @@ class IncCodeG : Code
vm.global[var] = Value(l ~ r); vm.global[var] = Value(l ~ r);
} }
} }
override string toString(VM vm)
{
return "incglobal " ~ var.to!string;
}
} }
class IncCodeL : Code class IncCodeL : Code
{ {
@@ -990,6 +1110,10 @@ class IncCodeL : Code
*g = Value(l ~ r); *g = Value(l ~ r);
} }
} }
override string toString(VM vm)
{
return "inclocal " ~ var.to!string;
}
} }
class OnBase : Code class OnBase : Code
{ {
@@ -1043,6 +1167,10 @@ class OnGoto : OnBase
if(index < 0) return; if(index < 0) return;
vm.pc = index - 1; vm.pc = index - 1;
} }
override string toString(VM vm)
{
return "ongoto " ~ labels.to!string;
}
} }
class OnGosub : OnBase class OnGosub : OnBase
{ {
@@ -1057,6 +1185,10 @@ class OnGosub : OnBase
vm.push(Value(vm.pc)); vm.push(Value(vm.pc));
vm.pc = index - 1; vm.pc = index - 1;
} }
override string toString(VM vm)
{
return "ongosub " ~ labels.to!string;
}
} }
import std.string; import std.string;
class InputCode : Code class InputCode : Code
@@ -1141,6 +1273,10 @@ class InputCode : Code
} }
} while(error); } while(error);
} }
override string toString(VM vm)
{
return "input " ~ count.to!string;
}
} }
class ReadCode : Code class ReadCode : Code
{ {
@@ -1158,6 +1294,10 @@ class ReadCode : Code
vm.push(data); vm.push(data);
} }
} }
override string toString(VM vm)
{
return "read " ~ count.to!string;
}
} }
class RestoreCodeS : Code class RestoreCodeS : Code
{ {
@@ -1185,6 +1325,10 @@ class RestoreCode : Code
{ {
datatable.dataIndex = label; datatable.dataIndex = label;
} }
override string toString(VM vm)
{
return "restore " ~ label.to!string;
}
} }
class PushSystemVariable : Code class PushSystemVariable : Code
{ {
@@ -1197,6 +1341,10 @@ class PushSystemVariable : Code
{ {
vm.push(var.value); vm.push(var.value);
} }
override string toString(VM vm)
{
return "pushsysvar " ~ var.to!string;
}
} }
class PopSystemVariable : Code class PopSystemVariable : Code
{ {
@@ -1211,4 +1359,8 @@ class PopSystemVariable : Code
vm.pop(v); vm.pop(v);
var.value = v; var.value = v;
} }
override string toString(VM vm)
{
return "popsysvar " ~ var.to!string;
}
} }

View File

@@ -11,6 +11,7 @@ import otya.smilebasic.error;
import otya.smilebasic.type; import otya.smilebasic.type;
import otya.smilebasic.petitcomputer; import otya.smilebasic.petitcomputer;
import otya.smilebasic.sprite; import otya.smilebasic.sprite;
import otya.smilebasic.vm;
//プチコンの引数省略は特殊なので //プチコンの引数省略は特殊なので
//LOCATE ,,0のように省略できる //LOCATE ,,0のように省略できる
struct DefaultValue(T, bool skippable = true) struct DefaultValue(T, bool skippable = true)
@@ -52,14 +53,16 @@ class BuiltinFunction
void function(PetitComputer, Value[], Value[]) func; void function(PetitComputer, Value[], Value[]) func;
int startskip; int startskip;
bool variadic; bool variadic;
string name;
this(BuiltinFunctionArgument[] argments, ValueType result, void function(PetitComputer, Value[], Value[]) func, int startskip, this(BuiltinFunctionArgument[] argments, ValueType result, void function(PetitComputer, Value[], Value[]) func, int startskip,
bool variadic) bool variadic, string name)
{ {
this.argments = argments; this.argments = argments;
this.result = result; this.result = result;
this.func = func; this.func = func;
this.startskip = startskip; this.startskip = startskip;
this.variadic = variadic; this.variadic = variadic;
this.name = name;
} }
bool hasSkipArgument() bool hasSkipArgument()
{ {
@@ -99,6 +102,11 @@ class BuiltinFunction
time.setDefaultValue(1); time.setDefaultValue(1);
p.vsync(cast(int)time); p.vsync(cast(int)time);
} }
static void WAIT(PetitComputer p, DefaultValue!int time)
{
time.setDefaultValue(1);
p.vsync(cast(int)time);
}
//TODO:プチコンのCLSには引数の個数制限がない //TODO:プチコンのCLSには引数の個数制限がない
static void CLS(PetitComputer p/*vaarg*/) static void CLS(PetitComputer p/*vaarg*/)
{ {
@@ -121,9 +129,13 @@ class BuiltinFunction
} }
static void XSCREEN(PetitComputer p, int mode, DefaultValue!(int, false) a, DefaultValue!(int, false) b) static void XSCREEN(PetitComputer p, int mode, DefaultValue!(int, false) a, DefaultValue!(int, false) b)
{ {
a.setDefaultValue(512);
b.setDefaultValue(512);
p.xscreen(mode, cast(int)a, cast(int)b);
} }
static void DISPLAY(PetitComputer p, DefaultValue!(int, false) display) static void DISPLAY(PetitComputer p, int display)
{ {
p.display(display);
} }
static void GCLS(PetitComputer p, DefaultValue!(int, false) color) static void GCLS(PetitComputer p, DefaultValue!(int, false) color)
{ {
@@ -157,6 +169,11 @@ class BuiltinFunction
static void GPRIO(PetitComputer p, int z) static void GPRIO(PetitComputer p, int z)
{ {
} }
static void GPAGE(PetitComputer p, int showPage, int usePage)
{
p.showGRP = showPage;
p.useGRP = usePage;
}
static void BGMPLAY(PetitComputer p, int music) static void BGMPLAY(PetitComputer p, int music)
{ {
} }
@@ -181,7 +198,7 @@ class BuiltinFunction
static int RND(int max) static int RND(int max)
{ {
import std.random; import std.random;
return uniform(0, max - 1); return uniform(0, max - 1 + 1);
} }
static void DTREAD(DefaultValue!(wstring, false) date, out int Y, out int M, out int D/*W*/) static void DTREAD(DefaultValue!(wstring, false) date, out int Y, out int M, out int D/*W*/)
{ {
@@ -206,6 +223,8 @@ class BuiltinFunction
return str.length; return str.length;
} }
static double VAL(wstring str) static double VAL(wstring str)
{
try
{ {
if(str[0..2] == "&H") if(str[0..2] == "&H")
{ {
@@ -214,15 +233,74 @@ class BuiltinFunction
double val = str.to!double; double val = str.to!double;
return val; return val;
} }
catch(Exception e)
{
return 0;//toriaezu
}
}
static double FLOOR(double val) static double FLOOR(double val)
{ {
return val.floor; return val.floor;
} }
static wstring MID(wstring str, int i, int len) static wstring MID(wstring str, int i, int len)
{ {
if(i + len > str.length)
{
return "";//範囲外で空文字
}
//挙動未定 //挙動未定
return str[i..i + len]; return str[i..i + len];
} }
//INSTRSUSBTLEFT
static wstring LEFT(wstring str, int len)
{
return str[0..len];
}
static wstring SUBST(wstring str, int i, Value alen, DefaultValue!(Value,false) areplace)
{
int len = 1;
wstring replace = "";
if(alen.isNumber)
{
len = alen.castInteger;
replace = areplace.castString;
}
else
{
replace = alen.castString;
//省略されたらi以降の全文字を置換
return str[0..i] ~ replace;
}
if(str.length <= i + len)
{
return str[0..i] ~ replace;
}
str.replaceInPlace(i, i + len, replace);
return str;
}
static int INSTR(Value vstart, Value vstr1, DefaultValue!(wstring, false) vstr2)
{
import std.string;
int start = 0;
wstring str1, str2;
if(!vstr2.isDefault)
{
start = vstart.castInteger;
str1 = vstr1.castString;
str2 = cast(wstring)vstr2;
}
else
{
str1 = vstart.castString;
str2 = vstr1.castString;
}
int aaa = str1[start..$].indexOf(str2, CaseSensitive.no);
return str1[start..$].indexOf(str2, CaseSensitive.no);
}
static int ASC(wstring str)
{
return cast(int)str[0];
}
static void SPSET(PetitComputer p, int id, int defno) static void SPSET(PetitComputer p, int id, int defno)
{ {
p.sprite.spset(id, defno); p.sprite.spset(id, defno);
@@ -241,7 +319,7 @@ class BuiltinFunction
} }
static void SPANIM(PetitComputer p, Value[] va_args) static void SPANIM(PetitComputer p, Value[] va_args)
{ {
writeln("NOTIMPL:SPANIM"); //TODO:配列
auto args = retro(va_args); auto args = retro(va_args);
int no = args[0].castInteger; int no = args[0].castInteger;
double[] animdata = new double[args.length - 2]; double[] animdata = new double[args.length - 2];
@@ -255,6 +333,79 @@ class BuiltinFunction
if(args[1].isNumber) if(args[1].isNumber)
p.sprite.spanim(no, cast(SpriteAnimTarget)(args[1].castInteger), animdata); p.sprite.spanim(no, cast(SpriteAnimTarget)(args[1].castInteger), animdata);
} }
static void SPDEF(PetitComputer p, Value[] va_args)
{
switch(va_args.length)
{
case 1://array
{
if(va_args[0].isNumberArray)
{
writeln("NOTIMPL:SPDEF ARRAY");
//return;
}
if(va_args[0].isString)
{
VM vm = p.vm;
vm.pushDataIndex();
vm.restoreData(va_args[0].castString);
auto count = vm.readData().castInteger;//読み込むスプライト数
int defno = 0;//?
for(int i = 0; i < count; i++)
{
int U = vm.readData().castInteger;
int V = vm.readData().castInteger;
int W = vm.readData().castInteger;
int H = vm.readData().castInteger;
int HX = vm.readData().castInteger;
int HY = vm.readData().castInteger;
int ATTR = vm.readData().castInteger;
p.sprite.SPDEFTable[defno] = SpriteDef(U, V, W, H, HX, HY, cast(SpriteAttr)ATTR);
defno++;
}
vm.popDataIndex();
return;
}
throw new IllegalFunctionCall("SPDEF");
return;
}
default:
}
{
int defno = va_args[0].castInteger;
int U = va_args[1].castInteger;
int V = va_args[2].castInteger;
int W = 16, H = 16, HX = 0, HY = 0, ATTR = 1;
if(va_args.length > 3)
{
W = va_args[3].castInteger;
}
if(va_args.length > 4)
{
H = va_args[4].castInteger;
}
if(va_args.length > 5)
{
HX = va_args[5].castInteger;
}
if(va_args.length > 6)
{
HY = va_args[6].castInteger;
}
if(va_args.length > 7)
{
ATTR = va_args[7].castInteger;
}
p.sprite.SPDEFTable[defno] = SpriteDef(U, V, W, H, HX, HY, cast(SpriteAttr)ATTR);
}
}
static void SPCLR(PetitComputer p, DefaultValue!(int, false) i)
{
if(i.isDefault)
p.sprite.spclr();
else
p.sprite.spclr(cast(int)i);
}
static void BGMSTOP(PetitComputer p) static void BGMSTOP(PetitComputer p)
{ {
writeln("NOTIMPL:BGMSTOP"); writeln("NOTIMPL:BGMSTOP");
@@ -341,6 +492,7 @@ class BuiltinFunction
{ {
return sqrt(a1); return sqrt(a1);
} }
//GalateaTalk利用面倒くさい...
static void TALK(wstring a1) static void TALK(wstring a1)
{ {
} }
@@ -365,6 +517,7 @@ class BuiltinFunction
mixin(AddFunc!(BuiltinFunction, name)), mixin(AddFunc!(BuiltinFunction, name)),
GetStartSkip!(BuiltinFunction, name), GetStartSkip!(BuiltinFunction, name),
IsVariadic!(BuiltinFunction, name), IsVariadic!(BuiltinFunction, name),
name,
); );
writeln(AddFunc!(BuiltinFunction, name)); writeln(AddFunc!(BuiltinFunction, name));
} }
@@ -384,6 +537,14 @@ template GetStartSkip(T, string N)
{ {
enum SkipSkip = I - is(P[0] : PetitComputer); enum SkipSkip = I - is(P[0] : PetitComputer);
} }
else static if(is(P[I] == DefaultValue!(wstring, false)))
{
enum SkipSkip = I - is(P[0] : PetitComputer);
}
else static if(is(P[I] == DefaultValue!(Value, false)))
{
enum SkipSkip = I - is(P[0] : PetitComputer);
}
else else
{ {
enum SkipSkip = SkipSkip!(I + 1, P); enum SkipSkip = SkipSkip!(I + 1, P);
@@ -419,7 +580,7 @@ template AddFunc(T, string N)
{ {
static if(is(ReturnType!(__traits(getMember, T, N)) == double) || is(ReturnType!(__traits(getMember, T, N)) == int)) static if(is(ReturnType!(__traits(getMember, T, N)) == double) || is(ReturnType!(__traits(getMember, T, N)) == int))
{ {
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~ const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ N ~ "\");}ret[0] = Value(" ~ N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}"; , ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
} }
@@ -427,13 +588,13 @@ template AddFunc(T, string N)
{ {
pragma(msg, GetArgumentCount!(T,N)); pragma(msg, GetArgumentCount!(T,N));
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){/*if(ret.length != 0){throw new IllegalFunctionCall();}*/" ~ OutArgsInit!(T,N) ~ N ~ "(" ~ const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){/*if(ret.length != 0){throw new IllegalFunctionCall(\"" ~ N ~ "\");}*/" ~ OutArgsInit!(T,N) ~ N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N, AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N,
ParameterTypeTuple!(__traits(getMember, T, N))) ~ ");}"; ParameterTypeTuple!(__traits(getMember, T, N))) ~ ");}";
} }
else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring)) else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring))
{ {
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~ const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ N ~ "\");}ret[0] = Value(" ~ N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}"; , ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
} }
@@ -471,6 +632,20 @@ DefaultValue!(wstring, false) fromStringToSkip(Value v)
else else
return DefaultValue!(wstring, false)(true); return DefaultValue!(wstring, false)(true);
} }
DefaultValue!Value fromValueToDefault(Value v)
{
if(v.type != ValueType.Void)
return DefaultValue!Value(v);
else
return DefaultValue!Value(true);
}
DefaultValue!(Value, false) fromValueToSkip(Value v)
{
if(v.type != ValueType.Void)
return DefaultValue!(Value, false)(v);
else
return DefaultValue!(Value, false)(true);
}
template GetFunctionParamType(T, string N) template GetFunctionParamType(T, string N)
{ {
enum GetFunctionParamType = mixin("[" ~ Array!(ParameterTypeTuple!(__traits(getMember, T, N))) ~ "]"); enum GetFunctionParamType = mixin("[" ~ Array!(ParameterTypeTuple!(__traits(getMember, T, N))) ~ "]");
@@ -515,6 +690,14 @@ template GetFunctionParamType(T, string N)
{ {
const string arg = ""; const string arg = "";
} }
else static if(is(P[0] == DefaultValue!(Value)) || is(P[0] == Value))
{
const string arg = "ValueType.Void, false";
}
else static if(is(P[0] == DefaultValue!(Value, false)))
{
const string arg = "ValueType.Void, true";
}
else static if(is(P[0] == PetitComputer)) else static if(is(P[0] == PetitComputer))
{ {
static if(P.length != 0) static if(P.length != 0)
@@ -602,10 +785,29 @@ template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
{ {
const string arg = "arg"; const string arg = "arg";
} }
else static if(is(P[0] == Value))
{
enum add = 1;
enum outadd = 0;
const string arg = "arg[" ~ I.to!string ~ "]";
}
else static if(is(P[0] == DefaultValue!Value))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromValueToDefault(arg[" ~ I.to!string ~ "])";
}
else static if(is(P[0] == DefaultValue!(Value, false)))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromValueToSkip(arg[" ~ I.to!string ~ "])";
}
else else
{ {
enum add = 1; enum add = 1;
enum outadd = 0; enum outadd = 0;
pragma(msg, P[0]);
static assert(false, "Invalid type"); static assert(false, "Invalid type");
const string arg = ""; const string arg = "";
} }

View File

@@ -1,11 +1,13 @@
module otya.smilebasic.error; module otya.smilebasic.error;
import std.exception; import std.exception;
import std.string; import std.string;
import std.conv;
class SmileBasicError : Exception class SmileBasicError : Exception
{ {
int errnum; int errnum;
int errline; int errline;
int errprg; int errprg;
string message2;
this(int slot, int line, string message) this(int slot, int line, string message)
{ {
super(format("%s in %d:%d", message, slot, line)); super(format("%s in %d:%d", message, slot, line));
@@ -18,6 +20,11 @@ class SmileBasicError : Exception
{ {
super(message); super(message);
} }
this(string message, string message2)
{
super(message);
this.message2 = message2;
}
} }
class SyntaxError : SmileBasicError class SyntaxError : SmileBasicError
{ {
@@ -26,13 +33,18 @@ class SyntaxError : SmileBasicError
this.errnum = 3; this.errnum = 3;
super("Syntax error"); super("Syntax error");
} }
this(wstring func)
{
this();
this.message2 = "Undefine function (" ~ func.to!string ~ ")";
}
} }
class IllegalFunctionCall : SmileBasicError class IllegalFunctionCall : SmileBasicError
{ {
this() this(string func)
{ {
this.errnum = 4; this.errnum = 4;
super("Illegal function call"); super("Illegal function call(" ~ func ~ ")");
} }
} }
class TypeMismatch : SmileBasicError class TypeMismatch : SmileBasicError

View File

@@ -142,7 +142,7 @@ class Lexical
wstring iden; wstring iden;
for(;i < code.length;i++) for(;i < code.length;i++)
{ {
c = code[i]; c = cast(wchar)code[i].toUpper;;
if(!c.isAlpha() && !c.isDigit() && c != '_') if(!c.isAlpha() && !c.isDigit() && c != '_')
{ {
break; break;

View File

@@ -11,6 +11,7 @@ import std.c.stdio;
import core.sync.mutex; import core.sync.mutex;
import otya.smilebasic.parser; import otya.smilebasic.parser;
import otya.smilebasic.sprite; import otya.smilebasic.sprite;
import otya.smilebasic.error;
enum Button enum Button
{ {
NONE = 0, NONE = 0,
@@ -89,7 +90,7 @@ class PetitComputer
{ {
this() this()
{ {
new Test(); //new Test();
} }
static const string resourceDirName = "resources"; static const string resourceDirName = "resources";
static const string resourcePath = "./resources"; static const string resourcePath = "./resources";
@@ -99,10 +100,16 @@ class PetitComputer
static const string fontTableFile = resourcePath ~ "/fonttable.txt"; static const string fontTableFile = resourcePath ~ "/fonttable.txt";
int screenWidth; int screenWidth;
int screenHeight; int screenHeight;
int screenWidthDisplay1;
int screenHeightDisplay1;
int fontWidth; int fontWidth;
int fontHeight; int fontHeight;
int consoleWidth; int consoleWidth;
int consoleHeight; int consoleHeight;
int consoleWidthDisplay1;
int consoleHeightDisplay1;
int consoleHeightC, consoleWidthC;
ConsoleCharacter[][] consoleC;
int[] consoleColor = int[] consoleColor =
[ [
0x00000000, 0x00000000,
@@ -141,6 +148,7 @@ class PetitComputer
} }
Button button; Button button;
ConsoleCharacter[][] console; ConsoleCharacter[][] console;
ConsoleCharacter[][] consoleDisplay1;
bool visibleGRP = true; bool visibleGRP = true;
int showGRP; int showGRP;
int useGRP; int useGRP;
@@ -426,17 +434,41 @@ class PetitComputer
writeln("OK"); writeln("OK");
screenWidth = 400; screenWidth = 400;
screenHeight = 240; screenHeight = 240;
screenWidthDisplay1 = 320;
screenHeightDisplay1 = 240;
fontWidth = 8; fontWidth = 8;
fontHeight = 8; fontHeight = 8;
consoleWidth = screenWidth / fontWidth; consoleWidth = screenWidth / fontWidth;
consoleHeight = screenHeight / fontHeight; consoleHeight = screenHeight / fontHeight;
consoleWidthDisplay1 = screenWidthDisplay1 / fontWidth;
consoleHeightDisplay1 = screenHeightDisplay1 / fontHeight;
console = new ConsoleCharacter[][consoleHeight]; console = new ConsoleCharacter[][consoleHeight];
consoleDisplay1 = new ConsoleCharacter[][consoleHeightDisplay1];
consoleForeColor = 15;//#T_WHITE consoleForeColor = 15;//#T_WHITE
for(int i = 0; i < console.length; i++) for(int i = 0; i < console.length; i++)
{ {
console[i] = new ConsoleCharacter[consoleWidth]; console[i] = new ConsoleCharacter[consoleWidth];
console[i][] = ConsoleCharacter(0, consoleForeColor, consoleBackColor); console[i][] = ConsoleCharacter(0, consoleForeColor, consoleBackColor);
} }
for(int i = 0; i < consoleDisplay1.length; i++)
{
consoleDisplay1[i] = new ConsoleCharacter[consoleWidthDisplay1];
consoleDisplay1[i][] = ConsoleCharacter(0, consoleForeColor, consoleBackColor);
}
display(0);
}
void display(int number)
{
if(number)
{
consoleHeightC = consoleHeightDisplay1;
consoleWidthC = consoleWidthDisplay1;
consoleC = consoleDisplay1;
return;
}
consoleHeightC = consoleHeight;
consoleWidthC = consoleWidth;
consoleC = console;
} }
void cls() void cls()
{ {
@@ -470,6 +502,7 @@ class PetitComputer
} }
Mutex grpmutex; Mutex grpmutex;
otya.smilebasic.draw.Draw draw; otya.smilebasic.draw.Draw draw;
bool displaynum;
void renderGraphic() void renderGraphic()
{ {
//grpmutex.lock(); //grpmutex.lock();
@@ -504,6 +537,24 @@ class PetitComputer
} }
Button[] buttonTable; Button[] buttonTable;
Sprite sprite; Sprite sprite;
int xscreenmode = 0;
void xscreen(int mode, int sprite, int bg)
{
int mode2 = mode / 2;
if(mode2 == 0)
{
SDL_SetWindowSize(window, 400, 240);
}
if(mode2 == 1)
{
SDL_SetWindowSize(window, 400, 480);
}
if(mode == 4)
{
SDL_SetWindowSize(window, 320, 240);
}
xscreenmode = mode2;
}
void render() void render()
{ {
buttonTable = new Button[SDL_SCANCODE_SLEEP + 1]; buttonTable = new Button[SDL_SCANCODE_SLEEP + 1];
@@ -512,7 +563,7 @@ class PetitComputer
buttonTable[SDL_SCANCODE_LEFT] = Button.LEFT; buttonTable[SDL_SCANCODE_LEFT] = Button.LEFT;
buttonTable[SDL_SCANCODE_RIGHT] = Button.RIGHT; buttonTable[SDL_SCANCODE_RIGHT] = Button.RIGHT;
buttonTable[SDL_SCANCODE_SPACE] = Button.A; buttonTable[SDL_SCANCODE_SPACE] = Button.A;
bool renderprofile = true; bool renderprofile;// = true;
try try
{ {
version(Windows) version(Windows)
@@ -570,10 +621,18 @@ class PetitComputer
loopcnt = 0; loopcnt = 0;
} }
} }
if(xscreenmode == 1)
{
glViewport(0, 240, 400, 240);
}
renderGraphic(); renderGraphic();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
renderGraphicPage(); renderGraphicPage();
renderConsoleGL(); renderConsoleGL();
if(xscreenmode == 1)
{
glViewport(0, 240, 400, 240);
}
sprite.render(); sprite.render();
/* if(this.sprite.sprites[0].define) /* if(this.sprite.sprites[0].define)
if(this.sprite.sprites[0].u == 0) if(this.sprite.sprites[0].u == 0)
@@ -653,6 +712,7 @@ class PetitComputer
} }
} }
SDL_Window* window; SDL_Window* window;
otya.smilebasic.vm.VM vm;
void run() void run()
{ {
init(); init();
@@ -675,11 +735,12 @@ class PetitComputer
//とりあえず //とりあえず
auto parser = new Parser( auto parser = new Parser(
//readText("./SYS/GAME6TALK.TXT").to!wstring //readText("./SYS/GAME6TALK.TXT").to!wstring
readText("./SYS/GAME2RPG.TXT").to!wstring
//readText("./SYS/GAME1DOTRC.TXT").to!wstring //readText("./SYS/GAME1DOTRC.TXT").to!wstring
//readText(input("LOAD PROGRAM:", true).to!string).to!wstring //readText(input("LOAD PROGRAM:", true).to!string).to!wstring
//readText("./SYS/EX1TEXT.TXT").to!wstring //readText("./SYS/EX1TEXT.TXT").to!wstring
//readText("FIZZBUZZ.TXT").to!wstring //readText("FIZZBUZZ.TXT").to!wstring
readText("TEST.TXT").to!wstring //readText("TEST.TXT").to!wstring
/*"?ABS(-1) /*"?ABS(-1)
LOCATE 0,10 LOCATE 0,10
COLOR 5 COLOR 5
@@ -722,6 +783,8 @@ class PetitComputer
auto vm = parser.compile(); auto vm = parser.compile();
bool running = true; bool running = true;
vm.init(this); vm.init(this);
vm.dump;
this.vm = vm;
//gpset(0, 10, 10, 0xFF00FF00); //gpset(0, 10, 10, 0xFF00FF00);
//gline(0, 0, 0, 399, 239, RGB(0, 255, 0)); //gline(0, 0, 0, 399, 239, RGB(0, 255, 0));
//gfill(0, 78, 78, 40, 40, RGB(0, 255, 255)); //gfill(0, 78, 78, 40, 40, RGB(0, 255, 255));
@@ -734,7 +797,11 @@ class PetitComputer
{ {
try try
{ {
if(!vsyncFrame && running) running = vm.runStep(); if(!vsyncFrame && running)
{
//writefln("%04X:%s", vm.pc, vm.getCurrent);
running = vm.runStep();
}
} }
catch(SmileBasicError sbe) catch(SmileBasicError sbe)
{ {
@@ -786,6 +853,8 @@ class PetitComputer
} }
wstring input(wstring prompt, bool useClipBoard) wstring input(wstring prompt, bool useClipBoard)
{ {
auto olddisplay = displaynum;
displaynum = 0;
printConsole(prompt); printConsole(prompt);
clearKeyBuffer(); clearKeyBuffer();
wstring buffer; wstring buffer;
@@ -836,6 +905,7 @@ class PetitComputer
} }
} }
showCursor = false; showCursor = false;
display = olddisplay;
return buffer; return buffer;
} }
int CSRX; int CSRX;
@@ -1028,6 +1098,55 @@ class PetitComputer
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0); glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
} }
glEnd(); glEnd();
if(xscreenmode != 1)
{
return;
}
//下画面
glViewport(40, 0, 400, 240);
glBindTexture(GL_TEXTURE_2D, GRPF.glTexture);
glDisable(GL_TEXTURE_2D);
glBegin(GL_QUADS);
for(int y = 0; y < consoleHeightDisplay1; y++)
for(int x = 0; x < consoleWidthDisplay1; x++)
{
auto back = consoleColorGL[consoleDisplay1[y][x].backColor];
glColor4ubv(cast(ubyte*)&back);
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0.9f);
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8) / 120f, 0.9f);
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8) / 120f, 0.9f);
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0.9f);
}
if(showCursor && animationCursor)
{
glColor4ubv(cast(ubyte*)&consoleColorGL[15]);
glVertex3f((CSRX * 8) / 200f - 1, 1 - (CSRY * 8 + 8) / 120f, -0.9f);
glVertex3f((CSRX * 8) / 200f - 1, 1 - (CSRY * 8) / 120f, -0.9f);
glVertex3f((CSRX * 8 + 2) / 200f - 1, 1 - (CSRY * 8) / 120f, -0.9f);
glVertex3f((CSRX * 8 + 2) / 200f - 1, 1 - (CSRY * 8 + 8) / 120f, -0.9f);
}
glEnd();
glEnable(GL_TEXTURE_2D);
//glAlphaFunc(GL_GEQUAL, 0.5);
//glEnable(GL_ALPHA_TEST);
glBegin(GL_QUADS);
for(int y = 0; y < consoleHeightDisplay1; y++)
for(int x = 0; x < consoleWidthDisplay1; x++)
{
auto fore = consoleColorGL[consoleDisplay1[y][x].foreColor];
auto rect = &fontTable[consoleDisplay1[y][x].character];
glColor4ubv(cast(ubyte*)&fore);
glTexCoord2f((rect.x) / 512f - 1 , (rect.y + 8) / 512f - 1);
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
glTexCoord2f((rect.x) / 512f - 1, (rect.y) / 512f - 1);
glVertex3f((x * 8) / 200f - 1, 1 - (y * 8) / 120f, 0);
glTexCoord2f((rect.x + 8) / 512f - 1, (rect.y) / 512f - 1);
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8) / 120f, 0);
glTexCoord2f((rect.x + 8) / 512f - 1, (rect.y +8) / 512f - 1);
glVertex3f((x * 8 + 8) / 200f - 1, 1 - (y * 8 + 8) / 120f, 0);
}
glEnd();
// glFlush(); // glFlush();
} }
void printConsole(T...)(T args) void printConsole(T...)(T args)
@@ -1039,115 +1158,39 @@ class PetitComputer
} }
void printConsoleString(wstring text) void printConsoleString(wstring text)
{ {
consolem.lock(); //consolem.lock();
scope(exit) consolem.unlock(); //scope(exit) consolem.unlock();
//write(text); //write(text);
foreach(wchar c; text) foreach(wchar c; text)
{ {
if(CSRY >= consoleHeight) if(CSRY >= consoleHeightC)
{ {
CSRY = consoleHeight - 1; CSRY = consoleHeightC - 1;
} }
if(c != '\r' && c != '\n') if(c != '\r' && c != '\n')
{ {
console[CSRY][CSRX].character = c; consoleC[CSRY][CSRX].character = c;
console[CSRY][CSRX].foreColor = consoleForeColor; consoleC[CSRY][CSRX].foreColor = consoleForeColor;
console[CSRY][CSRX].backColor = consoleBackColor; consoleC[CSRY][CSRX].backColor = consoleBackColor;
} }
CSRX++; CSRX++;
if(CSRX >= consoleWidth || c == '\n' || c == '\r') if(CSRX >= consoleWidthC || c == '\n' || c == '\r')
{ {
CSRX = 0; CSRX = 0;
CSRY++; CSRY++;
} }
if(CSRY >= consoleHeight) if(CSRY >= consoleHeightC)
{ {
auto tmp = console[0]; auto tmp = consoleC[0];
for(int i = 0; i < consoleHeight - 1; i++) for(int i = 0; i < consoleHeightC - 1; i++)
{ {
console[i] = console[i + 1]; consoleC[i] = consoleC[i + 1];
} }
console[consoleHeight - 1] = tmp; consoleC[consoleHeightC - 1] = tmp;
tmp[] = ConsoleCharacter(0, consoleForeColor, consoleBackColor); tmp[] = ConsoleCharacter(0, consoleForeColor, consoleBackColor);
//assert(console[0] != console[2]); //assert(console[0] != console[2]);
CSRY = consoleHeight - 1; CSRY = consoleHeightC - 1;
} }
} }
} }
} }
import std.typecons;
import std.typetuple;
import std.traits;
import otya.smilebasic.error;
import otya.smilebasic.type;
static string func;
class Test
{
import otya.smilebasic.type;
int a;/*
static Value abs(Value[] a)
{
return Value((a[0].castDouble < 0 ? -a[0].castDouble : a[0].castDouble));
}*/
static double ABS(double a)
{
return a < 0 ? -a : a;
}
wstring[] ah;
void*[] ahe;
alias void function(Value[], Value[]) BuiltinFunc;
BuiltinFunc[] builtinFunctions;
this()
{
foreach(name; __traits(derivedMembers, Test))
{
//writeln(name);
ah ~= name;
// foreach (t; __traits(getVirtualFunctions, Test, name))
{
static if(__traits(isStaticFunction, __traits(getMember, Test, name)))
{
ahe ~= cast(void*)&__traits(getMember, Test, name);
writeln(name);
auto m = typeid(typeof(__traits(getMember, Test, name)));
writeln(m);
writeln(AddFunc!(Test,name));
builtinFunctions ~= mixin(AddFunc!(Test,name));
}
}
}
}
}
template AddFunc(T, string N)
{
static if(is(ReturnType!(__traits(getMember, T, N)) == double))
{
const string AddFunc = "function void(Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~
AddFuncArg!(Tuple!(ParameterTypeTuple!(__traits(getMember, T, N))), 0) ~ "));}";
}
else
{
const string AddFunc = "";
}
}
template AddFuncArg(P, int N = 0)
{
static if(is(typeof(P[N]) == double))
{
const string arg = "arg[" ~ N.to!string ~ "].castDouble";
}
else
{
const string arg = "";
static assert(false, "Invalid type");
}
static if(N + 1 == P.length)
{
const string AddFuncArg = arg;
}
else
{
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(P, N + 1);
}
}

View File

@@ -5,6 +5,7 @@ import derelict.sdl2.sdl;
import derelict.opengl3.gl; import derelict.opengl3.gl;
enum SpriteAttr enum SpriteAttr
{ {
none = 0,
show = 0b00001, show = 0b00001,
rotate90 = 0b00010, rotate90 = 0b00010,
rotate180 = 0b00100, rotate180 = 0b00100,
@@ -113,7 +114,7 @@ struct SpriteAnimData
this.data.var = data[i++]; this.data.var = data[i++];
break; break;
default: default:
throw new IllegalFunctionCall(); throw new IllegalFunctionCall("SPANIM");
} }
return i; return i;
} }
@@ -179,6 +180,10 @@ struct SpriteData
this.anim[sat] = anim; this.anim[sat] = anim;
isAnim = true; isAnim = true;
} }
void clear()
{
this.define = false;
}
} }
struct SpriteDef struct SpriteDef
{ {
@@ -284,7 +289,6 @@ class Sprite
} }
if(sprite.attr & SpriteAttr.show) if(sprite.attr & SpriteAttr.show)
{ {
glLoadIdentity();
int x = cast(int)sprite.x - sprite.homex; int x = cast(int)sprite.x - sprite.homex;
int y = cast(int)sprite.y - sprite.homey; int y = cast(int)sprite.y - sprite.homey;
int w = sprite.w; int w = sprite.w;
@@ -327,6 +331,7 @@ class Sprite
glTexCoord2f(u2 / 512f - 1, v / 512f - 1); glTexCoord2f(u2 / 512f - 1, v / 512f - 1);
glVertex3f(sprite.w / 200f, 0, z);//4 glVertex3f(sprite.w / 200f, 0, z);//4
glEnd(); glEnd();
glLoadIdentity();
continue; continue;
} }
if((sprite.attr & SpriteAttr.rotate270) == SpriteAttr.rotate270) if((sprite.attr & SpriteAttr.rotate270) == SpriteAttr.rotate270)
@@ -340,6 +345,7 @@ class Sprite
glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1);//4 glTexCoord2f(u2 / 512f - 1, v2 / 512f - 1);//4
glVertex3f(w / 200f, 0, z);//4 glVertex3f(w / 200f, 0, z);//4
glEnd(); glEnd();
glLoadIdentity();
continue; continue;
} }
if((sprite.attr & SpriteAttr.rotate90) == SpriteAttr.rotate90) if((sprite.attr & SpriteAttr.rotate90) == SpriteAttr.rotate90)
@@ -353,6 +359,7 @@ class Sprite
glTexCoord2f(u / 512f - 1, v / 512f - 1);//1 glTexCoord2f(u / 512f - 1, v / 512f - 1);//1
glVertex3f(w / 200f, 0, z);//4 glVertex3f(w / 200f, 0, z);//4
glEnd(); glEnd();
glLoadIdentity();
continue; continue;
} }
if((sprite.attr & SpriteAttr.rotate180) == SpriteAttr.rotate180) if((sprite.attr & SpriteAttr.rotate180) == SpriteAttr.rotate180)
@@ -366,9 +373,11 @@ class Sprite
glTexCoord2f(u / 512f - 1 , v2 / 512f - 1);//2 glTexCoord2f(u / 512f - 1 , v2 / 512f - 1);//2
glVertex3f(w / 200f, 0, z);//4 glVertex3f(w / 200f, 0, z);//4
glEnd(); glEnd();
glLoadIdentity();
continue; continue;
} }
glEnd(); glEnd();
glLoadIdentity();
continue; continue;
} }
} }
@@ -430,4 +439,15 @@ class Sprite
} }
sprites[id].setAnimation(animdata, target); sprites[id].setAnimation(animdata, target);
} }
void spclr(int id)
{
sprites[id].clear;
}
void spclr()
{
for(int i = 0; i < sprites.length; i++)
{
spclr(i);
}
}
} }

View File

@@ -78,6 +78,10 @@ struct Value
return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray || return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray ||
this.type == ValueType.StringArray || this.type == ValueType.String; this.type == ValueType.StringArray || this.type == ValueType.String;
} }
bool isNumberArray()
{
return this.type == ValueType.IntegerArray || this.type == ValueType.DoubleArray;
}
bool isNumber() bool isNumber()
{ {
return this.type == ValueType.Integer || this.type == ValueType.Double; return this.type == ValueType.Integer || this.type == ValueType.Double;