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
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 "テスト正常終了"

View File

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

View File

@@ -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))) ~ "));}";

View File

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

View File

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

View File

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

View File

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

View File

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