ファイルを扱えるようにした
This commit is contained in:
@@ -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" />
|
||||
|
||||
@@ -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 = "";
|
||||
|
||||
@@ -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
118
SMILEBASIC/project.d
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user