1
0

関数内ラベル実装と引数なし関数を正常に呼べるようにした

This commit is contained in:
otya128
2015-07-13 21:39:42 +09:00
parent b51fe86fd6
commit 5dff13b64f
8 changed files with 215 additions and 47 deletions

View File

@@ -24,6 +24,18 @@ DEF INCTEST A
DEC A DEC A
ASSERT__ A==10, "A==10" ASSERT__ A==10, "A==10"
END 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, LOCATE 10,
COLOR 1,15 COLOR 1,15
PRINT "テスト正常終了" PRINT "テスト正常終了"

View File

@@ -486,14 +486,16 @@ class GotoAddr : Code
class GotoS : Code class GotoS : Code
{ {
wstring label; wstring label;
this(wstring label) Scope sc;
this(wstring label, Scope sc)
{ {
this.type = CodeType.GotoS; this.type = CodeType.GotoS;
this.label = label; this.label = label;
this.sc = sc;
} }
override void execute(VM vm) override void execute(VM vm)
{ {
stderr.writeln("can't execute"); stderr.writeln("can't execute (compiler bug?)");
} }
} }
class GotoTrue : Code class GotoTrue : Code
@@ -545,14 +547,16 @@ class GosubAddr : Code
class GosubS : Code class GosubS : Code
{ {
wstring label; wstring label;
this(wstring label) Scope sc;
this(wstring label, Scope sc)
{ {
this.type = CodeType.GosubS; this.type = CodeType.GosubS;
this.label = label; this.label = label;
this.sc = sc;
} }
override void execute(VM vm) override void execute(VM vm)
{ {
stderr.writeln("can't execute"); stderr.writeln("can't execute (compiler bug?)");
} }
} }
class ReturnSubroutine : Code class ReturnSubroutine : Code
@@ -829,7 +833,7 @@ class CallFunctionCode : Code
} }
override void execute(VM vm) override void execute(VM vm)
{ {
Function func = vm.functions[name]; Function func = vm.functions.get(name, null);
if(!func) if(!func)
{ {
throw new SyntaxError(); throw new SyntaxError();

View File

@@ -102,6 +102,20 @@ class BuiltinFunction
} }
assert(cond, message.to!string); 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; //alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
static BuiltinFunction[wstring] builtinFunctions; static BuiltinFunction[wstring] builtinFunctions;
static this() static this()
@@ -148,6 +162,10 @@ template GetFunctionReturnType(T, string N)
{ {
enum GetFunctionReturnType = ValueType.Double; 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)) else static if(is(ReturnType!(__traits(getMember, T, N)) == void))
{ {
enum GetFunctionReturnType = ValueType.Void; enum GetFunctionReturnType = ValueType.Void;
@@ -160,7 +178,7 @@ template GetFunctionReturnType(T, string N)
} }
template AddFunc(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 ~ "(" ~ 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 - 1, 0, 0, ParameterTypeTuple!(__traits(getMember, T, N))) ~ "));}";

View File

@@ -10,20 +10,37 @@ class Scope
GotoAddr breakAddr; GotoAddr breakAddr;
GotoAddr continueAddr; GotoAddr continueAddr;
Function func; Function func;
DataTable data;
this() this()
{ {
this.data = new DataTable();
} }
this(GotoAddr breakAddr, GotoAddr continueAddr, Scope parent) this(GotoAddr breakAddr, GotoAddr continueAddr, Scope parent)
{ {
this.breakAddr = breakAddr; this.breakAddr = breakAddr;
this.continueAddr = continueAddr; this.continueAddr = continueAddr;
this.func = parent.func; this.func = parent.func;
this.data = parent.data;
} }
this(Function func) this(Function func)
{ {
this();
this.func = func; 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 class Function
{ {
int address; int address;
@@ -185,13 +202,13 @@ class Compiler
{ {
code ~= new Operate(op); 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() GotoAddr genCodeGoto()
{ {
@@ -554,12 +571,19 @@ class Compiler
case NodeType.Label: case NodeType.Label:
{ {
auto label = cast(Label)i; 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; break;
case NodeType.Goto: case NodeType.Goto:
{ {
genCodeGoto((cast(Goto)i).label); genCodeGoto((cast(Goto)i).label, s);
} }
break; break;
case NodeType.If: case NodeType.If:
@@ -571,7 +595,7 @@ class Compiler
case NodeType.Gosub: case NodeType.Gosub:
{ {
auto gosub = cast(Gosub)i; auto gosub = cast(Gosub)i;
genCodeGosub(gosub.label); genCodeGosub(gosub.label, s);
} }
break; break;
case NodeType.Return: case NodeType.Return:
@@ -666,6 +690,13 @@ class Compiler
case NodeType.Inc: case NodeType.Inc:
compileInc(cast(Inc)i, s); compileInc(cast(Inc)i, s);
break; break;
case NodeType.Data:
{
auto data = cast(Data)i;
foreach(j; data.data)
s.data.addData(j);
}
break;
default: default:
stderr.writeln("Compile:NotImpl ", i.type); stderr.writeln("Compile:NotImpl ", i.type);
} }
@@ -686,11 +717,27 @@ class Compiler
{ {
if(c.type == CodeType.GotoS) 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) 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); return new VM(code, globalIndex + 1, global, functions);

View File

@@ -36,6 +36,9 @@ enum NodeType
DefineFunction, DefineFunction,
While, While,
Inc, Inc,
Data,
Read,
Restore,
} }
abstract class Node abstract class Node
{ {
@@ -432,3 +435,16 @@ class Inc : Statement
this.expression = expr; this.expression = expr;
} }
} }
class Data : Statement
{
Value[] data;
this()
{
this.type = NodeType.Data;
this.data = new Value[0];
}
void addData(Value v)
{
data ~= v;
}
}

View File

@@ -64,6 +64,9 @@ class Lexical
reserved["WEND"] = TokenType.WEnd; reserved["WEND"] = TokenType.WEnd;
reserved["INC"] = TokenType.Inc; reserved["INC"] = TokenType.Inc;
reserved["DEC"] = TokenType.Dec; reserved["DEC"] = TokenType.Dec;
reserved["DATA"] = TokenType.Data;
reserved["READ"] = TokenType.Read;
reserved["RESTORE"] = TokenType.Restore;
reserved.rehash(); reserved.rehash();
line = 1; line = 1;
} }
@@ -168,7 +171,7 @@ class Lexical
for(;i < code.length;i++) for(;i < code.length;i++)
{ {
c = code[i]; c = code[i];
if(!c.isAlpha()) if(!c.isAlpha() && !c.isDigit() && c != '_')
{ {
break; break;
} }
@@ -506,21 +509,25 @@ class Parser
else else
{ {
//MEMO:引数に[]を付けようが扱いは同一 //MEMO:引数に[]を付けようが扱いは同一
while(true) token = lex.front();
if(token.type == TokenType.Iden)
{ {
wstring arg = getFunctionArgument(); while(true)
if(arg.length == 0)
{ {
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) if(token.type == TokenType.Out)
{ {
@@ -680,7 +687,11 @@ class Parser
token = lex.front(); token = lex.front();
} }
else else
func.addArg(expression()); {
auto expr = expression();
if(expr)
func.addArg(expr);
}
if(lex.front().type != TokenType.Comma) break; if(lex.front().type != TokenType.Comma) break;
lex.popFront(); lex.popFront();
} }
@@ -772,6 +783,8 @@ class Parser
case TokenType.Inc: case TokenType.Inc:
case TokenType.Dec: case TokenType.Dec:
return incStatement(); return incStatement();
case TokenType.Data:
return dataStatement();
default: default:
syntaxError(); syntaxError();
break; break;
@@ -779,6 +792,31 @@ class Parser
lex.popFront(); lex.popFront();
return node; 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() Inc incStatement()
{ {
auto token = lex.front(); auto token = lex.front();

View File

@@ -75,6 +75,8 @@ class PetitComputer
GraphicPage GRPF; GraphicPage GRPF;
GraphicPage[] GRPFColor; GraphicPage[] GRPFColor;
GraphicPage[][] GRPFColorFore; GraphicPage[][] GRPFColorFore;
SDL_Surface* s8x8;
SDL_Texture* t8x8;
//PNG画像から透過色のpixelを指定して透過しGRPを作る //PNG画像から透過色のpixelを指定して透過しGRPを作る
GraphicPage createGraphicPage(string file, int pixel) GraphicPage createGraphicPage(string file, int pixel)
{ {
@@ -223,12 +225,22 @@ class PetitComputer
fontFile); fontFile);
} }
GRPF = createGraphicPage(fontFile, 0); GRPF = createGraphicPage(fontFile, 0);
GRPFColor = new GraphicPage[consoleColor.length]; s8x8 = SDL_CreateRGBSurface(0, 8, 8, 32, 0, 0, 0, 0);
GRPFColorFore = new GraphicPage[][consoleColor.length]; auto pixels = (cast(uint*)s8x8.pixels);
for(int i = 0; i < GRPFColor.length; i++) 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++) /+for(int i = 0; i < GRPFColor.length; i++)
{ {
GRPFColorFore[i] = new GraphicPage[consoleColor.length]; GRPFColorFore[i] = new GraphicPage[consoleColor.length];
@@ -289,6 +301,9 @@ class PetitComputer
vsyncCount = 0; vsyncCount = 0;
vsyncFrame = f; vsyncFrame = f;
} }
int keybufferpos;
//解析した結果キー入力のバッファは127くらい
wchar[] keybuffer = new wchar[127];
void render() void render()
{ {
bool renderprofile; bool renderprofile;
@@ -299,10 +314,11 @@ class PetitComputer
SDL_WINDOW_SHOWN); SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, 0); renderer = SDL_CreateRenderer(window, -1, 0);
GRPF.createTexture(renderer); GRPF.createTexture(renderer);
for(int i = 0; i < GRPFColor.length; i++) /*for(int i = 0; i < GRPFColor.length; i++)
{ {
GRPFColor[i].createTexture(renderer); GRPFColor[i].createTexture(renderer);
} }*/
t8x8 = SDL_CreateTextureFromSurface(renderer, s8x8);
write("OK!"); write("OK!");
SDL_Event event; SDL_Event event;
while(true) while(true)
@@ -313,7 +329,6 @@ class PetitComputer
renderConsole; renderConsole;
SDL_RenderPresent(renderer); SDL_RenderPresent(renderer);
auto a = (SDL_GetTicks() - profile); auto a = (SDL_GetTicks() - profile);
if(renderprofile) writeln(a);
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
switch (event.type) switch (event.type)
@@ -322,11 +337,16 @@ class PetitComputer
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();
return; return;
case SDL_KEYDOWN:
auto key = event.key.keysym.sym;
keybuffer[keybufferpos] = cast(wchar)key;
keybufferpos = (keybufferpos + 1) % keybuffer.length;
break;
default: default:
break; break;
} }
} }
if(!renderprofile) writeln(a);
} }
} }
catch(Throwable t) catch(Throwable t)
@@ -347,8 +367,10 @@ class PetitComputer
} }
}+/ }+/
//とりあえず //とりあえず
auto parser = new Parser(readText("TEST.TXT").to!wstring/*readText("FIZZBUZZ.TXT").to!wstring*//*" auto parser = new Parser(//readText("./SYS/EX1TEXT.TXT").to!wstring
?ABS(-1) //readText("FIZZBUZZ.TXT").to!wstring
readText("TEST.TXT").to!wstring
/*"?ABS(-1)
LOCATE 0,10 LOCATE 0,10
COLOR 5 COLOR 5
FOR I=0 TO 10 FOR I=0 TO 10
@@ -357,12 +379,9 @@ NEXT
DEF FACT(N) DEF FACT(N)
IF N<=1 THEN RETURN 1 IF N<=1 THEN RETURN 1
RETURN N*FACT(N-1) RETURN N*FACT(N-1)
END"*//* END"*/
/*
`CLS : CL=0 : Z=0 `CLS : CL=0 : Z=0
WHILE 1
INC Z,2
?Z,
WEND
WHILE 1 WHILE 1
INC Z : IF Z>200 THEN Z=0 INC Z : IF Z>200 THEN Z=0
FOR I=0 TO 15 FOR I=0 TO 15
@@ -370,7 +389,8 @@ WHILE 1
PRINT "★ 梅雨で雨が多い季節ですね ★" PRINT "★ 梅雨で雨が多い季節ですね ★"
NEXT NEXT
CL=(CL+1) MOD 16 : VSYNC 2 CL=(CL+1) MOD 16 : VSYNC 2
WEND`*//* WEND`*/
/*
`CLS : CL=0 `CLS : CL=0
WHILE 1 WHILE 1
FOR I=0 TO 15 FOR I=0 TO 15
@@ -436,6 +456,11 @@ GOTO @LOOP`*/
SDL_DestroyWindow(window); SDL_DestroyWindow(window);
SDL_Quit(); SDL_Quit();
} }
wstring input(wstring prompt, bool useClipBoard)
{
printConsole(prompt);
return "";
}
int CSRX; int CSRX;
int CSRY; int CSRY;
int CSRZ; int CSRZ;
@@ -449,10 +474,15 @@ GOTO @LOOP`*/
for(int x = 0; x < consoleWidth; x++) for(int x = 0; x < consoleWidth; x++)
{ {
SDL_Rect rect = SDL_Rect(x * 8, y * 8, 8, 8); 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 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; 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_SetTextureColorMod(GRPF.texture, fore >> 16 & 0xFF, fore >> 8 & 0xFF, fore & 0xFF);
SDL_SetTextureAlphaMod(GRPF.texture, fore >> 24 & 0xFF); SDL_SetTextureAlphaMod(GRPF.texture, fore >> 24 & 0xFF);
SDL_RenderCopy(renderer, GRPF.texture, &fontTable[console[y][x].charater], &rect); SDL_RenderCopy(renderer, GRPF.texture, &fontTable[console[y][x].charater], &rect);

View File

@@ -58,6 +58,9 @@ enum TokenType
WEnd, WEnd,
Inc, Inc,
Dec, Dec,
Data,
Read,
Restore,
} }
struct Token struct Token