関数内ラベル実装と引数なし関数を正常に呼べるようにした
This commit is contained in:
@@ -24,6 +24,18 @@ DEF INCTEST A
|
||||
DEC A
|
||||
ASSERT__ A==10, "A==10"
|
||||
END
|
||||
GOTOTEST
|
||||
GOTO@SKIP
|
||||
@LOCAL
|
||||
ASSERT__ 0, "LOCAL LABEL"
|
||||
@SKIP
|
||||
DEF GOTOTEST
|
||||
GOTO @LOCAL
|
||||
ASSERT__ 0, "LOCAL LABEL"
|
||||
@LOCAL
|
||||
END
|
||||
@DATA_1
|
||||
DATA "A",1,2,3,4
|
||||
LOCATE 10,
|
||||
COLOR 1,15
|
||||
PRINT "テスト正常終了"
|
||||
@@ -486,14 +486,16 @@ class GotoAddr : Code
|
||||
class GotoS : Code
|
||||
{
|
||||
wstring label;
|
||||
this(wstring label)
|
||||
Scope sc;
|
||||
this(wstring label, Scope sc)
|
||||
{
|
||||
this.type = CodeType.GotoS;
|
||||
this.label = label;
|
||||
this.sc = sc;
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
stderr.writeln("can't execute");
|
||||
stderr.writeln("can't execute (compiler bug?)");
|
||||
}
|
||||
}
|
||||
class GotoTrue : Code
|
||||
@@ -545,14 +547,16 @@ class GosubAddr : Code
|
||||
class GosubS : Code
|
||||
{
|
||||
wstring label;
|
||||
this(wstring label)
|
||||
Scope sc;
|
||||
this(wstring label, Scope sc)
|
||||
{
|
||||
this.type = CodeType.GosubS;
|
||||
this.label = label;
|
||||
this.sc = sc;
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
stderr.writeln("can't execute");
|
||||
stderr.writeln("can't execute (compiler bug?)");
|
||||
}
|
||||
}
|
||||
class ReturnSubroutine : Code
|
||||
@@ -829,7 +833,7 @@ class CallFunctionCode : Code
|
||||
}
|
||||
override void execute(VM vm)
|
||||
{
|
||||
Function func = vm.functions[name];
|
||||
Function func = vm.functions.get(name, null);
|
||||
if(!func)
|
||||
{
|
||||
throw new SyntaxError();
|
||||
|
||||
@@ -102,6 +102,20 @@ class BuiltinFunction
|
||||
}
|
||||
assert(cond, message.to!string);
|
||||
}
|
||||
static int BUTTON(PetitComputer p, DefaultValue!(int, false) mode)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static void VISIBLE(PetitComputer p, DefaultValue!(int) console, DefaultValue!(int) graphic, DefaultValue!(int) BG, DefaultValue!(int) sprite)
|
||||
{
|
||||
}
|
||||
static void XSCREEN(PetitComputer p, int mode, DefaultValue!(int, false) a, DefaultValue!(int, false) b)
|
||||
{
|
||||
}
|
||||
static void DISPLAY(PetitComputer p, DefaultValue!(int) display)
|
||||
{
|
||||
}
|
||||
|
||||
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
|
||||
static BuiltinFunction[wstring] builtinFunctions;
|
||||
static this()
|
||||
@@ -148,6 +162,10 @@ template GetFunctionReturnType(T, string N)
|
||||
{
|
||||
enum GetFunctionReturnType = ValueType.Double;
|
||||
}
|
||||
else static if(is(ReturnType!(__traits(getMember, T, N)) == int))
|
||||
{
|
||||
enum GetFunctionReturnType = ValueType.Integer;
|
||||
}
|
||||
else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
|
||||
{
|
||||
enum GetFunctionReturnType = ValueType.Void;
|
||||
@@ -160,7 +178,7 @@ template GetFunctionReturnType(T, string N)
|
||||
}
|
||||
template AddFunc(T, string N)
|
||||
{
|
||||
static if(is(ReturnType!(__traits(getMember, T, N)) == double))
|
||||
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 ~ "(" ~
|
||||
AddFuncArg!(ParameterTypeTuple!(__traits(getMember, T, N)).length - 1, 0, 0, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";
|
||||
|
||||
@@ -10,20 +10,37 @@ class Scope
|
||||
GotoAddr breakAddr;
|
||||
GotoAddr continueAddr;
|
||||
Function func;
|
||||
DataTable data;
|
||||
this()
|
||||
{
|
||||
this.data = new DataTable();
|
||||
}
|
||||
this(GotoAddr breakAddr, GotoAddr continueAddr, Scope parent)
|
||||
{
|
||||
this.breakAddr = breakAddr;
|
||||
this.continueAddr = continueAddr;
|
||||
this.func = parent.func;
|
||||
this.data = parent.data;
|
||||
}
|
||||
this(Function func)
|
||||
{
|
||||
this();
|
||||
this.func = func;
|
||||
}
|
||||
}
|
||||
class DataTable
|
||||
{
|
||||
Value[] data;
|
||||
int[wstring] label;
|
||||
void addData(Value data)
|
||||
{
|
||||
this.data ~= data;
|
||||
}
|
||||
void addLabel(wstring label)
|
||||
{
|
||||
this.label[label] = data.length;
|
||||
}
|
||||
}
|
||||
class Function
|
||||
{
|
||||
int address;
|
||||
@@ -185,13 +202,13 @@ class Compiler
|
||||
{
|
||||
code ~= new Operate(op);
|
||||
}
|
||||
void genCodeGoto(wstring label)
|
||||
void genCodeGoto(wstring label, Scope sc)
|
||||
{
|
||||
code ~= new GotoS(label);
|
||||
code ~= new GotoS(label, sc);
|
||||
}
|
||||
void genCodeGosub(wstring label)
|
||||
void genCodeGosub(wstring label, Scope sc)
|
||||
{
|
||||
code ~= new GosubS(label);
|
||||
code ~= new GosubS(label, sc);
|
||||
}
|
||||
GotoAddr genCodeGoto()
|
||||
{
|
||||
@@ -554,12 +571,19 @@ class Compiler
|
||||
case NodeType.Label:
|
||||
{
|
||||
auto label = cast(Label)i;
|
||||
globalLabel[label.label] = code.length;
|
||||
if(s.func)
|
||||
{
|
||||
s.func.label[label.label] = code.length;
|
||||
}
|
||||
else
|
||||
{
|
||||
globalLabel[label.label] = code.length;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case NodeType.Goto:
|
||||
{
|
||||
genCodeGoto((cast(Goto)i).label);
|
||||
genCodeGoto((cast(Goto)i).label, s);
|
||||
}
|
||||
break;
|
||||
case NodeType.If:
|
||||
@@ -571,7 +595,7 @@ class Compiler
|
||||
case NodeType.Gosub:
|
||||
{
|
||||
auto gosub = cast(Gosub)i;
|
||||
genCodeGosub(gosub.label);
|
||||
genCodeGosub(gosub.label, s);
|
||||
}
|
||||
break;
|
||||
case NodeType.Return:
|
||||
@@ -666,6 +690,13 @@ class Compiler
|
||||
case NodeType.Inc:
|
||||
compileInc(cast(Inc)i, s);
|
||||
break;
|
||||
case NodeType.Data:
|
||||
{
|
||||
auto data = cast(Data)i;
|
||||
foreach(j; data.data)
|
||||
s.data.addData(j);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
stderr.writeln("Compile:NotImpl ", i.type);
|
||||
}
|
||||
@@ -686,11 +717,27 @@ class Compiler
|
||||
{
|
||||
if(c.type == CodeType.GotoS)
|
||||
{
|
||||
code[i] = new GotoAddr(globalLabel[(cast(GotoS)c).label]);
|
||||
auto label = cast(GotoS)c;
|
||||
if(label.sc.func)
|
||||
{
|
||||
code[i] = new GotoAddr(label.sc.func.label[label.label]);
|
||||
}
|
||||
else
|
||||
{
|
||||
code[i] = new GotoAddr(globalLabel[label.label]);
|
||||
}
|
||||
}
|
||||
if(c.type == CodeType.GosubS)
|
||||
{
|
||||
code[i] = new GosubAddr(globalLabel[(cast(GosubS)c).label]);
|
||||
auto label = cast(GosubS)c;
|
||||
if(label.sc.func)
|
||||
{
|
||||
code[i] = new GosubAddr(label.sc.func.label[label.label]);
|
||||
}
|
||||
else
|
||||
{
|
||||
code[i] = new GosubAddr(globalLabel[label.label]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new VM(code, globalIndex + 1, global, functions);
|
||||
|
||||
@@ -36,6 +36,9 @@ enum NodeType
|
||||
DefineFunction,
|
||||
While,
|
||||
Inc,
|
||||
Data,
|
||||
Read,
|
||||
Restore,
|
||||
}
|
||||
abstract class Node
|
||||
{
|
||||
@@ -432,3 +435,16 @@ class Inc : Statement
|
||||
this.expression = expr;
|
||||
}
|
||||
}
|
||||
class Data : Statement
|
||||
{
|
||||
Value[] data;
|
||||
this()
|
||||
{
|
||||
this.type = NodeType.Data;
|
||||
this.data = new Value[0];
|
||||
}
|
||||
void addData(Value v)
|
||||
{
|
||||
data ~= v;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,6 +64,9 @@ class Lexical
|
||||
reserved["WEND"] = TokenType.WEnd;
|
||||
reserved["INC"] = TokenType.Inc;
|
||||
reserved["DEC"] = TokenType.Dec;
|
||||
reserved["DATA"] = TokenType.Data;
|
||||
reserved["READ"] = TokenType.Read;
|
||||
reserved["RESTORE"] = TokenType.Restore;
|
||||
reserved.rehash();
|
||||
line = 1;
|
||||
}
|
||||
@@ -168,7 +171,7 @@ class Lexical
|
||||
for(;i < code.length;i++)
|
||||
{
|
||||
c = code[i];
|
||||
if(!c.isAlpha())
|
||||
if(!c.isAlpha() && !c.isDigit() && c != '_')
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -506,21 +509,25 @@ class Parser
|
||||
else
|
||||
{
|
||||
//MEMO:引数に[]を付けようが扱いは同一
|
||||
while(true)
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.Iden)
|
||||
{
|
||||
wstring arg = getFunctionArgument();
|
||||
if(arg.length == 0)
|
||||
while(true)
|
||||
{
|
||||
return null;
|
||||
wstring arg = getFunctionArgument();
|
||||
if(arg.length == 0)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
node.addArgument(arg);
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.Comma)
|
||||
{
|
||||
lex.popFront();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
node.addArgument(arg);
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.Comma)
|
||||
{
|
||||
lex.popFront();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(token.type == TokenType.Out)
|
||||
{
|
||||
@@ -680,7 +687,11 @@ class Parser
|
||||
token = lex.front();
|
||||
}
|
||||
else
|
||||
func.addArg(expression());
|
||||
{
|
||||
auto expr = expression();
|
||||
if(expr)
|
||||
func.addArg(expr);
|
||||
}
|
||||
if(lex.front().type != TokenType.Comma) break;
|
||||
lex.popFront();
|
||||
}
|
||||
@@ -772,6 +783,8 @@ class Parser
|
||||
case TokenType.Inc:
|
||||
case TokenType.Dec:
|
||||
return incStatement();
|
||||
case TokenType.Data:
|
||||
return dataStatement();
|
||||
default:
|
||||
syntaxError();
|
||||
break;
|
||||
@@ -779,6 +792,31 @@ class Parser
|
||||
lex.popFront();
|
||||
return node;
|
||||
}
|
||||
Data dataStatement()
|
||||
{
|
||||
Data data = new Data();
|
||||
lex.popFront();
|
||||
auto token = lex.front();
|
||||
while(true)
|
||||
{
|
||||
if(token.type != TokenType.String && token.type != TokenType.Integer)
|
||||
{
|
||||
syntaxError();
|
||||
return null;
|
||||
}
|
||||
data.addData(token.value);
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
if(token.type == TokenType.Comma)
|
||||
{
|
||||
lex.popFront();
|
||||
token = lex.front();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
Inc incStatement()
|
||||
{
|
||||
auto token = lex.front();
|
||||
|
||||
@@ -75,6 +75,8 @@ class PetitComputer
|
||||
GraphicPage GRPF;
|
||||
GraphicPage[] GRPFColor;
|
||||
GraphicPage[][] GRPFColorFore;
|
||||
SDL_Surface* s8x8;
|
||||
SDL_Texture* t8x8;
|
||||
//PNG画像から透過色のpixelを指定して透過しGRPを作る
|
||||
GraphicPage createGraphicPage(string file, int pixel)
|
||||
{
|
||||
@@ -223,12 +225,22 @@ class PetitComputer
|
||||
fontFile);
|
||||
}
|
||||
GRPF = createGraphicPage(fontFile, 0);
|
||||
GRPFColor = new GraphicPage[consoleColor.length];
|
||||
GRPFColorFore = new GraphicPage[][consoleColor.length];
|
||||
for(int i = 0; i < GRPFColor.length; i++)
|
||||
s8x8 = SDL_CreateRGBSurface(0, 8, 8, 32, 0, 0, 0, 0);
|
||||
auto pixels = (cast(uint*)s8x8.pixels);
|
||||
for(int x = 0; x < 8; x++)
|
||||
{
|
||||
GRPFColor[i] = createGRPF(i, GRPF.surface);
|
||||
for(int y = 0; y < 8; y++)
|
||||
{
|
||||
*pixels = SDL_MapRGBA(s8x8.format, 255, 255, 255, 255);
|
||||
pixels++;
|
||||
}
|
||||
}
|
||||
//GRPFColor = new GraphicPage[consoleColor.length];
|
||||
//GRPFColorFore = new GraphicPage[][consoleColor.length];
|
||||
//for(int i = 0; i < GRPFColor.length; i++)
|
||||
//{
|
||||
// GRPFColor[i] = createGRPF(i, GRPF.surface);
|
||||
//}
|
||||
/+for(int i = 0; i < GRPFColor.length; i++)
|
||||
{
|
||||
GRPFColorFore[i] = new GraphicPage[consoleColor.length];
|
||||
@@ -289,6 +301,9 @@ class PetitComputer
|
||||
vsyncCount = 0;
|
||||
vsyncFrame = f;
|
||||
}
|
||||
int keybufferpos;
|
||||
//解析した結果キー入力のバッファは127くらい
|
||||
wchar[] keybuffer = new wchar[127];
|
||||
void render()
|
||||
{
|
||||
bool renderprofile;
|
||||
@@ -299,10 +314,11 @@ class PetitComputer
|
||||
SDL_WINDOW_SHOWN);
|
||||
renderer = SDL_CreateRenderer(window, -1, 0);
|
||||
GRPF.createTexture(renderer);
|
||||
for(int i = 0; i < GRPFColor.length; i++)
|
||||
/*for(int i = 0; i < GRPFColor.length; i++)
|
||||
{
|
||||
GRPFColor[i].createTexture(renderer);
|
||||
}
|
||||
}*/
|
||||
t8x8 = SDL_CreateTextureFromSurface(renderer, s8x8);
|
||||
write("OK!");
|
||||
SDL_Event event;
|
||||
while(true)
|
||||
@@ -313,7 +329,6 @@ class PetitComputer
|
||||
renderConsole;
|
||||
SDL_RenderPresent(renderer);
|
||||
auto a = (SDL_GetTicks() - profile);
|
||||
if(renderprofile) writeln(a);
|
||||
while (SDL_PollEvent(&event))
|
||||
{
|
||||
switch (event.type)
|
||||
@@ -322,11 +337,16 @@ class PetitComputer
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
return;
|
||||
|
||||
case SDL_KEYDOWN:
|
||||
auto key = event.key.keysym.sym;
|
||||
keybuffer[keybufferpos] = cast(wchar)key;
|
||||
keybufferpos = (keybufferpos + 1) % keybuffer.length;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!renderprofile) writeln(a);
|
||||
}
|
||||
}
|
||||
catch(Throwable t)
|
||||
@@ -347,8 +367,10 @@ class PetitComputer
|
||||
}
|
||||
}+/
|
||||
//とりあえず
|
||||
auto parser = new Parser(readText("TEST.TXT").to!wstring/*readText("FIZZBUZZ.TXT").to!wstring*//*"
|
||||
?ABS(-1)
|
||||
auto parser = new Parser(//readText("./SYS/EX1TEXT.TXT").to!wstring
|
||||
//readText("FIZZBUZZ.TXT").to!wstring
|
||||
readText("TEST.TXT").to!wstring
|
||||
/*"?ABS(-1)
|
||||
LOCATE 0,10
|
||||
COLOR 5
|
||||
FOR I=0 TO 10
|
||||
@@ -357,12 +379,9 @@ NEXT
|
||||
DEF FACT(N)
|
||||
IF N<=1 THEN RETURN 1
|
||||
RETURN N*FACT(N-1)
|
||||
END"*//*
|
||||
END"*/
|
||||
/*
|
||||
`CLS : CL=0 : Z=0
|
||||
WHILE 1
|
||||
INC Z,2
|
||||
?Z,
|
||||
WEND
|
||||
WHILE 1
|
||||
INC Z : IF Z>200 THEN Z=0
|
||||
FOR I=0 TO 15
|
||||
@@ -370,7 +389,8 @@ WHILE 1
|
||||
PRINT "★ 梅雨で雨が多い季節ですね ★"
|
||||
NEXT
|
||||
CL=(CL+1) MOD 16 : VSYNC 2
|
||||
WEND`*//*
|
||||
WEND`*/
|
||||
/*
|
||||
`CLS : CL=0
|
||||
WHILE 1
|
||||
FOR I=0 TO 15
|
||||
@@ -436,6 +456,11 @@ GOTO @LOOP`*/
|
||||
SDL_DestroyWindow(window);
|
||||
SDL_Quit();
|
||||
}
|
||||
wstring input(wstring prompt, bool useClipBoard)
|
||||
{
|
||||
printConsole(prompt);
|
||||
return "";
|
||||
}
|
||||
int CSRX;
|
||||
int CSRY;
|
||||
int CSRZ;
|
||||
@@ -449,10 +474,15 @@ GOTO @LOOP`*/
|
||||
for(int x = 0; x < consoleWidth; x++)
|
||||
{
|
||||
SDL_Rect rect = SDL_Rect(x * 8, y * 8, 8, 8);
|
||||
auto back = console[y][x].backColor;
|
||||
auto fore = consoleColor[console[y][x].foreColor];
|
||||
auto back = consoleColor[console[y][x].backColor];
|
||||
SDL_SetTextureColorMod(t8x8, back >> 16 & 0xFF, back >> 8 & 0xFF, back & 0xFF);
|
||||
SDL_SetTextureAlphaMod(t8x8, back >> 24 & 0xFF);
|
||||
SDL_RenderCopy(renderer, t8x8, null, &rect);
|
||||
/*
|
||||
auto texture = GRPFColor[back].texture;
|
||||
SDL_RenderCopy(renderer, texture, &fontTable[console[y][x].charater], &rect);
|
||||
auto back = console[y][x].backColor;
|
||||
SDL_RenderCopy(renderer, texture, &fontTable[console[y][x].charater], &rect);*/
|
||||
SDL_SetTextureColorMod(GRPF.texture, fore >> 16 & 0xFF, fore >> 8 & 0xFF, fore & 0xFF);
|
||||
SDL_SetTextureAlphaMod(GRPF.texture, fore >> 24 & 0xFF);
|
||||
SDL_RenderCopy(renderer, GRPF.texture, &fontTable[console[y][x].charater], &rect);
|
||||
|
||||
@@ -58,6 +58,9 @@ enum TokenType
|
||||
WEnd,
|
||||
Inc,
|
||||
Dec,
|
||||
Data,
|
||||
Read,
|
||||
Restore,
|
||||
}
|
||||
|
||||
struct Token
|
||||
|
||||
Reference in New Issue
Block a user