1
0

GBOXを実装,GCLSを実装,システム変数DATE$TIME$を実装,そのほか関数を実装,TRUE/FALSEを追加,小数点リテラルを実装.

This commit is contained in:
otya128
2015-08-20 15:28:02 +09:00
parent c9d6043fe4
commit b589766d47
8 changed files with 527 additions and 78 deletions

View File

@@ -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" />

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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;
} }
} }

View File

@@ -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:

View File

@@ -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)

View File

@@ -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)
{ {

View File

@@ -63,6 +63,8 @@ enum TokenType
Restore, Restore,
On, On,
Input, Input,
True,
False,
} }
struct Token struct Token