GBOXを実装,GCLSを実装,システム変数DATE$TIME$を実装,そのほか関数を実装,TRUE/FALSEを追加,小数点リテラルを実装.
This commit is contained in:
@@ -207,11 +207,13 @@
|
|||||||
<Folder name="SMILEBASIC">
|
<Folder name="SMILEBASIC">
|
||||||
<File path="builtinfunctions.d" />
|
<File path="builtinfunctions.d" />
|
||||||
<File path="compiler.d" />
|
<File path="compiler.d" />
|
||||||
|
<File path="draw.d" />
|
||||||
<File path="error.d" />
|
<File path="error.d" />
|
||||||
<File path="main.d" />
|
<File path="main.d" />
|
||||||
<File path="node.d" />
|
<File path="node.d" />
|
||||||
<File path="parser.d" />
|
<File path="parser.d" />
|
||||||
<File path="petitcomputer.d" />
|
<File path="petitcomputer.d" />
|
||||||
|
<File path="systemvariable.d" />
|
||||||
<File path="TEST.txt" />
|
<File path="TEST.txt" />
|
||||||
<File path="token.d" />
|
<File path="token.d" />
|
||||||
<File path="type.d" />
|
<File path="type.d" />
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
GOSUB@A
|
||||||
|
GOTO@B
|
||||||
|
'A=SIN(B)
|
||||||
|
'?Y2,SIN(DAY * 2 * 3.141 / BDAY),LINEH,LINEC
|
||||||
|
@A
|
||||||
|
Y2 = LINEC - SIN(DAY * 2 * 3 / BDAY) * LINEH
|
||||||
|
RETURN
|
||||||
|
@B
|
||||||
|
?DATE$, TIME$
|
||||||
|
DTREAD "2014/10/12" OUT Y,M,D
|
||||||
|
?Y,M,D
|
||||||
|
?SIN(1)
|
||||||
'COMMENT'
|
'COMMENT'
|
||||||
ASSERT__ 1, "TRUE"
|
ASSERT__ 1, "TRUE"
|
||||||
A$="A"
|
A$="A"
|
||||||
@@ -80,14 +92,18 @@ DEF ONGOSUBTEST
|
|||||||
@4
|
@4
|
||||||
END
|
END
|
||||||
@DATA_1
|
@DATA_1
|
||||||
DATA "A",1,2,3,4
|
DIM ARY[2]
|
||||||
|
DATA "A",1,2,3,4,5
|
||||||
READ DATA$,_1,_2
|
READ DATA$,_1,_2
|
||||||
READ _3,_4
|
READ _3,_4
|
||||||
|
READ ARY[_1]
|
||||||
ASSERT__ DATA$=="A", "DATA"
|
ASSERT__ DATA$=="A", "DATA"
|
||||||
ASSERT__ _1==1, "DATA"
|
ASSERT__ _1==1, "DATA"
|
||||||
ASSERT__ _2==2, "DATA"
|
ASSERT__ _2==2, "DATA"
|
||||||
ASSERT__ _3==3, "DATA"
|
ASSERT__ _3==3, "DATA"
|
||||||
ASSERT__ _4==4, "DATA"
|
ASSERT__ _4==4, "DATA"
|
||||||
|
ASSERT__ ARY[1]==5, "DATA"
|
||||||
|
?ARY[_1]
|
||||||
INPUT$="HELLO"
|
INPUT$="HELLO"
|
||||||
INPUT INPUT$,IN
|
INPUT INPUT$,IN
|
||||||
?INPUT$,IN
|
?INPUT$,IN
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import otya.smilebasic.token;
|
|||||||
import otya.smilebasic.error;
|
import otya.smilebasic.error;
|
||||||
import otya.smilebasic.compiler;
|
import otya.smilebasic.compiler;
|
||||||
import otya.smilebasic.petitcomputer;
|
import otya.smilebasic.petitcomputer;
|
||||||
|
import otya.smilebasic.systemvariable;
|
||||||
import std.uni;
|
import std.uni;
|
||||||
import std.utf;
|
import std.utf;
|
||||||
import std.conv;
|
import std.conv;
|
||||||
@@ -17,6 +18,10 @@ struct VMVariable
|
|||||||
this.index = index;
|
this.index = index;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
this(int index)
|
||||||
|
{
|
||||||
|
this.index = index;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
class VM
|
class VM
|
||||||
{
|
{
|
||||||
@@ -38,7 +43,8 @@ class VM
|
|||||||
this.globalTable = globalTable;
|
this.globalTable = globalTable;
|
||||||
foreach(wstring k, VMVariable v ; globalTable)
|
foreach(wstring k, VMVariable v ; globalTable)
|
||||||
{
|
{
|
||||||
this.global[v.index] = Value(v.type);
|
if(v.index >= 0)
|
||||||
|
this.global[v.index] = Value(v.type);
|
||||||
}
|
}
|
||||||
this.functions = functions;
|
this.functions = functions;
|
||||||
this.globalDataTable = gdt;
|
this.globalDataTable = gdt;
|
||||||
@@ -889,10 +895,16 @@ class CallBuiltinFunction : Code
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
arg = vm.stack[vm.stacki - argcount..vm.stacki];
|
arg = vm.stack[vm.stacki - argcount..vm.stacki];
|
||||||
result = vm.stack[vm.stacki - argcount..vm.stacki - argcount + outcount];//雑;
|
result = vm.stack[vm.stacki/* - argcount */+ 1..vm.stacki + 1/* - argcount */+ outcount];//雑;
|
||||||
}
|
}
|
||||||
func.func(vm.petitcomputer, arg, result);
|
func.func(vm.petitcomputer, arg, result);
|
||||||
vm.stacki -= func.argments.length - outcount;
|
vm.stacki -= func.argments.length;// - outcount;
|
||||||
|
////vm.stacki += outcount;
|
||||||
|
//vm.stacki = old;
|
||||||
|
for(int i = 0; i < result.length; i++)
|
||||||
|
{
|
||||||
|
vm.push(result[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class IncCodeG : Code
|
class IncCodeG : Code
|
||||||
@@ -1139,3 +1151,29 @@ class ReadCode : Code
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
class PushSystemVariable : Code
|
||||||
|
{
|
||||||
|
SystemVariable var;
|
||||||
|
this(SystemVariable var)
|
||||||
|
{
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
vm.push(var.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class PopSystemVariable : Code
|
||||||
|
{
|
||||||
|
SystemVariable var;
|
||||||
|
this(SystemVariable var)
|
||||||
|
{
|
||||||
|
this.var = var;
|
||||||
|
}
|
||||||
|
override void execute(VM vm)
|
||||||
|
{
|
||||||
|
Value v;
|
||||||
|
vm.pop(v);
|
||||||
|
var.value = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ struct DefaultValue(T, bool skippable = true)
|
|||||||
{
|
{
|
||||||
T value;
|
T value;
|
||||||
bool isDefault;
|
bool isDefault;
|
||||||
this(int v, bool f)
|
this(T v, bool f)
|
||||||
{
|
{
|
||||||
value = v;
|
value = v;
|
||||||
isDefault = f;
|
isDefault = f;
|
||||||
}
|
}
|
||||||
this(int v)
|
this(T v)
|
||||||
{
|
{
|
||||||
value = v;
|
value = v;
|
||||||
isDefault = false;
|
isDefault = false;
|
||||||
@@ -67,6 +67,10 @@ class BuiltinFunction
|
|||||||
return a < 0 ? -a : a;
|
return a < 0 ? -a : a;
|
||||||
}*/
|
}*/
|
||||||
static double function(double) ABS = &abs!double;
|
static double function(double) ABS = &abs!double;
|
||||||
|
static double SIN(double arg1)
|
||||||
|
{
|
||||||
|
return sin(arg1);
|
||||||
|
}
|
||||||
//static ABS = function double(double x) => abs(this.result == ValueType.Double ? 1 : 0);
|
//static ABS = function double(double x) => abs(this.result == ValueType.Double ? 1 : 0);
|
||||||
static void LOCATE(PetitComputer p, DefaultValue!int x, DefaultValue!int y, DefaultValue!(int, false) z)
|
static void LOCATE(PetitComputer p, DefaultValue!int x, DefaultValue!int y, DefaultValue!(int, false) z)
|
||||||
{
|
{
|
||||||
@@ -115,16 +119,84 @@ class BuiltinFunction
|
|||||||
static void DISPLAY(PetitComputer p, DefaultValue!(int, false) display)
|
static void DISPLAY(PetitComputer p, DefaultValue!(int, false) display)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
static void GCLS(PetitComputer p, DefaultValue!(int, false) display)
|
static void GCLS(PetitComputer p, DefaultValue!(int, false) color)
|
||||||
{
|
{
|
||||||
|
color.setDefaultValue(p.gcolor);
|
||||||
|
p.gfill(p.useGRP, 0, 0, 511, 511, cast(int)color);
|
||||||
}
|
}
|
||||||
static void GPSET(PetitComputer p, int x, int y, DefaultValue!(int, false) color)
|
static void GPSET(PetitComputer p, int x, int y, DefaultValue!(int, false) color)
|
||||||
{
|
{
|
||||||
//p.gpset(p.useGRP, x, y, );
|
color.setDefaultValue(p.gcolor);
|
||||||
|
p.gpset(p.useGRP, x, y, cast(int)color);
|
||||||
|
}
|
||||||
|
static void GLINE(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
|
||||||
|
{
|
||||||
|
color.setDefaultValue(p.gcolor);
|
||||||
|
p.gline(p.useGRP, x, y, x2, y2, cast(int)color);
|
||||||
|
}
|
||||||
|
static void GBOX(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
|
||||||
|
{
|
||||||
|
color.setDefaultValue(p.gcolor);
|
||||||
|
p.gbox(p.useGRP, x, y, x2, y2, cast(int)color);
|
||||||
|
}
|
||||||
|
static void GFILL(PetitComputer p, int x, int y, int x2, int y2, DefaultValue!(int, false) color)
|
||||||
|
{
|
||||||
|
color.setDefaultValue(p.gcolor);
|
||||||
|
p.gfill(p.useGRP, x, y, x2, y2, cast(int)color);
|
||||||
|
}
|
||||||
|
static void GCOLOR(PetitComputer p, int color)
|
||||||
|
{
|
||||||
|
p.gcolor = color;
|
||||||
}
|
}
|
||||||
static void BEEP(PetitComputer p, DefaultValue!(int, false) display)
|
static void BEEP(PetitComputer p, DefaultValue!(int, false) display)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
static int RGB(int R, int G, int B, DefaultValue!(int, false) _)
|
||||||
|
{
|
||||||
|
if(!_.isDefault)
|
||||||
|
{
|
||||||
|
//やや強引なオーバーロード
|
||||||
|
return PetitComputer.RGB(cast(ubyte)R, cast(ubyte)G, cast(ubyte)B, cast(ubyte)_);
|
||||||
|
}
|
||||||
|
return PetitComputer.RGB(cast(ubyte)R, cast(ubyte)G, cast(ubyte)B);
|
||||||
|
}
|
||||||
|
static int RND(int max)
|
||||||
|
{
|
||||||
|
import std.random;
|
||||||
|
return uniform(0, max - 1);
|
||||||
|
}
|
||||||
|
static void DTREAD(DefaultValue!(wstring, false) date, out int Y, out int M, out int D/*W*/)
|
||||||
|
{
|
||||||
|
import std.datetime;
|
||||||
|
auto currentTime = Clock.currTime();
|
||||||
|
if(date.isDefault)
|
||||||
|
{
|
||||||
|
Y = currentTime.year;
|
||||||
|
M = currentTime.month;
|
||||||
|
D = currentTime.day;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
import std.format;
|
||||||
|
auto v = date.value;
|
||||||
|
formattedRead(v, "%d/%d/%d", &Y, &M, &D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//hairetuha?
|
||||||
|
static int LEN(wstring str)
|
||||||
|
{
|
||||||
|
return str.length;
|
||||||
|
}
|
||||||
|
static double VAL(wstring str)
|
||||||
|
{
|
||||||
|
double val = str.to!double;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
static wstring MID(wstring str, int i, int len)
|
||||||
|
{
|
||||||
|
//挙動未定
|
||||||
|
return str[i..i + len];
|
||||||
|
}
|
||||||
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
|
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
|
||||||
static BuiltinFunction[wstring] builtinFunctions;
|
static BuiltinFunction[wstring] builtinFunctions;
|
||||||
static this()
|
static this()
|
||||||
@@ -134,7 +206,13 @@ class BuiltinFunction
|
|||||||
writeln(name);
|
writeln(name);
|
||||||
static if(/*__traits(isStaticFunction, __traits(getMember, BuiltinFunction, name)) && */name[0].isUpper)
|
static if(/*__traits(isStaticFunction, __traits(getMember, BuiltinFunction, name)) && */name[0].isUpper)
|
||||||
{
|
{
|
||||||
builtinFunctions[name] = new BuiltinFunction(
|
pragma(msg, AddFunc!(BuiltinFunction, name));
|
||||||
|
wstring suffix = "";
|
||||||
|
if(is(ReturnType!(__traits(getMember, BuiltinFunction, name)) == wstring))
|
||||||
|
{
|
||||||
|
suffix = "$";
|
||||||
|
}
|
||||||
|
builtinFunctions[name ~ suffix] = new BuiltinFunction(
|
||||||
GetFunctionParamType!(BuiltinFunction, name),
|
GetFunctionParamType!(BuiltinFunction, name),
|
||||||
GetFunctionReturnType!(BuiltinFunction, name),
|
GetFunctionReturnType!(BuiltinFunction, name),
|
||||||
mixin(AddFunc!(BuiltinFunction, name)),
|
mixin(AddFunc!(BuiltinFunction, name)),
|
||||||
@@ -179,6 +257,10 @@ template GetFunctionReturnType(T, string N)
|
|||||||
{
|
{
|
||||||
enum GetFunctionReturnType = ValueType.Void;
|
enum GetFunctionReturnType = ValueType.Void;
|
||||||
}
|
}
|
||||||
|
else static if(is(ReturnType!(__traits(getMember, T, N)) == wstring))
|
||||||
|
{
|
||||||
|
enum GetFunctionReturnType = ValueType.String;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enum GetFunctionReturnType = ValueType.Void;
|
enum GetFunctionReturnType = ValueType.Void;
|
||||||
@@ -190,12 +272,22 @@ 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();}ret[0] = Value(" ~ N ~ "(" ~
|
||||||
AddFuncArg!(ParameterTypeTuple!(__traits(getMember, T, N)).length - 1, 0, 0, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
|
||||||
|
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
||||||
}
|
}
|
||||||
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
|
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
|
||||||
{
|
{
|
||||||
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 0){throw new IllegalFunctionCall();}" ~ N ~ "(" ~
|
|
||||||
AddFuncArg!(ParameterTypeTuple!(__traits(getMember, T, N)).length - 1, 0, 0, ParameterTypeTuple!(__traits(getMember, 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 ~ "(" ~
|
||||||
|
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N,
|
||||||
|
ParameterTypeTuple!(__traits(getMember, T, N))) ~ ");}";
|
||||||
|
}
|
||||||
|
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 ~ "(" ~
|
||||||
|
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(T,N) - 1, 0, 0, 0, T, N
|
||||||
|
, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -217,6 +309,20 @@ DefaultValue!(int, false) fromIntToSkip(Value v)
|
|||||||
else
|
else
|
||||||
return DefaultValue!(int, false)(true);
|
return DefaultValue!(int, false)(true);
|
||||||
}
|
}
|
||||||
|
DefaultValue!wstring fromStringToDefault(Value v)
|
||||||
|
{
|
||||||
|
if(v.type == ValueType.String)
|
||||||
|
return DefaultValue!wstring(v.castString());
|
||||||
|
else
|
||||||
|
return DefaultValue!wstring(true);
|
||||||
|
}
|
||||||
|
DefaultValue!(wstring, false) fromStringToSkip(Value v)
|
||||||
|
{
|
||||||
|
if(v.type == ValueType.String)
|
||||||
|
return DefaultValue!(wstring, false)(v.castString());
|
||||||
|
else
|
||||||
|
return DefaultValue!(wstring, 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))) ~ "]");
|
||||||
@@ -249,6 +355,14 @@ template GetFunctionParamType(T, string N)
|
|||||||
{
|
{
|
||||||
const string arg = "ValueType.Integer, true";
|
const string arg = "ValueType.Integer, 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] == PetitComputer))
|
else static if(is(P[0] == PetitComputer))
|
||||||
{
|
{
|
||||||
static if(P.length != 0)
|
static if(P.length != 0)
|
||||||
@@ -271,42 +385,71 @@ template GetFunctionParamType(T, string N)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
template AddFuncArg(int L, int N, int M, P...)
|
template AddFuncArg(int L, int N, int M, int O, T, string NAME, P...)
|
||||||
{
|
{
|
||||||
enum I = L - N;
|
enum I = L - N;
|
||||||
|
enum storage = ParameterStorageClassTuple!(__traits(getMember, T, NAME))[M];
|
||||||
static if(is(P[0] == double))
|
static if(is(P[0] == double))
|
||||||
{
|
{
|
||||||
enum add = 1;
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
const string arg = "arg[" ~ I.to!string ~ "].castDouble";
|
const string arg = "arg[" ~ I.to!string ~ "].castDouble";
|
||||||
}
|
}
|
||||||
else static if(is(P[0] == PetitComputer))
|
else static if(is(P[0] == PetitComputer))
|
||||||
{
|
{
|
||||||
enum add = 0;
|
enum add = 0;
|
||||||
|
enum outadd = 0;
|
||||||
const string arg = "p";
|
const string arg = "p";
|
||||||
}
|
}
|
||||||
else static if(is(P[0] == int))
|
else static if(is(P[0] == int))
|
||||||
{
|
{
|
||||||
enum add = 1;
|
static if(storage & ParameterStorageClass.out_)
|
||||||
const string arg = "arg[" ~ I.to!string ~ "].castInteger";
|
{
|
||||||
|
enum add = 0;
|
||||||
|
enum outadd = 1;
|
||||||
|
const string arg = "ret[" ~ O.to!string ~ "].integerValue";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
|
const string arg = "arg[" ~ I.to!string ~ "].castInteger";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else static if(is(P[0] == wstring))
|
else static if(is(P[0] == wstring))
|
||||||
{
|
{
|
||||||
enum add = 1;
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
const string arg = "arg[" ~ I.to!string ~ "].castString";
|
const string arg = "arg[" ~ I.to!string ~ "].castString";
|
||||||
}
|
}
|
||||||
else static if(is(P[0] == DefaultValue!int))
|
else static if(is(P[0] == DefaultValue!int))
|
||||||
{
|
{
|
||||||
enum add = 1;
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
const string arg = "fromIntToDefault(arg[" ~ I.to!string ~ "])";
|
const string arg = "fromIntToDefault(arg[" ~ I.to!string ~ "])";
|
||||||
}
|
}
|
||||||
else static if(is(P[0] == DefaultValue!(int, false)))
|
else static if(is(P[0] == DefaultValue!(int, false)))
|
||||||
{
|
{
|
||||||
enum add = 1;
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
const string arg = "fromIntToSkip(arg[" ~ I.to!string ~ "])";
|
const string arg = "fromIntToSkip(arg[" ~ I.to!string ~ "])";
|
||||||
}
|
}
|
||||||
|
else static if(is(P[0] == DefaultValue!wstring))
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
|
const string arg = "fromStringToDefault(arg[" ~ I.to!string ~ "])";
|
||||||
|
}
|
||||||
|
else static if(is(P[0] == DefaultValue!(wstring, false)))
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
|
const string arg = "fromStringToSkip(arg[" ~ I.to!string ~ "])";
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enum add = 1;
|
enum add = 1;
|
||||||
|
enum outadd = 0;
|
||||||
static assert(false, "Invalid type");
|
static assert(false, "Invalid type");
|
||||||
const string arg = "";
|
const string arg = "";
|
||||||
}
|
}
|
||||||
@@ -316,6 +459,62 @@ template AddFuncArg(int L, int N, int M, P...)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(L - !add, N + add, M + 1, P[1..$]);
|
const string AddFuncArg = arg ~ ", " ~ AddFuncArg!(L - !add, N + add, M + 1, O + outadd, T, NAME, P[1..$]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template OutArgsInit(T, string N, int I = 0, int J = 0)
|
||||||
|
{
|
||||||
|
enum tuple = ParameterStorageClassTuple!(__traits(getMember, T, N))[I];
|
||||||
|
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
|
||||||
|
static if(tuple & ParameterStorageClass.out_)
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
enum ret1 = "ret[" ~ J.to!string ~ "].type = ";
|
||||||
|
static if(is(param[I] == int))
|
||||||
|
{
|
||||||
|
enum ret2 = "ValueType.Integer;";
|
||||||
|
}
|
||||||
|
enum result = ret1 ~ ret2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum add = 0;
|
||||||
|
enum result = "";
|
||||||
|
}
|
||||||
|
static if(param.length > I + 1)
|
||||||
|
{
|
||||||
|
enum OutArgsInit = result ~ OutArgsInit!(T, N, I + 1, J + add);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum OutArgsInit = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
template GetArgumentCount(T, string N, int I = 0)
|
||||||
|
{
|
||||||
|
enum tuple = ParameterStorageClassTuple!(__traits(getMember, T, N))[I];
|
||||||
|
alias param = ParameterTypeTuple!(__traits(getMember, T, N));
|
||||||
|
static if(is(param[I] == PetitComputer))
|
||||||
|
{
|
||||||
|
enum add = 0 + 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static if(tuple & ParameterStorageClass.out_)
|
||||||
|
{
|
||||||
|
enum add = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum add = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static if(param.length > I + 1)
|
||||||
|
{
|
||||||
|
enum GetArgumentCount = add + GetArgumentCount!(T, N, I + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum GetArgumentCount = add;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import otya.smilebasic.token;
|
|||||||
import otya.smilebasic.vm;
|
import otya.smilebasic.vm;
|
||||||
import otya.smilebasic.type;
|
import otya.smilebasic.type;
|
||||||
import otya.smilebasic.error;
|
import otya.smilebasic.error;
|
||||||
|
import otya.smilebasic.systemvariable;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
class Scope
|
class Scope
|
||||||
{
|
{
|
||||||
@@ -145,6 +146,7 @@ class Compiler
|
|||||||
case '%':
|
case '%':
|
||||||
return ValueType.Integer;
|
return ValueType.Integer;
|
||||||
default:
|
default:
|
||||||
|
return ValueType.Double;//非DEFINT時
|
||||||
return ValueType.Integer;//DEFINT時
|
return ValueType.Integer;//DEFINT時
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,8 +155,13 @@ class Compiler
|
|||||||
{
|
{
|
||||||
this.statements = statements;
|
this.statements = statements;
|
||||||
code = new Code[0];
|
code = new Code[0];
|
||||||
|
global["DATE$"] = VMVariable(-1);
|
||||||
|
sysVariable["DATE$"] = new Date();
|
||||||
|
global["TIME$"] = VMVariable(-1);
|
||||||
|
sysVariable["TIME$"] = new Time();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SystemVariable[wstring] sysVariable;
|
||||||
Code[] code;
|
Code[] code;
|
||||||
VMVariable[wstring] global;
|
VMVariable[wstring] global;
|
||||||
int[wstring] globalLabel;
|
int[wstring] globalLabel;
|
||||||
@@ -176,6 +183,19 @@ class Compiler
|
|||||||
{
|
{
|
||||||
code ~= new PopG(ind);
|
code ~= new PopG(ind);
|
||||||
}
|
}
|
||||||
|
SystemVariable getSystemVariable(wstring name)
|
||||||
|
{
|
||||||
|
auto var = sysVariable.get(name, null);
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
void genCodePushSysVar(wstring name)
|
||||||
|
{
|
||||||
|
code ~= new PushSystemVariable(getSystemVariable(name));
|
||||||
|
}
|
||||||
|
void genCodePopSysVar(wstring name)
|
||||||
|
{
|
||||||
|
code ~= new PopSystemVariable(getSystemVariable(name));
|
||||||
|
}
|
||||||
void genCodePushVar(wstring name, Scope sc)
|
void genCodePushVar(wstring name, Scope sc)
|
||||||
{
|
{
|
||||||
auto global = hasGlobalVarIndex(name);
|
auto global = hasGlobalVarIndex(name);
|
||||||
@@ -186,6 +206,11 @@ class Compiler
|
|||||||
}
|
}
|
||||||
if(global)
|
if(global)
|
||||||
{
|
{
|
||||||
|
if(global < 0)
|
||||||
|
{
|
||||||
|
genCodePushSysVar(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
code ~= new PushG(global);
|
code ~= new PushG(global);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -201,6 +226,11 @@ class Compiler
|
|||||||
}
|
}
|
||||||
if(global)
|
if(global)
|
||||||
{
|
{
|
||||||
|
if(global < 0)
|
||||||
|
{
|
||||||
|
genCodePopSysVar(name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
code ~= new PopG(global);
|
code ~= new PopG(global);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -371,13 +401,17 @@ class Compiler
|
|||||||
case NodeType.CallFunction:
|
case NodeType.CallFunction:
|
||||||
{
|
{
|
||||||
auto func = cast(CallFunction)exp;
|
auto func = cast(CallFunction)exp;
|
||||||
|
writeln(func.name);
|
||||||
auto bfun = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
|
auto bfun = otya.smilebasic.builtinfunctions.BuiltinFunction.builtinFunctions.get(func.name, null);
|
||||||
if(bfun)
|
if(bfun)
|
||||||
{
|
{
|
||||||
auto k = bfun.argments.length - func.args.length;
|
if(bfun.argments.length >= func.args.length)
|
||||||
foreach(l;0..k)
|
|
||||||
{
|
{
|
||||||
genCodeImm(Value(ValueType.Void));
|
auto k = bfun.argments.length - func.args.length;
|
||||||
|
foreach(l;0..k)
|
||||||
|
{
|
||||||
|
genCodeImm(Value(ValueType.Void));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach_reverse(Expression i ; func.args)
|
foreach_reverse(Expression i ; func.args)
|
||||||
@@ -418,10 +452,11 @@ class Compiler
|
|||||||
case NodeType.Variable:
|
case NodeType.Variable:
|
||||||
{
|
{
|
||||||
auto var = cast(Variable)expr;
|
auto var = cast(Variable)expr;
|
||||||
int index;
|
genCodePopVar(var.name, sc);
|
||||||
bool local;
|
//int index;
|
||||||
getVarIndex(var.name, sc, index, local);
|
//bool local;
|
||||||
genCode(local ? new PopL(index) : new PopG(index));
|
//getVarIndex(var.name, sc, index, local);
|
||||||
|
//genCode(local ? new PopL(index) : new PopG(index));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case NodeType.BinaryOperator:
|
case NodeType.BinaryOperator:
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import otya.smilebasic.node;
|
|||||||
import otya.smilebasic.compiler;
|
import otya.smilebasic.compiler;
|
||||||
import std.ascii;
|
import std.ascii;
|
||||||
import std.stdio;
|
import std.stdio;
|
||||||
|
import std.conv;
|
||||||
class Lexical
|
class Lexical
|
||||||
{
|
{
|
||||||
TokenType[] table;
|
TokenType[] table;
|
||||||
@@ -60,6 +61,7 @@ class Lexical
|
|||||||
reserved["DIM"] = TokenType.Var;
|
reserved["DIM"] = TokenType.Var;
|
||||||
reserved["DEF"] = TokenType.Def;
|
reserved["DEF"] = TokenType.Def;
|
||||||
reserved["OUT"] = TokenType.Out;
|
reserved["OUT"] = TokenType.Out;
|
||||||
|
reserved["out"] = TokenType.Out;//ekkitou
|
||||||
reserved["WHILE"] = TokenType.While;
|
reserved["WHILE"] = TokenType.While;
|
||||||
reserved["WEND"] = TokenType.WEnd;
|
reserved["WEND"] = TokenType.WEnd;
|
||||||
reserved["INC"] = TokenType.Inc;
|
reserved["INC"] = TokenType.Inc;
|
||||||
@@ -69,6 +71,8 @@ class Lexical
|
|||||||
reserved["RESTORE"] = TokenType.Restore;
|
reserved["RESTORE"] = TokenType.Restore;
|
||||||
reserved["ON"] = TokenType.On;
|
reserved["ON"] = TokenType.On;
|
||||||
reserved["INPUT"] = TokenType.Input;
|
reserved["INPUT"] = TokenType.Input;
|
||||||
|
reserved["TRUE"] = TokenType.True;
|
||||||
|
reserved["FALSE"] = TokenType.False;
|
||||||
reserved.rehash();
|
reserved.rehash();
|
||||||
line = 1;
|
line = 1;
|
||||||
}
|
}
|
||||||
@@ -103,19 +107,34 @@ class Lexical
|
|||||||
token = Token(TokenType.NewLine);
|
token = Token(TokenType.NewLine);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(c.isDigit())
|
if(c.isDigit() || c == '.')
|
||||||
{
|
{
|
||||||
int num;
|
bool dot;
|
||||||
|
int start = i;
|
||||||
|
double num;
|
||||||
for(;i < code.length;i++)
|
for(;i < code.length;i++)
|
||||||
{
|
{
|
||||||
c = code[i];
|
c = code[i];
|
||||||
if(!c.isDigit())
|
if(c == '.')
|
||||||
|
{
|
||||||
|
if(dot) break;
|
||||||
|
dot = true;
|
||||||
|
}
|
||||||
|
if(!c.isDigit() && c != '.')
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
num = num * 10 + (c - '0');
|
|
||||||
}
|
}
|
||||||
token = Token(TokenType.Integer, Value(num));
|
wstring numstr = code[start..i];
|
||||||
|
num = numstr.to!double;
|
||||||
|
if(num <= int.max && num >= int.min && !dot)
|
||||||
|
{
|
||||||
|
token = Token(TokenType.Integer, Value(cast(int)num));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
token = Token(TokenType.Integer, Value(num));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(c.isAlpha() || c == '_')
|
if(c.isAlpha() || c == '_')
|
||||||
@@ -138,6 +157,17 @@ class Lexical
|
|||||||
else//変数が予約語であることはありえない
|
else//変数が予約語であることはありえない
|
||||||
{
|
{
|
||||||
auto r = reserved.get(iden, TokenType.Unknown);
|
auto r = reserved.get(iden, TokenType.Unknown);
|
||||||
|
//TRUE/FALSEは3.1でもDATAに使える定数
|
||||||
|
if(r == TokenType.True)
|
||||||
|
{
|
||||||
|
token = Token(TokenType.Integer, Value(1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(r == TokenType.False)
|
||||||
|
{
|
||||||
|
token = Token(TokenType.Integer, Value(0));
|
||||||
|
break;
|
||||||
|
}
|
||||||
if(r != TokenType.Unknown)
|
if(r != TokenType.Unknown)
|
||||||
{
|
{
|
||||||
token = Token(r);
|
token = Token(r);
|
||||||
@@ -628,6 +658,20 @@ class Parser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
|
auto token = lex.front;
|
||||||
|
if(token.type == TokenType.Iden)
|
||||||
|
{
|
||||||
|
//NEXT I[,J[,K...]]プチコン3号だと無視
|
||||||
|
lex.popFront();
|
||||||
|
token = lex.front;
|
||||||
|
while(token.type == TokenType.Comma)
|
||||||
|
{
|
||||||
|
lex.popFront();
|
||||||
|
token = lex.front;
|
||||||
|
if(token.type != TokenType.Iden) break;
|
||||||
|
lex.popFront();
|
||||||
|
}
|
||||||
|
}
|
||||||
return statements;
|
return statements;
|
||||||
}
|
}
|
||||||
Statements whileStatements()
|
Statements whileStatements()
|
||||||
@@ -655,6 +699,7 @@ class Parser
|
|||||||
{
|
{
|
||||||
auto token = lex.front();
|
auto token = lex.front();
|
||||||
Statement node = null;
|
Statement node = null;
|
||||||
|
writeln(token.type);
|
||||||
switch(token.type)
|
switch(token.type)
|
||||||
{
|
{
|
||||||
case TokenType.Print:
|
case TokenType.Print:
|
||||||
@@ -694,6 +739,7 @@ class Parser
|
|||||||
if(expr)
|
if(expr)
|
||||||
func.addArg(expr);
|
func.addArg(expr);
|
||||||
}
|
}
|
||||||
|
if(lex.front().type == TokenType.Out) break;
|
||||||
if(lex.front().type != TokenType.Comma) break;
|
if(lex.front().type != TokenType.Comma) break;
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
}
|
}
|
||||||
@@ -753,8 +799,7 @@ class Parser
|
|||||||
node = if_();
|
node = if_();
|
||||||
return node;
|
return node;
|
||||||
case TokenType.For:
|
case TokenType.For:
|
||||||
node = forStatement();
|
return forStatement();
|
||||||
break;
|
|
||||||
case TokenType.Return:
|
case TokenType.Return:
|
||||||
lex.popFront();
|
lex.popFront();
|
||||||
if(isFuncReturnExpr)
|
if(isFuncReturnExpr)
|
||||||
|
|||||||
@@ -123,6 +123,8 @@ class PetitComputer
|
|||||||
ConsoleCharacter[][] console;
|
ConsoleCharacter[][] console;
|
||||||
bool visibleGRP = true;
|
bool visibleGRP = true;
|
||||||
int showGRP;
|
int showGRP;
|
||||||
|
int useGRP;
|
||||||
|
uint gcolor;
|
||||||
GraphicPage[] GRP;
|
GraphicPage[] GRP;
|
||||||
GraphicPage GRPF;
|
GraphicPage GRPF;
|
||||||
GraphicPage[] GRPFColor;
|
GraphicPage[] GRPFColor;
|
||||||
@@ -261,6 +263,19 @@ class PetitComputer
|
|||||||
}
|
}
|
||||||
return new GraphicPage(surface);
|
return new GraphicPage(surface);
|
||||||
}
|
}
|
||||||
|
GraphicPage createEmptyPage()
|
||||||
|
{
|
||||||
|
auto surface = SDL_CreateRGBSurface(0, 512, 512, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0xff);
|
||||||
|
auto pixels = (cast(uint*)surface.pixels);
|
||||||
|
for(int x = 0; x < surface.w; x++)
|
||||||
|
{
|
||||||
|
for(int y = 0; y < surface.h; y++)
|
||||||
|
{
|
||||||
|
*pixels++ = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new GraphicPage(surface);
|
||||||
|
}
|
||||||
struct Point
|
struct Point
|
||||||
{
|
{
|
||||||
int x, y;
|
int x, y;
|
||||||
@@ -382,7 +397,7 @@ class PetitComputer
|
|||||||
GRP = new GraphicPage[6];
|
GRP = new GraphicPage[6];
|
||||||
for(int i = 0; i < 4; i++)
|
for(int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
GRP[i] = new GraphicPage(SDL_CreateRGBSurface(0, 512, 512, 32, 0xff000000, 0x00ff0000, 0x0000ff00, 0xff));
|
GRP[i] = createEmptyPage();
|
||||||
}
|
}
|
||||||
GRP[4] = createGRPF(spriteFile);
|
GRP[4] = createGRPF(spriteFile);
|
||||||
GRP[5] = createGRPF(BGFile);
|
GRP[5] = createGRPF(BGFile);
|
||||||
@@ -431,9 +446,43 @@ class PetitComputer
|
|||||||
keybufferlen = keybuffer.length;
|
keybufferlen = keybuffer.length;
|
||||||
keybufferpos = (keybufferpos + 1) % keybuffer.length;
|
keybufferpos = (keybufferpos + 1) % keybuffer.length;
|
||||||
}
|
}
|
||||||
|
Mutex grpmutex;
|
||||||
|
otya.smilebasic.draw.Draw draw;
|
||||||
|
void renderGraphic()
|
||||||
|
{
|
||||||
|
//grpmutex.lock();
|
||||||
|
//scope(exit)
|
||||||
|
// grpmutex.unlock();
|
||||||
|
drawflag = true;
|
||||||
|
//betuni kouzoutai demo sonnnani sokudo kawaranasasou
|
||||||
|
auto len = drawMessageLength;
|
||||||
|
drawMessageLength = 0;
|
||||||
|
for(int i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
DrawMessage dm = drawMessageQueue[i];
|
||||||
|
switch(dm.type)
|
||||||
|
{
|
||||||
|
case DrawType.PSET:
|
||||||
|
draw.gpset(dm.page, dm.x, dm.y ,dm.color);
|
||||||
|
break;
|
||||||
|
case DrawType.LINE:
|
||||||
|
draw.gline(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
|
||||||
|
break;
|
||||||
|
case DrawType.FILL:
|
||||||
|
draw.gfill(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
|
||||||
|
break;
|
||||||
|
case DrawType.BOX:
|
||||||
|
draw.gbox(dm.page, dm.x, dm.y ,dm.x2, dm.y2, dm.color);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
drawflag = false;
|
||||||
|
|
||||||
|
}
|
||||||
void render()
|
void render()
|
||||||
{
|
{
|
||||||
bool renderprofile = true;
|
bool renderprofile;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
version(Windows)
|
version(Windows)
|
||||||
@@ -471,8 +520,12 @@ class PetitComputer
|
|||||||
g.createTexture(renderer);
|
g.createTexture(renderer);
|
||||||
}
|
}
|
||||||
//GRP[0] = GRPF;
|
//GRP[0] = GRPF;
|
||||||
gpset(0, 10, 10, 0xFF00FF00);
|
//glEnable(GL_BLEND);
|
||||||
gline(0, 0, 0, 399, 239, RGB(0, 255, 0));
|
//glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
glAlphaFunc(GL_GEQUAL, 0.5);
|
||||||
|
glEnable(GL_ALPHA_TEST);
|
||||||
|
draw = new otya.smilebasic.draw.Draw(this);
|
||||||
while(true)
|
while(true)
|
||||||
{
|
{
|
||||||
auto profile = SDL_GetTicks();
|
auto profile = SDL_GetTicks();
|
||||||
@@ -486,9 +539,10 @@ class PetitComputer
|
|||||||
loopcnt = 0;
|
loopcnt = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
renderGraphic();
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
//renderConsoleGL();
|
|
||||||
renderGraphicPage();
|
renderGraphicPage();
|
||||||
|
renderConsoleGL();
|
||||||
SDL_GL_SwapWindow(window);
|
SDL_GL_SwapWindow(window);
|
||||||
auto renderticks = (SDL_GetTicks() - profile);
|
auto renderticks = (SDL_GetTicks() - profile);
|
||||||
if(renderprofile) writeln(renderticks);
|
if(renderprofile) writeln(renderticks);
|
||||||
@@ -528,9 +582,18 @@ class PetitComputer
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
long delay = (1000/60) - cast(long)(SDL_GetTicks() - profile);
|
while(true)
|
||||||
if(delay > 0)
|
{
|
||||||
SDL_Delay(cast(uint)delay);
|
long delay = (1000/60) - cast(long)(SDL_GetTicks() - profile);
|
||||||
|
if(delay > 0)
|
||||||
|
SDL_Delay(cast(uint)delay);
|
||||||
|
break;
|
||||||
|
if(delay < 0) break;
|
||||||
|
renderGraphic();
|
||||||
|
SDL_Delay(1);
|
||||||
|
//if(delay > 0)
|
||||||
|
// SDL_Delay(cast(uint)delay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch(Throwable t)
|
catch(Throwable t)
|
||||||
@@ -553,11 +616,13 @@ class PetitComputer
|
|||||||
|
|
||||||
consolem = new Mutex();
|
consolem = new Mutex();
|
||||||
keybuffermutex = new Mutex();
|
keybuffermutex = new Mutex();
|
||||||
|
grpmutex = new Mutex();
|
||||||
core.thread.Thread thread = new core.thread.Thread(&render);
|
core.thread.Thread thread = new core.thread.Thread(&render);
|
||||||
thread.start();
|
thread.start();
|
||||||
auto startTicks = SDL_GetTicks();
|
auto startTicks = SDL_GetTicks();
|
||||||
//とりあえず
|
//とりあえず
|
||||||
auto parser = new Parser(readText(input("LOAD PROGRAM:", true).to!string).to!wstring
|
auto parser = new Parser(readText("./SYS/EX5BIORHYTHM.TXT").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
|
||||||
@@ -603,6 +668,10 @@ class PetitComputer
|
|||||||
auto vm = parser.compile();
|
auto vm = parser.compile();
|
||||||
bool running = true;
|
bool running = true;
|
||||||
vm.init(this);
|
vm.init(this);
|
||||||
|
gpset(0, 10, 10, 0xFF00FF00);
|
||||||
|
gline(0, 0, 0, 399, 239, RGB(0, 255, 0));
|
||||||
|
gfill(0, 78, 78, 40, 40, RGB(0, 255, 255));
|
||||||
|
gbox(0, 78, 78, 40, 40, RGB(255, 255, 0));
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
uint elapse;
|
uint elapse;
|
||||||
@@ -712,7 +781,7 @@ class PetitComputer
|
|||||||
bool animationCursor;
|
bool animationCursor;
|
||||||
Mutex consolem;
|
Mutex consolem;
|
||||||
//プチコン内部表現はRGB5_A1
|
//プチコン内部表現はRGB5_A1
|
||||||
uint toGLColor(GLenum format, ubyte r, ubyte g, ubyte b, ubyte a)
|
static uint toGLColor(GLenum format, ubyte r, ubyte g, ubyte b, ubyte a)
|
||||||
{
|
{
|
||||||
if(format == GL_BGRA)
|
if(format == GL_BGRA)
|
||||||
{
|
{
|
||||||
@@ -724,7 +793,7 @@ class PetitComputer
|
|||||||
}
|
}
|
||||||
throw new Exception("unsuport enviroment");
|
throw new Exception("unsuport enviroment");
|
||||||
}
|
}
|
||||||
uint toGLColor(GLenum format, uint petitcolor)
|
static uint toGLColor(GLenum format, uint petitcolor)
|
||||||
{
|
{
|
||||||
if(format == GL_BGRA)
|
if(format == GL_BGRA)
|
||||||
{
|
{
|
||||||
@@ -737,7 +806,7 @@ class PetitComputer
|
|||||||
throw new Exception("unsuport enviroment");
|
throw new Exception("unsuport enviroment");
|
||||||
}
|
}
|
||||||
//プチコンと違って[A,]R,G,Bじゃない
|
//プチコンと違って[A,]R,G,Bじゃない
|
||||||
void RGBRead(uint color, out ubyte r, out ubyte g, out ubyte b, out ubyte a)
|
static void RGBRead(uint color, out ubyte r, out ubyte g, out ubyte b, out ubyte a)
|
||||||
{
|
{
|
||||||
//エンディアン関係ない
|
//エンディアン関係ない
|
||||||
a = color >> 24;
|
a = color >> 24;
|
||||||
@@ -745,62 +814,107 @@ class PetitComputer
|
|||||||
g = color >> 8 & 0xFF;
|
g = color >> 8 & 0xFF;
|
||||||
b = color& 0xFF;
|
b = color& 0xFF;
|
||||||
}
|
}
|
||||||
uint RGB(ubyte r, ubyte g, ubyte b)
|
static uint RGB(ubyte r, ubyte g, ubyte b)
|
||||||
{
|
{
|
||||||
return 0xFF000000 | r << 16 | g << 8 | b;
|
return 0xFF000000 | r << 16 | g << 8 | b;
|
||||||
}
|
}
|
||||||
uint RGB(ubyte a, ubyte r, ubyte g, ubyte b)
|
static uint RGB(ubyte a, ubyte r, ubyte g, ubyte b)
|
||||||
{
|
{
|
||||||
return a << 24 | r << 16 | g << 8 | b;
|
return a << 24 | r << 16 | g << 8 | b;
|
||||||
}
|
}
|
||||||
|
enum DrawType
|
||||||
|
{
|
||||||
|
CLEAR,
|
||||||
|
PSET,
|
||||||
|
LINE,
|
||||||
|
FILL,
|
||||||
|
BOX,
|
||||||
|
CIRCLE,
|
||||||
|
TRI,
|
||||||
|
}
|
||||||
|
struct DrawMessage
|
||||||
|
{
|
||||||
|
DrawType type;
|
||||||
|
byte page;
|
||||||
|
short x;
|
||||||
|
short y;
|
||||||
|
short x2;
|
||||||
|
short y2;
|
||||||
|
uint color;
|
||||||
|
//
|
||||||
|
}
|
||||||
|
static const int dmqqueuelen = 8192;
|
||||||
|
DrawMessage[] drawMessageQueue = new DrawMessage[dmqqueuelen];
|
||||||
|
int drawMessageLength;
|
||||||
|
bool drawflag;
|
||||||
|
void sendDrawMessage(DrawType type, byte page, short x, short y, uint color)
|
||||||
|
{
|
||||||
|
//grpmutex.lock();
|
||||||
|
//scope(exit)
|
||||||
|
// grpmutex.unlock();
|
||||||
|
if(drawMessageLength >= dmqqueuelen)
|
||||||
|
{
|
||||||
|
while(drawMessageLength)
|
||||||
|
{
|
||||||
|
SDL_Delay(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while(drawflag){}
|
||||||
|
drawMessageQueue[drawMessageLength].type = type;
|
||||||
|
drawMessageQueue[drawMessageLength].page = page;
|
||||||
|
drawMessageQueue[drawMessageLength].x = x;
|
||||||
|
drawMessageQueue[drawMessageLength].y = y;
|
||||||
|
drawMessageQueue[drawMessageLength].color = color;
|
||||||
|
drawMessageLength++;
|
||||||
|
}
|
||||||
|
void sendDrawMessage(DrawType type, byte page, short x, short y, short x2, short y2, uint color)
|
||||||
|
{
|
||||||
|
grpmutex.lock();
|
||||||
|
scope(exit)
|
||||||
|
grpmutex.unlock();
|
||||||
|
drawMessageQueue[drawMessageLength].type = type;
|
||||||
|
drawMessageQueue[drawMessageLength].page = page;
|
||||||
|
drawMessageQueue[drawMessageLength].x = x;
|
||||||
|
drawMessageQueue[drawMessageLength].y = y;
|
||||||
|
drawMessageQueue[drawMessageLength].x2 = x2;
|
||||||
|
drawMessageQueue[drawMessageLength].y2 = y2;
|
||||||
|
drawMessageQueue[drawMessageLength].color = color;
|
||||||
|
drawMessageLength++;
|
||||||
|
}
|
||||||
|
//TODO:範囲チェック
|
||||||
void gpset(int page, int x, int y, uint color)
|
void gpset(int page, int x, int y, uint color)
|
||||||
{
|
{
|
||||||
color = toGLColor(GRP[page].textureFormat, color);
|
sendDrawMessage(DrawType.PSET, cast(byte)page, cast(short)x, cast(short)y, color);
|
||||||
glBindTexture(GL_TEXTURE_2D, GRP[page].glTexture);
|
|
||||||
glTexSubImage2D(GL_TEXTURE_2D , 0, x, y, 1, 1, GRP[page].textureFormat, GL_UNSIGNED_BYTE, &color);
|
|
||||||
}
|
}
|
||||||
void gline(int page, int x, int y, int x2, int y2, uint color)
|
void gline(int page, int x, int y, int x2, int y2, uint color)
|
||||||
{
|
{
|
||||||
import std.math;
|
sendDrawMessage(DrawType.LINE, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
|
||||||
int dx = abs(x2 - x);
|
}
|
||||||
int dy = abs(y2 - y);
|
void gbox(int page, int x, int y, int x2, int y2, uint color)
|
||||||
int sx, sy;
|
{
|
||||||
if(x < x2) sx = 1; else sx = -1;
|
sendDrawMessage(DrawType.BOX, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
|
||||||
if(y < y2) sy = 1; else sy = -1;
|
}
|
||||||
int err = dx - dy;
|
void gfill(int page, int x, int y, int x2, int y2, uint color)
|
||||||
while(true)
|
{
|
||||||
{
|
sendDrawMessage(DrawType.FILL, cast(byte)page, cast(short)x, cast(short)y, cast(short)x2, cast(short)y2, color);
|
||||||
gpset(page, x, y, color);
|
|
||||||
if(x == x2 && y == y2)break;
|
|
||||||
int e2 = 2*err;
|
|
||||||
if(e2 > -dy)
|
|
||||||
{
|
|
||||||
err = err - dy;
|
|
||||||
x = x + sx;
|
|
||||||
}
|
|
||||||
if(e2 < dx)
|
|
||||||
{
|
|
||||||
err = err + dx;
|
|
||||||
y = y + sy ;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void renderGraphicPage()
|
void renderGraphicPage()
|
||||||
{
|
{
|
||||||
|
float z = 0.01f;
|
||||||
glColor3f(1.0, 1.0, 1.0);
|
glColor3f(1.0, 1.0, 1.0);
|
||||||
glBindTexture(GL_TEXTURE_2D, GRP[showGRP].glTexture);
|
glBindTexture(GL_TEXTURE_2D, GRP[showGRP].glTexture);
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glBegin(GL_QUADS);
|
glBegin(GL_QUADS);
|
||||||
glTexCoord2f(0 / 512f - 1 , 240 / 512f - 1);
|
glTexCoord2f(0 / 512f - 1 , 240 / 512f - 1);
|
||||||
glVertex3f(0 / 200f - 1, 1 - 240 / 120f, 0);
|
glVertex3f(0 / 200f - 1, 1 - 240 / 120f, z);
|
||||||
glTexCoord2f(0 / 512f - 1, 0 / 512f - 1);
|
glTexCoord2f(0 / 512f - 1, 0 / 512f - 1);
|
||||||
glVertex3f(0 / 200f - 1, 1 - 0 / 120f, 0);
|
glVertex3f(0 / 200f - 1, 1 - 0 / 120f, z);
|
||||||
glTexCoord2f(400 / 512f - 1, 0 / 512f - 1);
|
glTexCoord2f(400 / 512f - 1, 0 / 512f - 1);
|
||||||
glVertex3f(400 / 200f - 1, 1 - 0 / 120f, 0);
|
glVertex3f(400 / 200f - 1, 1 - 0 / 120f, z);
|
||||||
glTexCoord2f(400 / 512f - 1, 240 / 512f - 1);
|
glTexCoord2f(400 / 512f - 1, 240 / 512f - 1);
|
||||||
glVertex3f(400 / 200f - 1, 1 - 240 / 120f, 0);
|
glVertex3f(400 / 200f - 1, 1 - 240 / 120f, z);
|
||||||
glEnd();
|
glEnd();
|
||||||
glFlush();
|
//glFlush();
|
||||||
}
|
}
|
||||||
void renderConsoleGL()
|
void renderConsoleGL()
|
||||||
{
|
{
|
||||||
@@ -829,8 +943,6 @@ class PetitComputer
|
|||||||
}
|
}
|
||||||
glEnd();
|
glEnd();
|
||||||
glEnable(GL_TEXTURE_2D);
|
glEnable(GL_TEXTURE_2D);
|
||||||
glEnable(GL_BLEND);
|
|
||||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
||||||
|
|
||||||
//glAlphaFunc(GL_GEQUAL, 0.5);
|
//glAlphaFunc(GL_GEQUAL, 0.5);
|
||||||
//glEnable(GL_ALPHA_TEST);
|
//glEnable(GL_ALPHA_TEST);
|
||||||
@@ -851,7 +963,7 @@ 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();
|
||||||
glFlush();
|
// glFlush();
|
||||||
}
|
}
|
||||||
void printConsole(T...)(T args)
|
void printConsole(T...)(T args)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ enum TokenType
|
|||||||
Restore,
|
Restore,
|
||||||
On,
|
On,
|
||||||
Input,
|
Input,
|
||||||
|
True,
|
||||||
|
False,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|||||||
Reference in New Issue
Block a user