builtinfunction.dが追加されていなかったので追加
This commit is contained in:
@@ -853,3 +853,22 @@ class CallFunctionCode : Code
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
import otya.smilebasic.builtinfunctions;
|
||||||
|
class CallBuiltinFunction : Code
|
||||||
|
{
|
||||||
|
BuiltinFunction func;
|
||||||
|
int argcount;
|
||||||
|
int outcount;
|
||||||
|
this(BuiltinFunction func, int argcount, int outcount/+可変長引数用+/)
|
||||||
|
{
|
||||||
|
this.func = func;
|
||||||
|
this.argcount = argcount;
|
||||||
|
this.outcount = outcount;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
Value[] arg = vm.stack[vm.stacki - argcount..vm.stacki - 1];
|
||||||
|
Value[] result = vm.stack[vm.stacki - argcount..vm.stacki - argcount + outcount - 1];//雑;
|
||||||
|
func.func(vm.petitcomputer, arg, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
189
SMILEBASIC/builtinfunctions.d
Normal file
189
SMILEBASIC/builtinfunctions.d
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
module otya.smilebasic.builtinfunctions;
|
||||||
|
|
||||||
|
import std.conv;
|
||||||
|
import std.typecons;
|
||||||
|
import std.typetuple;
|
||||||
|
import std.traits;
|
||||||
|
import std.stdio;
|
||||||
|
import std.ascii;
|
||||||
|
import otya.smilebasic.error;
|
||||||
|
import otya.smilebasic.type;
|
||||||
|
import otya.smilebasic.petitcomputer;
|
||||||
|
//プチコンの引数省略は特殊なので
|
||||||
|
//LOCATE ,,0のように省略できる
|
||||||
|
struct DefaultValue(T)
|
||||||
|
{
|
||||||
|
T value;
|
||||||
|
bool isDefault;
|
||||||
|
this(int v, bool f)
|
||||||
|
{
|
||||||
|
value = v;
|
||||||
|
isDefault = f;
|
||||||
|
}
|
||||||
|
this(int v)
|
||||||
|
{
|
||||||
|
value = v;
|
||||||
|
isDefault = false;
|
||||||
|
}
|
||||||
|
this(bool f)
|
||||||
|
{
|
||||||
|
isDefault = f;
|
||||||
|
}
|
||||||
|
mixin Proxy!value;
|
||||||
|
}
|
||||||
|
alias ValueType = otya.smilebasic.type.ValueType;
|
||||||
|
struct BuiltinFunctionArgument
|
||||||
|
{
|
||||||
|
ValueType argType;
|
||||||
|
bool optionalArg;
|
||||||
|
}
|
||||||
|
class BuiltinFunction
|
||||||
|
{
|
||||||
|
BuiltinFunctionArgument[] argments;
|
||||||
|
ValueType result;
|
||||||
|
void function(PetitComputer, Value[], Value[]) func;
|
||||||
|
this(BuiltinFunctionArgument[] argments, ValueType result, void function(PetitComputer, Value[], Value[]) func)
|
||||||
|
{
|
||||||
|
this.argments = argments;
|
||||||
|
this.result = result;
|
||||||
|
this.func = func;
|
||||||
|
}
|
||||||
|
import std.math;
|
||||||
|
/*
|
||||||
|
static pure double ABS(double a, double b)
|
||||||
|
{
|
||||||
|
return a < 0 ? -a : a;
|
||||||
|
}*/
|
||||||
|
static ABS = function(double x) => abs(x);
|
||||||
|
static void LOCATE(PetitComputer p, DefaultValue!int x, DefaultValue!int y, DefaultValue!int z)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
|
||||||
|
static BuiltinFunction[wstring] builtinFunctions;
|
||||||
|
static this()
|
||||||
|
{
|
||||||
|
foreach(name; __traits(derivedMembers, BuiltinFunction))
|
||||||
|
{
|
||||||
|
writeln(name);
|
||||||
|
static if(/*__traits(isStaticFunction, __traits(getMember, BuiltinFunction, name)) && */name[0].isUpper)
|
||||||
|
{
|
||||||
|
builtinFunctions[name] = new BuiltinFunction(
|
||||||
|
GetFunctionParamType!(BuiltinFunction, name),
|
||||||
|
GetFunctionReturnType!(BuiltinFunction, name),
|
||||||
|
mixin(AddFunc!(BuiltinFunction, name))
|
||||||
|
);
|
||||||
|
writeln(AddFunc!(BuiltinFunction, name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
template GetFunctionReturnType(T, string N)
|
||||||
|
{
|
||||||
|
static if(is(ReturnType!(__traits(getMember, T, N)) == double))
|
||||||
|
{
|
||||||
|
enum GetFunctionReturnType = ValueType.Double;
|
||||||
|
}
|
||||||
|
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
|
||||||
|
{
|
||||||
|
enum GetFunctionReturnType = ValueType.Void;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum GetFunctionReturnType = ValueType.Void;
|
||||||
|
static assert(false, "Invalid type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template AddFunc(T, string N)
|
||||||
|
{
|
||||||
|
static if(is(ReturnType!(__traits(getMember, T, N)) == double))
|
||||||
|
{
|
||||||
|
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}ret[0] = Value(" ~ N ~ "(" ~
|
||||||
|
AddFuncArg!(0, 0, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
||||||
|
}
|
||||||
|
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
|
||||||
|
{
|
||||||
|
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall();}" ~ N ~ "(" ~
|
||||||
|
AddFuncArg!(0, 0, ParameterTypeTuple!(__traits(getMember, T, N))) ~ ");}";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const string AddFunc = "";
|
||||||
|
static assert(false, "Invalid type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DefaultValue!int fromIntToDefault(Value v)
|
||||||
|
{
|
||||||
|
if(v.isNumber)
|
||||||
|
return DefaultValue!int(v.castInteger());
|
||||||
|
else
|
||||||
|
return DefaultValue!int(true);
|
||||||
|
}
|
||||||
|
template GetFunctionParamType(T, string N)
|
||||||
|
{
|
||||||
|
enum GetFunctionParamType = mixin("[" ~ Array!(ParameterTypeTuple!(__traits(getMember, T, N))) ~ "]");
|
||||||
|
private template Array(P...)
|
||||||
|
{
|
||||||
|
static if(is(P[0] == double))
|
||||||
|
{
|
||||||
|
const string arg = "ValueType.Double, false";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == int))
|
||||||
|
{
|
||||||
|
const string arg = "ValueType.Integer, false";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == DefaultValue!int))
|
||||||
|
{
|
||||||
|
const string arg = "ValueType.Integer, true";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == PetitComputer))
|
||||||
|
{
|
||||||
|
enum Array = Array!(P[1..$]);
|
||||||
|
}
|
||||||
|
static if(1 == P.length && !is(P[0] == PetitComputer))
|
||||||
|
{
|
||||||
|
enum Array = "BuiltinFunctionArgument(" ~ arg ~ ")";
|
||||||
|
}
|
||||||
|
else static if(!is(P[0] == PetitComputer))
|
||||||
|
{
|
||||||
|
enum Array = "BuiltinFunctionArgument(" ~ arg ~ ")," ~ Array!(P[1..$]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template AddFuncArg(int N, int M, P...)
|
||||||
|
{
|
||||||
|
static if(is(P[0] == double))
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
const string arg = "arg[" ~ N.to!string ~ "].castDouble";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == PetitComputer))
|
||||||
|
{
|
||||||
|
enum add = 0;
|
||||||
|
const string arg = "p";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == int))
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
const string arg = "arg[" ~ N.to!string ~ "].castInteger";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == DefaultValue!int))
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
const string arg = "fromIntToDefault(arg[" ~ N.to!string ~ "])";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
static assert(false, "Invalid type");
|
||||||
|
const string arg = "";
|
||||||
|
}
|
||||||
|
static if(1 == P.length)
|
||||||
|
{
|
||||||
|
const string AddFuncArg = arg;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(N + add, M + 1, P[1..$]);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user