1
0

ファイルを扱えるようにした

This commit is contained in:
otya128
2016-02-23 21:24:55 +09:00
parent e3487276b9
commit fbf8c884b0
4 changed files with 225 additions and 7 deletions

View File

@@ -214,6 +214,7 @@
<File path="node.d" />
<File path="parser.d" />
<File path="petitcomputer.d" perConfig="true" />
<File path="project.d" />
<File path="sprite.d" />
<File path="systemvariable.d" />
<File path="TEST.txt" />

View File

@@ -43,6 +43,10 @@ struct StartOptional
{
const char[] name;
}
struct BasicName
{
wstring naame;
}
alias ValueType = otya.smilebasic.type.ValueType;
struct BuiltinFunctionArgument
{
@@ -69,7 +73,8 @@ class BuiltinFunctions
//とりあえず引数の数で解決させる,というよりコンパイル時に型を取得する方法がない
foreach(f; func)
{
if(f.startskip <= argc && f.argments.length >= argc && f.outoptional <= outargc && f.results.length >= outargc)
if(f.startskip <= argc && f.argments.length >= argc)
if((f.outoptional != 0 && f.outoptional <= outargc && f.results.length >= outargc) || f.results.length == outargc)
return f;
if(f.variadic)
va = f;
@@ -1302,8 +1307,94 @@ class BuiltinFunction
}
throw new IllegalFunctionCall("COPY (Not implemented error)");
}
@BasicName("LOAD")
static Value LOAD1(PetitComputer p, wstring name, DefaultValue!(int, false) flag)
{
import otya.smilebasic.project;
import std.string;
flag.setDefaultValue(0);
auto type = Projects.splitResourceName(name);
wstring txt;
wstring resname = type[0];
wstring projectname = type[1];
wstring filename = type[2];
if(projectname != "" && projectname != "SYS")
{
throw new IllegalFunctionCall("LOAD");
}
if(projectname == "")
{
projectname = p.currentProject;
}
if(resname == "TXT")
{
if(p.project.loadFile(projectname, resname, filename, txt))
{
return Value(txt);
}
throw new IllegalFunctionCall("LOAD");
}
throw new IllegalFunctionCall("LOAD");
}
@BasicName("LOAD")
static void LOAD2(PetitComputer p, wstring name, DefaultValue!(int, false) flag)
{
import otya.smilebasic.project;
import std.string;
flag.setDefaultValue(0);
auto type = Projects.splitResourceName(name);
wstring txt;
wstring resname = type[0];
wstring projectname = type[1];
wstring filename = type[2];
if(projectname != "" && projectname != "SYS")
{
throw new IllegalFunctionCall("LOAD");
}
if(projectname == "")
{
projectname = p.currentProject;
}
if(resname == "" || resname.indexOf("PRG") == 0)
{
int lot;
if(resname != "" && resname != "PRG")
{
auto num = resname[3..$];
lot = num.to!int;
}
if(!p.project.loadFile(projectname, "TXT", filename, txt))
{
throw new IllegalFunctionCall("LOAD");
}
p.slot[lot].load(txt);
return;
}
if(resname.indexOf("GRP") == 0)
{
throw new IllegalFunctionCall("NOTIMPL:LOAD GRP");
}
throw new IllegalFunctionCall("LOAD");
}
static Value LOAD(wstring name, Value arr, DefaultValue!(int, false) flag)
{
flag.setDefaultValue(0);
throw new IllegalFunctionCall("NOTIMPL:LOAD");
}
//alias void function(PetitComputer, Value[], Value[]) BuiltinFunc;
static BuiltinFunctions[wstring] builtinFunctions;
static wstring getBasicName(BFD)(const wstring def)
{
enum attr = __traits(getAttributes, __traits(getOverloads, BFD.C_, BFD.N)[BFD.I_]);
foreach(i; attr)
{
static if(__traits(compiles, i.naame))
{
return i.naame;
}
}
return def;
}
static this()
{
foreach(name; __traits(derivedMembers, BuiltinFunction))
@@ -1319,9 +1410,9 @@ class BuiltinFunction
{
suffix = "$";
}
wstring name2 = name ~ suffix;
auto func = builtinFunctions.get(name2, null);
alias BFD = BuiltinFunctionData!(BuiltinFunction, name, i);
wstring name2 = getBasicName!BFD(name ~ suffix);
auto func = builtinFunctions.get(name2, null);
pragma(msg, AddFunc!BFD);
auto f = new BuiltinFunction(
GetFunctionParamType!(BFD),
@@ -1435,10 +1526,6 @@ template GetBuiltinFunctionArgment(P...)
{
const string arg = "ValueType.Integer, true";
}
else static if(is(P[0] == OptionalOutValue!int))
{
const string arg = "ValueType.Integer, true";
}
else static if(is(P[0] == DefaultValue!double))
{
const string arg = "ValueType.Double, true";
@@ -1576,6 +1663,12 @@ template AddFunc(BFD)
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(BFD) - 1, 0, 0, 0, BFD,
BFD.ParameterType) ~ "));}";
}
else static if(is(BFD.ReturnType == Value))
{
const string AddFunc = "function void(PetitComputer p, Value[] arg, Value[] ret){if(ret.length != 1){throw new IllegalFunctionCall(\"" ~ BFD.N ~ "\");}ret[0] = " ~ BFD.N ~ "(" ~
AddFuncArg!(/*ParameterTypeTuple!(__traits(getMember, T, N)).length*/GetArgumentCount!(BFD) - 1, 0, 0, 0, BFD,
BFD.ParameterType) ~ ");}";
}
else
{
const string AddFunc = "";

View File

@@ -14,6 +14,7 @@ import otya.smilebasic.sprite;
import otya.smilebasic.error;
import otya.smilebasic.bg;
import otya.smilebasic.parser;
import otya.smilebasic.project;
const static rot_test_deg = 45f;
const static rot_test_x = 0f;
const static rot_test_y = 1f;
@@ -141,6 +142,7 @@ struct Slot
void load(wstring data)
{
import std.algorithm;
program.clear();
foreach(l; splitter(data, "\n"))
{
program.insertBack(l);
@@ -358,8 +360,12 @@ class PetitComputer
fontTable[record[0]].h = 8;
}
}
Projects project;
wstring currentProject;
void init()
{
currentProject = "";
project = new Projects(".");
// DerelictGL.load();
for(int i = 0; i < consoleColor.length; i++)
consoleColorGL[i] = toGLColor(consoleColor[i]);

118
SMILEBASIC/project.d Normal file
View File

@@ -0,0 +1,118 @@
module otya.smilebasic.project;
import std.path;
import std.file;
import std.string;
import std.traits;
import std.conv;
import std.uni;
import std.typecons;
class Projects
{
wstring rootPath;
wstring projectPath;
string projectPathU8;
this(wstring root)
{
rootPath = root;
projectPath = buildPath(root, "PROJECTS"w);
projectPathU8 = projectPath.to!string;
if(exists(projectPathU8))
{
if(isFile(projectPathU8))
{
throw new Exception("PROJECTS is file");
}
}
else
{
mkdir(projectPathU8);
}
createProjectInternal("[DEFAULT]");
createProjectInternal("SYS");
}
bool isValidProjectName(C)(C[] filename) if(isSomeChar!(C))
{
if(filename.length > 14)
{
return false;
}
foreach(c; filename)
{
if(!((c >= 'A' && c<= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '_' || c == '-'))
{
return false;
}
}
return true;
}
bool isValidFileName(C)(C[] filename) if(isSomeChar!(C))
{
if(filename.length > 12)
{
return false;
}
foreach(c; filename)
{
if(!((c >= 'A' && c<= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '.' || c == '_' || c == '-' || c == '@'))
{
return false;
}
}
return true;
}
private void createProjectInternal(wstring name)
{
auto path = buildPath(projectPath, name.toUpper).to!string;
if(!exists(path))
{
mkdir(path);
}
auto txt = buildPath(path, "TXT").to!string;
if(!exists(txt))
{
mkdir(txt);
}
auto dat = buildPath(path, "DAT").to!string;
if(!exists(dat))
{
mkdir(dat);
}
}
static Tuple!(wstring, wstring, wstring) splitResourceName(wstring name)
{
auto ind = name.indexOf(":");
wstring type, project;
if(ind != -1)
{
type = name[0..ind];
name = name[ind + 1..$];
}
ptrdiff_t sep = name.indexOf("/");
if(sep != -1)
{
project = name[0..sep];
name = name[sep + 1..$];
}
return tuple(type, project, name);
}
bool loadFile(wstring project, wstring type, wstring name, out wstring contents)
{
contents = "";
if(!isValidProjectName(project))
{
return false;
}
if(project == "") project = "[DEFAULT]";
if(type != "TXT" && type != "DAT")
{
return false;
}
if(!isValidFileName(name))
{
return false;
}
auto path = buildPath(projectPath, project, type, name).to!string;
contents = readText(path).to!wstring;
return true;
}
}