1 module checker
is aliced
;
9 // ////////////////////////////////////////////////////////////////////////// //
10 NodeFunc
[] loadScript (string filename
, bool warnings
=true) {
11 import std
.algorithm
: startsWith
;
12 import std
.file
: readText
;
13 import std
.path
: baseName
, extension
;
15 import std
.string
: replace
;
17 auto s
= readText(filename
);
20 auto parser
= new Parser(s
, filename
);
21 parser
.warnings
= warnings
;
22 bool asGmx
= (filename
.extension
== ".gmx");
25 while (!parser
.lex
.empty
) res
~= parser
.parseFunction();
27 string scname
= filename
.baseName(".gml");
28 res
~= parser
.parseFunctionBody(scname
);
30 assert(parser
.lex
.empty
);
33 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
34 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
36 } catch (Exception e
) {
38 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
45 // ////////////////////////////////////////////////////////////////////////// //
46 NodeFunc
parseScript (string code
, string scname
, bool warnings
=true) {
47 auto parser
= new Parser(code
, scname
);
48 parser
.warnings
= warnings
;
50 return parser
.parseFunctionBody(scname
);
53 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
54 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
57 } catch (Exception e
) {
59 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
66 // ////////////////////////////////////////////////////////////////////////// //
67 NodeFunc
[] gmkLoadScripts (Gmk gmk
) {
72 void setupObject (GMObject obj
, GMObject oparent
) {
73 string parent
= (oparent
!is null ? oparent
.name
: null);
75 void parseECode (ref string evcode
, string evname
) {
77 import std
.string
: replace
;
78 scope(exit
) evcode
= null;
79 evcode
= evcode
.replace("\r\n", "\n").replace("\r", "\n").outdentAll
;
80 //while (evcode.length && evcode[0] <= ' ') evcode = evcode[1..$];
81 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
83 auto fn
= evcode
.parseScript(obj
.name
~":"~evname
);
85 if (hasReturn(fn
)) throw new Exception("event '"~evname
~"' for object '"~obj
.name
~"' contains `return`");
91 void createEvent (GMEvent
.Type evtype
) {
94 foreach (immutable evidx
, auto ev
; obj
.events
[evtype
]) {
95 foreach (immutable aidx
, auto act
; ev
.actions
) {
96 if (act
.type
== act
.Type
.Nothing
) continue; // comment
97 if (act
.kind
== act
.Kind
.act_normal
) {
99 if (act
.type
== act
.Type
.Function
) {
100 if (act
.funcname
== "action_inherited") {
101 assert(parent
.length
);
102 evcode
~= "_action_inherited(\""~to
!string(evtype
)~"\", \""~parent
~"\");\n";
105 if (act
.funcname
== "action_kill_object") {
106 evcode
~= "_action_kill_object();\n";
109 if (act
.funcname
== "action_execute_script") {
110 import std
.conv
: to
;
111 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_script
) assert(0, "invalid action function arguments: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
112 string s
= gmk
.scriptByNum(to
!int(act
.argvals
[0])).name
~"(";
113 foreach (immutable idx
; 1..act
.argused
) {
114 if (act
.argtypes
[idx
] != act
.ArgType
.t_expr
) assert(0, "invalid action type for execscript: "~to
!string(act
.argtypes
[idx
])~" for object '"~obj
.name
~"'");
115 if (idx
!= 1) s
~= ", ";
116 s
~= act
.argvals
[idx
];
118 s
~= "); // action_execute_script\n";
122 assert(0, "invalid action function: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
124 assert(0, "invalid normal action type");
126 if (act
.kind
== act
.Kind
.act_code
) {
128 if (act
.type
== act
.Type
.Code
) {
129 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_string
) {
130 import std
.conv
: to
;
131 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
133 import std
.string
: format
;
134 evcode
~= act
.argvals
[0];
135 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
136 if (evcode
.length
> 0) evcode
~= "\n";
139 assert(0, "invalid code action type: "~to
!string(act
.type
));
141 if (act
.kind
== act
.Kind
.act_var
) {
142 // variable assignment
143 if (act
.argused
!= 2 || act
.argtypes
[0] != act
.ArgType
.t_string || act
.argtypes
[1] != act
.ArgType
.t_expr
) {
144 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
146 evcode
~= act
.argvals
[0]~" = "~act
.argvals
[1]~"; // act_var";
150 assert(0, "FUUUCK: "~to
!string(act
.kind
));
153 if (evtype
== GMEvent
.Type
.ev_alarm
) {
154 parseECode(evcode
, to
!string(evtype
)~":"~to
!string(evidx
));
155 //{ import std.stdio; writeln("alarm #", evidx, " for '", obj.name, "'"); }
156 } else if (evtype
== GMEvent
.Type
.ev_step
) {
159 parseECode(evcode
, to
!string(evtype
));
160 } else if (evidx
== 1) {
162 parseECode(evcode
, to
!string(evtype
)~":begin");
163 } else if (evidx
== 2) {
165 parseECode(evcode
, to
!string(evtype
)~":end");
169 } else if (evtype
== GMEvent
.Type
.ev_keypress
) {
170 if (auto keyName
= cast(uint)evidx
in evKeyNames
) {
171 import std
.string
: replace
;
172 string kn
= (*keyName
).replace(" ", "_");
173 parseECode(evcode
, to
!string(evtype
)~"_"~kn
);
175 parseECode(evcode
, to
!string(evtype
)~"_vcode_"~to
!string(evidx
));
177 } else if (evtype
== GMEvent
.Type
.ev_keyboard
) {
178 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
));
179 } else if (evtype
== GMEvent
.Type
.ev_mouse
) {
180 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
));
181 } else if (evtype
== GMEvent
.Type
.ev_collision
) {
182 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
));
183 } else if (evtype
== GMEvent
.Type
.ev_other
) {
184 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
));
187 { import std
.stdio
; writeln("fuck! ", evtype
, " #", evidx
, " for '", obj
.name
, "'"); }
190 parseECode(evcode
, to
!string(evtype
));
195 foreach (immutable evtype
; 0..GMEvent
.Type
.max
+1) {
196 if (evtype
!= GMEvent
.Type
.ev_create
) {
197 if (obj
.name
== "oGamepad") continue;
199 createEvent(cast(GMEvent
.Type
)evtype
);
203 void processChildren (string parent
) {
204 auto po
= gmk
.objByName(parent
);
205 if (po
is null) assert(0, "wtf?! "~parent
);
206 gmk
.forEachObject((o
) {
207 if (o
.parentobjidx
== po
.idx
) {
209 processChildren(o
.name
);
216 gmk
.forEachObject((o
) {
217 if (o
.parentobjidx
< 0) {
218 setupObject(o
, null);
219 processChildren(o
.name
);
225 gmk
.forEachScript((sc
) {
226 assert(sc
.name
.length
);
227 NodeFunc fn
= sc
.code
.parseScript(sc
.name
);
228 assert(fn
.ebody
!is null);
237 // ////////////////////////////////////////////////////////////////////////// //
238 void main (string
[] args
) {
241 bool dumpFileNames
= false;
242 bool styleWarnings
= false;
246 foreach (string fname
; args
[1..$]) {
252 if (fname
.length
== 0) continue;
253 if (fname
== "--") { nomore
= true; continue; }
254 if (fname
== "-d") { dumpFileNames
= true; continue; }
255 if (fname
== "-w") { styleWarnings
= true; continue; }
256 if (fname
[0] == '@') {
257 if (fname
.length
< 2) assert(0, "gmk file?");
258 auto gmk
= new Gmk(fname
[1..$]);
259 funcs
~= gmkLoadScripts(gmk
);
263 foreach (auto de; dirEntries(fname
, "*.gm[lx]", SpanMode
.breadth
)) {
265 foreach (auto pt
; pathSplitter(de.dirName
)) {
266 if (pt
.length
&& pt
[0] == '_') { doit
= false; break; }
269 if (dumpFileNames
) { import std
.stdio
; writeln("loading '", de.name
, "'..."); }
270 funcs
~= loadScript(de.name
, true);
274 if (dumpFileNames
) { import std
.stdio
; writeln("loading '", fname
, "'..."); }
275 funcs
~= loadScript(fname
, true);
280 if (funcs
.length
> 1) {
281 writeln(funcs
.length
, " functions parsed");