1
0

SPLINK,SPOFS OUT実装,BuiltinFunctionクラスをオーバーロード対応にした

This commit is contained in:
otya128
2015-08-28 18:34:38 +09:00
parent f149ce596f
commit 61c1fd06f4
5 changed files with 515 additions and 113 deletions

View File

@@ -113,6 +113,15 @@ class VM
}
value = stack[--stacki];
}
void decSP()
{
if(stacki <= bp)
{
writeln("Stack underflow");
readln();
}
--stacki;
}
Value testGetGlobalVariable(wstring name)
{
return global[globalTable[name].index];
@@ -1391,3 +1400,10 @@ class PopSystemVariable : Code
return "popsysvar " ~ var.to!string;
}
}
class DecSP : Code
{
override void execute(VM vm)
{
vm.decSP;
}
}

View File

@@ -39,6 +39,10 @@ struct DefaultValue(T, bool skippable = true)
}
mixin Proxy!value;
}
struct StartOptional
{
const char[] name;
}
alias ValueType = otya.smilebasic.type.ValueType;
struct BuiltinFunctionArgument
{
@@ -46,23 +50,66 @@ struct BuiltinFunctionArgument
bool optionalArg;
bool skipArg;
}
//オーバーロード用
class BuiltinFunctions
{
private BuiltinFunction[] func;
this(BuiltinFunction f)
{
func = new BuiltinFunction[1];
func[0] = f;
}
void addFunction(BuiltinFunction func)
{
this.func ~= func;
}
BuiltinFunction overloadResolution(int argc, int outargc)
{
BuiltinFunction va;
//とりあえず引数の数で解決させる,というよりコンパイル時に型を取得する方法がない
foreach(f; func)
{
if(f.startskip <= argc && f.argments.length >= argc && f.outoptional <= outargc && f.results.length >= outargc)
return f;
if(f.variadic)
va = f;
}
//一応可変長は最後
if(va) return va;
writeln("====function overloads===");
foreach(f; func)
{
writefln("name=\"%s\", argments=%s, results = %s, variadic = %s, startoptional = %d, function pointer=%s", f.name, f.argments, f.results, f.variadic, f.startskip, f.func);
}
//引数数ちがうのは実行前にエラー
throw new IllegalFunctionCall(func[0].name);
}
}
alias DefaultValue!(int, false) optionalint;
alias DefaultValue!(int, false) optionaldouble;
alias DefaultValue!(int, false) optionalstring;
/**
ここに関数を定義すればコンパイル時にBuiltinFunctionに変換してくれる便利なクラス
*/
class BuiltinFunction
{
BuiltinFunctionArgument[] argments;
ValueType result;
BuiltinFunctionArgument[] results;
void function(PetitComputer, Value[], Value[]) func;
int startskip;
int outoptional;
bool variadic;
string name;
this(BuiltinFunctionArgument[] argments, ValueType result, void function(PetitComputer, Value[], Value[]) func, int startskip,
bool variadic, string name)
this(BuiltinFunctionArgument[] argments, BuiltinFunctionArgument[] results, void function(PetitComputer, Value[], Value[]) func, int startskip,
bool variadic, string name, int outoptional)
{
this.argments = argments;
this.result = result;
this.results = results;
this.func = func;
this.startskip = startskip;
this.variadic = variadic;
this.name = name;
this.outoptional = outoptional;
}
bool hasSkipArgument()
{
@@ -74,8 +121,16 @@ class BuiltinFunction
{
return a < 0 ? -a : a;
}*/
static double function(double) ABS = &abs!double;
static double function(double) SGN = &sgn!double;
//static double function(double) ABS = &abs!double;
//static double function(double) SGN = &sgn!double;
static double ABS(double arg1)
{
return abs(arg1);
}
static double SGN(double arg1)
{
return sgn(arg1);
}
static double SIN(double arg1)
{
return sin(arg1);
@@ -168,8 +223,12 @@ class BuiltinFunction
}
assert(cond, message.to!string);
}
static int BUTTON(PetitComputer p, DefaultValue!(int, false) mode)
static int BUTTON(PetitComputer p, DefaultValue!(int, false) mode, DefaultValue!(int, false) mp)
{
if(!mp.isDefault)
{
writeln("NOTIMPL:BUTTON(ID, MPID)");
}
return p.button;
}
static void VISIBLE(PetitComputer p, DefaultValue!(int) console, DefaultValue!(int) graphic, DefaultValue!(int) BG, DefaultValue!(int) sprite)
@@ -317,7 +376,11 @@ class BuiltinFunction
{
if(i + len > str.length)
{
return "";//範囲外で空文字
if(i >= str.length)
{
return "";//範囲外で空文字
}
return str[i..$];//iがまだ範囲内なら最後まで
}
//挙動未定
return str[i..i + len];
@@ -462,9 +525,21 @@ class BuiltinFunction
{
p.sprite.spshow(id);
}
static void SPOFS(PetitComputer p, int id, int x, int y, DefaultValue!(int, false) z)
static void SPOFS(PetitComputer p, int id, double x, double y, DefaultValue!(int, false) z)
{
p.sprite.spofs(id, x, y, cast(int)z);
if(z.isDefault)
{
p.sprite.spofs(id, x, y);
}
else
{
p.sprite.spofs(id, x, y, cast(int)z);
}
}
@StartOptional("z")
static void SPOFS(PetitComputer p, int id, out double x, out double y, out int z)
{
p.sprite.getspofs(id, x, y, z);
}
static void SPANIM(PetitComputer p, Value[] va_args)
{
@@ -573,6 +648,14 @@ class BuiltinFunction
{
p.sprite.spcolor(id, cast(uint)color);
}
static void SPLINK(PetitComputer p, int child, int parent)
{
p.sprite.splink(child, parent);
}
static void SPUNLINK(PetitComputer p, int id)
{
p.sprite.spunlink(id);
}
static void BGMSTOP(PetitComputer p)
{
writeln("NOTIMPL:BGMSTOP");
@@ -756,7 +839,7 @@ class BuiltinFunction
throw new IllegalFunctionCall("COPY (Not implemented error)");
}
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
static BuiltinFunction[wstring] builtinFunctions;
static BuiltinFunctions[wstring] builtinFunctions;
static this()
{
foreach(name; __traits(derivedMembers, BuiltinFunction))
@@ -764,27 +847,74 @@ class BuiltinFunction
//writeln(name);
static if(/*__traits(isStaticFunction, __traits(getMember, BuiltinFunction, name)) && */name[0].isUpper)
{
//pragma(msg, AddFunc!(BuiltinFunction, name));
wstring suffix = "";
if(is(ReturnType!(__traits(getMember, BuiltinFunction, name)) == wstring))
foreach(i, F; __traits(getOverloads, BuiltinFunction, name))
{
suffix = "$";
//pragma(msg, AddFunc!(BuiltinFunction, name));
wstring suffix = "";
if(is(ReturnType!(__traits(getMember, BuiltinFunction, name)) == wstring))
{
suffix = "$";
}
wstring name2 = name ~ suffix;
auto func = builtinFunctions.get(name2, null);
alias BFD = BuiltinFunctionData!(BuiltinFunction, name, i);
pragma(msg, AddFunc!BFD);
auto f = new BuiltinFunction(
GetFunctionParamType!(BFD),
GetFunctionReturnType!(BFD),
mixin(AddFunc!(BFD)),
GetStartSkip!(BFD),
IsVariadic!(BFD),
name,
GetOutStartSkip!(BFD)
);
if(func)
{
builtinFunctions[name2].addFunction(f);
}
else
{
builtinFunctions[name2] = new BuiltinFunctions(f);
}
//writeln(AddFunc!(BuiltinFunction, name));
}
builtinFunctions[name ~ suffix] = new BuiltinFunction(
GetFunctionParamType!(BuiltinFunction, name),
GetFunctionReturnType!(BuiltinFunction, name),
mixin(AddFunc!(BuiltinFunction, name)),
GetStartSkip!(BuiltinFunction, name),
IsVariadic!(BuiltinFunction, name),
name,
);
//writeln(AddFunc!(BuiltinFunction, name));
}
}
}
}
template GetStartSkip(T, string N)
template GetOutStartSkip(BFD)
{
static if(__traits(getAttributes, __traits(getOverloads, BFD.C_, BFD.N)[BFD.I_]).length == 1 &&
is(typeof(__traits(getAttributes, __traits(getOverloads, BFD.C_, BFD.N)[BFD.I_])[0]) == StartOptional))
{
enum so = __traits(getAttributes, __traits(getOverloads, BFD.C_, BFD.N)[BFD.I_])[0];
int GetOutStartSkip()
{
int k;
foreach (j, i; ParameterIdentifierTuple!(__traits(getOverloads, BFD.C_, BFD.N)[BFD.I_]))
{
if(i == so.name)
{
return k;
}
else if(BFD.ParameterStorageClass[j] & ParameterStorageClass.out_)
{
k++;
}
}
return 0;
}
}
else
{
int GetOutStartSkip()
{
return 0;
}
}
}
template GetStartSkip(BFD)
{
private template SkipSkip(int I, P...)
{
@@ -792,10 +922,18 @@ template GetStartSkip(T, string N)
{
enum SkipSkip = I - is(P[0] == PetitComputer);
}
else static if(BFD.ParameterStorageClass[I] & ParameterStorageClass.out_)
{
enum SkipSkip = I - is(P[0] : PetitComputer);
}
else static if(is(P[I] == DefaultValue!(int, false)))
{
enum SkipSkip = I - is(P[0] : PetitComputer);
}
else static if(is(P[I] == DefaultValue!(double, false)))
{
enum SkipSkip = I - is(P[0] : PetitComputer);
}
else static if(is(P[I] == DefaultValue!(wstring, false)))
{
enum SkipSkip = I - is(P[0] : PetitComputer);
@@ -809,52 +947,170 @@ template GetStartSkip(T, string N)
enum SkipSkip = SkipSkip!(I + 1, P);
}
}
enum GetStartSkip = SkipSkip!(0, ParameterTypeTuple!(__traits(getMember, T, N)));
enum GetStartSkip = SkipSkip!(0, BFD.ParameterType);
}
template GetFunctionReturnType(T, string N)
template GetBuiltinFunctionArgment(P...)
{
static if(is(ReturnType!(__traits(getMember, T, N)) == double))
static if(is(P[0] == double))
{
enum GetFunctionReturnType = ValueType.Double;
const string arg = "ValueType.Double, false";
}
else static if(is(ReturnType!(__traits(getMember, T, N)) == int))
else static if(is(P[0] == int))
{
enum GetFunctionReturnType = ValueType.Integer;
const string arg = "ValueType.Integer, false";
}
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
else static if(is(P[0] == wstring))
{
enum GetFunctionReturnType = ValueType.Void;
const string arg = "ValueType.String, false";
}
else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring))
else static if(is(P[0] == DefaultValue!int))
{
enum GetFunctionReturnType = ValueType.String;
const string arg = "ValueType.Integer, true";
}
else static if(is(P[0] == DefaultValue!(int, false)))
{
const string arg = "ValueType.Integer, true";
}
else static if(is(P[0] == OptionalOutValue!int))
{
const string arg = "ValueType.Integer, true";
}
else static if(is(P[0] == DefaultValue!double))
{
const string arg = "ValueType.Double, true";
}
else static if(is(P[0] == DefaultValue!(double, false)))
{
const string arg = "ValueType.Double, true";
}
else static if(is(P[0] == DefaultValue!(wstring)))
{
const string arg = "ValueType.String, false";
}
else static if(is(P[0] == DefaultValue!(wstring, false)))
{
const string arg = "ValueType.String, true";
}
else static if(is(P[0] == Value[]))
{
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] == void))
{
const string arg = "";
}
else
{
enum GetFunctionReturnType = ValueType.Void;
static assert(false, "Invalid type");
}
}
template AddFunc(T, string N)
{
static if(is(ReturnType!(__traits(getMember, T, N)) == double) || is(ReturnType!(__traits(getMember, T, N)) == int))
static if(is(P[0] == void))
{
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
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
enum GetBuiltinFunctionArgment = "";
}
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
else
{
enum GetBuiltinFunctionArgment = "BuiltinFunctionArgument(" ~ arg ~ ")";
}
}
template BuiltinFunctionData(C, string NAME, int I)
{
//struct BuiltinFunctionData
//{
//enum P = ParameterStorageClassTuple!(__traits(getOverloads, C, N)[I]);
struct BuiltinFunctionData
{
alias P = std.traits.ParameterStorageClassTuple!(__traits(getOverloads, C, NAME)[I]);
alias T = std.traits.ParameterTypeTuple!(__traits(getOverloads, C, NAME)[I]);
alias R = std.traits.ReturnType!(__traits(getOverloads, C, NAME)[I]);
alias ParameterStorageClass = std.traits.ParameterStorageClassTuple!(__traits(getOverloads, C, NAME)[I]);
alias ParameterType = std.traits.ParameterTypeTuple!(__traits(getOverloads, C, NAME)[I]);
alias ReturnType = std.traits.ReturnType!(__traits(getOverloads, C, NAME)[I]);
enum F = &__traits(getOverloads, C, NAME)[I];
alias N = NAME;
alias C_ = C;
alias I_ = I;
}
}
template GetOutArgment(C, string N)
{
alias T = ParameterTypeTuple!(__traits(getMember, C, N));
string GetOutArgment2()
{
string arg = "";
foreach(i, J; T)
{
enum P = ParameterStorageClassTuple!(__traits(getMember, C, N))[i];
static if(P & ParameterStorageClass.out_)
{
arg ~= GetBuiltinFunctionArgment!(J) ~ ",";
}
}
return arg;
}
enum GetOutArgment = GetOutArgment2();
}
template GetOutArgment2(BFD)
{
alias T = BFD.T;
string GetOutArgment22()
{
string arg = "";
foreach(i, J; T)
{
//enum P = ParameterStorageClassTuple!(__traits(getMember, C, N))[i];
static if(BFD.P[i] & ParameterStorageClass.out_)
{
arg ~= GetBuiltinFunctionArgment!(J) ~ ",";
}
}
return arg;
}
enum GetOutArgment2 = GetOutArgment22();
}
//template GetOutArgment2(T2)
//{
//}
template GetFunctionReturnType(BFD)
{
static if(is(BFD.R == void))
{
enum GetFunctionReturnType =
mixin("[" ~ GetOutArgment2!(BFD) ~ "]");
}
else
{
enum GetFunctionReturnType =
mixin("[" ~ GetBuiltinFunctionArgment!(BFD.R) ~ "]");
}
}
template AddFunc(BFD)
{
static if(is(BFD.ReturnType == double) || is(BFD.ReturnType == int))
{
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ BFD.N ~ "\");}ret[0] = Value(" ~ BFD.N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(BFD) - 1, 0, 0, 0, BFD,
BFD.ParameterType) ~ "));}";
}
else static if(is(BFD.ReturnType == void))
{
//pragma(msg, GetArgumentCount!(T,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,
ParameterTypeTuple!(__traits(getMember, T, N))) ~ ");}";
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){/*if(ret.length != 0){throw new IllegalFunctionCall(\"" ~ BFD.N ~ "\");}*/" ~ OutArgsInit!(BFD) ~ BFD.N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(BFD) - 1, 0, 0, 0, BFD,
BFD.ParameterType) ~ ");}";
}
else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring))
else static if(is(BFD.ReturnType == wstring))
{
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
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ BFD.N ~ "\");}ret[0] = Value(" ~ BFD.N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(BFD) - 1, 0, 0, 0, BFD,
BFD.ParameterType) ~ "));}";
}
else
{
@@ -918,16 +1174,27 @@ DefaultValue!(Value, false) fromValueToSkip(Value v)
else
return DefaultValue!(Value, false)(true);
}
template GetFunctionParamType(T, string N)
template GetFunctionParamType(BFD)
{
enum GetFunctionParamType = mixin("[" ~ Array!(ParameterTypeTuple!(__traits(getMember, T, N))) ~ "]");
private template Array(P...)
enum GetFunctionParamType = mixin("[" ~ Array!(0, BFD.T) ~ "]");
private template Array(int I, P...)
{
static if(P.length == 0)
{
const string arg = "";
enum Array = "";
}
else static if(BFD.ParameterStorageClass[I] & ParameterStorageClass.out_)
{
static if(1 == P.length && !is(P[0] == PetitComputer))
{
enum Array = "";
}
else static if(!is(P[0] == PetitComputer))
{
enum Array = Array!(I + 1, P[1..$]);
}
}
else
{
static if(is(P[0] == double))
@@ -982,7 +1249,7 @@ template GetFunctionParamType(T, string N)
{
static if(P.length != 0)
{
enum Array = Array!(P[1..$]);
enum Array = Array!(I + 1, P[1..$]);
}
else
{
@@ -995,26 +1262,35 @@ template GetFunctionParamType(T, string N)
}
else static if(!is(P[0] == PetitComputer))
{
enum Array = "BuiltinFunctionArgument(" ~ arg ~ ")," ~ Array!(P[1..$]);
enum Array = "BuiltinFunctionArgument(" ~ arg ~ ")," ~ Array!(I + 1, P[1..$]);
}
}
}
}
template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
template AddFuncArg(int L, int N, int M, int O, BFD, P...)
{
enum I = L - N;
static if(ParameterStorageClassTuple!(__traits(getMember, T, NAME)).length <= M)
static if(BFD.ParameterStorageClass.length <= M)
{
const string AddFuncArg = "";
}
else
{
enum storage = ParameterStorageClassTuple!(__traits(getMember, T, NAME))[M];
enum storage = BFD.ParameterStorageClass[M];
static if(is(P[0] == double))
{
enum add = 1;
enum outadd = 0;
const string arg = "arg[" ~ I.to!string ~ "].castDouble";
static if(storage & ParameterStorageClass.out_)
{
enum add = 0;
enum outadd = 1;
const string arg = "ret[" ~ O.to!string ~ "].doubleValue";
}
else
{
enum add = 1;
enum outadd = 0;
const string arg = "arg[" ~ I.to!string ~ "].castDouble";
}
}
else static if(is(P[0] == PetitComputer))
{
@@ -1045,9 +1321,18 @@ template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
}
else static if(is(P[0] == DefaultValue!int))
{
enum add = 1;
enum outadd = 0;
const string arg = "fromIntToDefault(arg[" ~ I.to!string ~ "])";
static if(storage & ParameterStorageClass.out_)
{
enum add = 0;
enum outadd = 1;
const string arg = "ret[" ~ O.to!string ~ "].integerValue";
}
else
{
enum add = 1;
enum outadd = 0;
const string arg = "fromIntToDefault(arg[" ~ I.to!string ~ "])";
}
}
else static if(is(P[0] == DefaultValue!(int, false)))
{
@@ -1059,7 +1344,7 @@ template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
{
enum add = 1;
enum outadd = 0;
const string arg = "fromIntDoubleToDefault(arg[" ~ I.to!string ~ "])";
const string arg = "fromDoubleToDefault(arg[" ~ I.to!string ~ "])";
}
else static if(is(P[0] == DefaultValue!(double, false)))
{
@@ -1115,20 +1400,20 @@ template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
}
else
{
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(L - !add, N + add, M + 1, O + outadd, T, NAME, P[1..$]);
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(L - !add, N + add, M + 1, O + outadd, BFD, P[1..$]);
}
}
}
template OutArgsInit(T, string N, int I = 0, int J = 0)
template OutArgsInit(BFD, int I = 0, int J = 0)
{
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
alias param = BFD.ParameterType;
static if(!param.length)
{
enum OutArgsInit = "";
}
else
{
enum tuple = ParameterStorageClassTuple!(__traits(getMember, T, N))[I];
enum tuple = BFD.ParameterStorageClass[I];
static if(tuple & ParameterStorageClass.out_)
{
enum add = 1;
@@ -1137,6 +1422,26 @@ template OutArgsInit(T, string N, int I = 0, int J = 0)
{
enum ret2 = "ValueType.Integer;";
}
else static if(is(param[I] == DefaultValue!int))
{
enum ret2 = "ValueType.Integer;";
}
//else static if(is(param[I] == OptionalOutValue!int))
//{
// enum ret2 = "ValueType.Integer;";
//}
else static if(is(param[I] == double))
{
enum ret2 = "ValueType.Double;";
}
else static if(is(param[I] == Value[]))
{
enum ret2 = "ValueType.Void;";
}
else
{
static assert(false, "invalid type " ~ param[I].stringof);
}
enum result = ret1 ~ ret2;
}
else
@@ -1146,7 +1451,7 @@ template OutArgsInit(T, string N, int I = 0, int J = 0)
}
static if(param.length > I + 1)
{
enum OutArgsInit = result ~ OutArgsInit!(T, N, I + 1, J + add);
enum OutArgsInit = result ~ OutArgsInit!(BFD, I + 1, J + add);
}
else
{
@@ -1154,16 +1459,16 @@ template OutArgsInit(T, string N, int I = 0, int J = 0)
}
}
}
template GetArgumentCount(T, string N, int I = 0)
template GetArgumentCount(BFD, int I = 0)
{
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
alias param = BFD.ParameterType;
static if(param.length <= I)
{
enum GetArgumentCount = 0;
}
else
{
enum tuple = ParameterStorageClassTuple!(__traits(getMember, T, N))[I];
enum tuple = BFD.ParameterStorageClass[I];
static if(is(param[I] == PetitComputer))
{
enum add = 0 + 1;
@@ -1181,7 +1486,7 @@ template GetArgumentCount(T, string N, int I = 0)
}
static if(param.length > I + 1)
{
enum GetArgumentCount = add + GetArgumentCount!(T, N, I + 1);
enum GetArgumentCount = add + GetArgumentCount!(BFD, I + 1);
}
else
{
@@ -1189,9 +1494,9 @@ template GetArgumentCount(T, string N, int I = 0)
}
}
}
template IsVariadic(T, string N, int I = 0)
template IsVariadic(BFD, int I = 0)
{
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
alias param = BFD.ParameterType;
static if(param.length == 0 || param.length <= I)
{
enum IsVariadic = false;
@@ -1202,7 +1507,7 @@ template IsVariadic(T, string N, int I = 0)
}
else
{
enum IsVariadic = IsVariadic!(T, N, I + 1);
enum IsVariadic = IsVariadic!(BFD, I + 1);
}
}

View File

@@ -416,9 +416,11 @@ class Compiler
case NodeType.CallFunction:
{
auto func = cast(CallFunction)exp;
auto bfun = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
if(bfun)
auto bfuns = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
otya.smilebasic.builtinfunctions.BuiltinFunction bfun;
if(bfuns)
{
bfun = bfuns.overloadResolution(func.args.length, 1);
if(bfun.argments.length >= func.args.length)
{
auto k = bfun.argments.length - func.args.length;
@@ -808,9 +810,11 @@ class Compiler
case NodeType.CallFunctionStatement:
{
auto func = cast(CallFunctionStatement)i;
auto bfun = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
if(bfun)
auto bfuns = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
otya.smilebasic.builtinfunctions.BuiltinFunction bfun;
if(bfuns)
{
bfun = bfuns.overloadResolution(func.args.length, func.outVariable.length);
int k = cast(int)bfun.argments.length - cast(int)func.args.length;
foreach(l;0..k)
{
@@ -823,13 +827,21 @@ class Compiler
}
if(bfun)
{
genCode(new CallBuiltinFunction(bfun, cast(int)func.args.length, cast(int)func.outVariable.length));
genCode(new CallBuiltinFunction(bfun, cast(int)func.args.length, cast(int)bfun.results.length));//func.outVariable.length));
}
else
{
writeln(func.name);
genCode(new CallFunctionCode(func.name, cast(int)func.args.length, cast(int)func.outVariable.length));
}
if(bfun)
{
int k = cast(int)bfun.results.length - cast(int)func.outVariable.length;
foreach(l;0..k)
{
genCode(new DecSP);
}
}
//TODO:OUT
foreach_reverse(wstring var; func.outVariable)
{

View File

@@ -644,6 +644,7 @@ class PetitComputer
DrawType dt;
auto start = SDL_GetTicks();
int i = s;
static const size = 255.5f;
for(; i < len; i++)
{
DrawMessage dm = drawMessageQueue[i];
@@ -657,7 +658,7 @@ class PetitComputer
case DrawType.PSET:
glBegin(GL_POINTS);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f((dm.x) / 256f - 1, (dm.y) / 256f - 1);
glVertex2f((dm.x) / size - 1, (dm.y) / size - 1);
glEnd();
//draw.gpset(dm.page, dm.x, dm.y ,dm.color);
break;
@@ -665,8 +666,8 @@ class PetitComputer
{
glBegin(GL_LINES);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f((dm.x) / 256f - 1, (dm.y) / 256f - 1);
glVertex2f((dm.x2) / 256f - 1, (dm.y2) / 256f - 1);
glVertex2f((dm.x) / size - 1, (dm.y) / size - 1);
glVertex2f((dm.x2) / size - 1, (dm.y2) / size - 1);
//glFlush();
glEnd();
}
@@ -676,10 +677,10 @@ class PetitComputer
{
glBegin(GL_QUADS);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f((dm.x) / 256f - 1, (dm.y) / 256f - 1);
glVertex2f((dm.x) / 256f - 1, (dm.y2 + 1) / 256f - 1);
glVertex2f((dm.x2 + 1) / 256f - 1, (dm.y2 + 1) / 256f - 1);
glVertex2f((dm.x2 + 1) / 256f - 1, (dm.y) / 256f - 1);
glVertex2f((dm.x) / size - 1, (dm.y) / size - 1);
glVertex2f((dm.x) / size - 1, (dm.y2 + 1) / size - 1);
glVertex2f((dm.x2 + 1) / size - 1, (dm.y2 + 1) / size - 1);
glVertex2f((dm.x2 + 1) / size - 1, (dm.y) / size - 1);
glEnd();
}
//draw.gfill(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
@@ -688,10 +689,10 @@ class PetitComputer
{
glBegin(GL_LINE_LOOP);
glColor4ubv(cast(ubyte*)&dm.color);
glVertex2f((dm.x) / 256f - 1, (dm.y) / 256f - 1);
glVertex2f((dm.x) / 256f - 1, (dm.y2) / 256f - 1);
glVertex2f((dm.x2) / 256f - 1, (dm.y2) / 256f - 1);
glVertex2f((dm.x2) / 256f - 1, (dm.y) / 256f - 1);
glVertex2f((dm.x) / size - 1, (dm.y) / size - 1);
glVertex2f((dm.x) / size - 1, (dm.y2) / size - 1);
glVertex2f((dm.x2) / size - 1, (dm.y2) / size - 1);
glVertex2f((dm.x2) / size - 1, (dm.y) / size - 1);
glEnd();
}
//draw.gbox(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
@@ -1041,6 +1042,8 @@ class PetitComputer
while(!buttonTable){}
auto startTicks = SDL_GetTicks();
Parser parser;
otya.smilebasic.vm.VM vm;
bool running;
//デバッグ用
version(NDirectMode)
{
@@ -1093,6 +1096,24 @@ class PetitComputer
CL=(CL+1) MOD 16 : VSYNC 1
GOTO @LOOP`*/
);
try
{
vm = parser.compile();
vm.init(this);
running = true;
}
catch(SmileBasicError sbe)
{
printConsole(sbe.getErrorMessage, "\n");
printConsole(sbe.getErrorMessage2, "\n");
//printConsole(sbe.to!string);
writeln(sbe.to!string);
writeln(sbe.getErrorMessage2);
}
catch(Throwable t)
{
writeln(t);
}
}
else
{
@@ -1109,13 +1130,30 @@ class PetitComputer
printConsole("can't open program \"", file, "\".\n");
continue;
}
try
{
vm = parser.compile();
vm.init(this);
running = true;
}
catch(SmileBasicError sbe)
{
printConsole(sbe.getErrorMessage, "\n");
printConsole(sbe.getErrorMessage2, "\n");
//printConsole(sbe.to!string);
writeln(sbe.to!string);
writeln(sbe.getErrorMessage2);
continue;
}
catch(Throwable t)
{
writeln(t);
continue;
}
break;
} while(!quit);
}
if(quit) return;
auto vm = parser.compile();
bool running = true;
vm.init(this);
//vm.dump;
this.vm = vm;
bg[0].put(0,0,1);

View File

@@ -239,18 +239,11 @@ struct SpriteData
this.homey = s.hy;
this.attr = s.a;
}
double debugZ()
{
import std.stdio;
// writefln("sprite=%d, z=%f", id, z);
return z;
}
int opCmp(ref SpriteData spr)
{
import std.stdio;
writeln("WHAT!????");
return 0;
}
//SPLINK用
SpriteData* parent;
//SPLINKの親は子より小さい管理番号でしかなれないのでsprite->child->nextのX座標を加算すればなんとかなる
//->挙動的に違う
int linkx, linky;
}
class Sprite
{
@@ -520,8 +513,19 @@ class Sprite
}
if(sprite.attr & SpriteAttr.show)
{
int x = cast(int)sprite.x;// - cast(int)(sprite.homex * sprite.scalex);
int y = cast(int)sprite.y;// - cast(int)(sprite.homey * sprite.scaley);
int x, y;
if(sprite.parent)
{
x += cast(int)(sprite.x + sprite.parent.linkx);
y += cast(int)(sprite.y + sprite.parent.linky);
}
else
{
x = cast(int)sprite.x;// - cast(int)(sprite.homex * sprite.scalex);
y = cast(int)sprite.y;// - cast(int)(sprite.homey * sprite.scaley);
}
sprite.linkx = x;
sprite.linky = y;
auto homex2 = ((sprite.w / 2 ) - sprite.homex) / disw;
auto homey2 = ((sprite.h / 2 ) - sprite.homey) / dish;
int w = sprite.w;
@@ -652,13 +656,13 @@ class Sprite
auto spdef = SpriteDef(u, v, w, h, 0, 0, attr);
sprites[id] = SpriteData(id, spdef, 0/*要調査*/);
}
void spofs(int id, int x, int y)
void spofs(int id, double x, double y)
{
id = spid(id);
sprites[id].x = x;
sprites[id].y = y;
}
void spofs(int id, int x, int y, int z)
void spofs(int id, double x, double y, int z)
{
id = spid(id);
sprites[id].x = x;
@@ -666,6 +670,13 @@ class Sprite
sprites[id].z = z;
zChange = true;
}
void getspofs(int id, out double x, out double y, out int z)
{
id = spid(id);
x = sprites[id].x;
y = sprites[id].y;
z = sprites[id].z;
}
void sphide(int id)
{
id = spid(id);
@@ -762,4 +773,24 @@ class Sprite
id = spid(id);
sprites[id].color = petitcom.toGLColor(color);
}
void splink(int child, int parent)
{
if(parent >= child)
{
throw new IllegalFunctionCall("SPLINK");
}
parent = spid(parent);
child = spid(child);
//SPLINK 2,0
//SPLINK 2,1した時の挙動謎
//最後にSPSETした親が優先される->子が親を保持?
sprites[child].parent = &sprites[parent];
}
//再帰的にUNLINKされるのか
void spunlink(int id)
{
id = spid(id);
//parent==nullでもエラーでない
sprites[id].parent = null;
}
}