1 module checker
is aliced
;
11 // ////////////////////////////////////////////////////////////////////////// //
12 NodeFunc
[] loadScript (string filename
, bool warnings
=true) {
13 import std
.algorithm
: startsWith
;
14 import std
.file
: readText
;
15 import std
.path
: baseName
, extension
;
17 import std
.string
: replace
;
19 auto s
= readText(filename
);
22 auto parser
= new Parser(s
, filename
);
23 parser
.warnings
= warnings
;
24 bool asGmx
= (filename
.extension
== ".gmx");
27 while (!parser
.lex
.empty
) res
~= parser
.parseFunction();
29 string scname
= filename
.baseName(".gml");
30 res
~= parser
.parseFunctionBody(scname
);
32 assert(parser
.lex
.empty
);
35 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
36 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
38 } catch (Exception e
) {
40 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
47 // ////////////////////////////////////////////////////////////////////////// //
48 NodeFunc
parseScript (string code
, string scname
, bool warnings
=true) {
49 auto parser
= new Parser(code
, scname
);
50 parser
.warnings
= warnings
;
52 return parser
.parseFunctionBody(scname
);
55 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
56 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
59 } catch (Exception e
) {
61 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
68 // ////////////////////////////////////////////////////////////////////////// //
69 NodeFunc
[] gmkLoadScripts (Gmk gmk
, bool doScripts
, bool doActions
) {
74 void setupObject (GMObject obj
, GMObject oparent
) {
75 string parent
= (oparent
!is null ? oparent
.name
: null);
77 void parseECode (ref string evcode
, string evname
) {
79 import std
.string
: replace
;
80 scope(exit
) evcode
= null;
81 evcode
= evcode
.replace("\r\n", "\n").replace("\r", "\n").outdentAll
;
82 //while (evcode.length && evcode[0] <= ' ') evcode = evcode[1..$];
83 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
85 auto fn
= evcode
.parseScript(obj
.name
~":"~evname
);
87 if (hasReturn(fn
)) throw new Exception("event '"~evname
~"' for object '"~obj
.name
~"' contains `return`");
93 void createEvent (GMEvent
.Type evtype
) {
96 foreach (immutable evidx
, auto ev
; obj
.events
[evtype
]) {
97 foreach (immutable aidx
, auto act
; ev
.actions
) {
98 if (act
.type
== act
.Type
.Nothing
) continue; // comment
99 if (act
.kind
== act
.Kind
.act_normal
) {
101 if (act
.type
== act
.Type
.Function
) {
102 if (act
.funcname
== "action_inherited") {
103 assert(parent
.length
);
104 evcode
~= "_action_inherited(\""~to
!string(evtype
)~"\", \""~parent
~"\");\n";
107 if (act
.funcname
== "action_kill_object") {
108 evcode
~= "_action_kill_object();\n";
111 if (act
.funcname
== "action_execute_script") {
112 import std
.conv
: to
;
113 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_script
) assert(0, "invalid action function arguments: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
114 string s
= gmk
.scriptByNum(to
!int(act
.argvals
[0])).name
~"(";
115 foreach (immutable idx
; 1..act
.argused
) {
116 if (act
.argtypes
[idx
] != act
.ArgType
.t_expr
) assert(0, "invalid action type for execscript: "~to
!string(act
.argtypes
[idx
])~" for object '"~obj
.name
~"'");
117 if (idx
!= 1) s
~= ", ";
118 s
~= act
.argvals
[idx
];
120 s
~= "); // action_execute_script\n";
124 assert(0, "invalid action function: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
126 assert(0, "invalid normal action type");
128 if (act
.kind
== act
.Kind
.act_code
) {
130 if (act
.type
== act
.Type
.Code
) {
131 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_string
) {
132 import std
.conv
: to
;
133 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
135 import std
.string
: format
;
136 evcode
~= act
.argvals
[0];
137 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
138 if (evcode
.length
> 0) evcode
~= "\n";
141 assert(0, "invalid code action type: "~to
!string(act
.type
));
143 if (act
.kind
== act
.Kind
.act_var
) {
144 // variable assignment
145 if (act
.argused
!= 2 || act
.argtypes
[0] != act
.ArgType
.t_string || act
.argtypes
[1] != act
.ArgType
.t_expr
) {
146 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
148 evcode
~= act
.argvals
[0]~" = "~act
.argvals
[1]~"; // act_var";
152 assert(0, "FUUUCK: "~to
!string(act
.kind
));
155 string baseevname
= to
!string(evtype
);
156 if (evidx
> 0) baseevname
~= to
!string(evidx
);
157 if (evtype
== GMEvent
.Type
.ev_alarm
) {
158 parseECode(evcode
, "ev_alarm:"~to
!string(ev
.id
));
159 //{ import std.stdio; writeln("alarm #", evidx, " for '", obj.name, "'"); }
160 } else if (evtype
== GMEvent
.Type
.ev_step
) {
163 parseECode(evcode
, baseevname
);
164 } else if (ev
.id
== 1) {
166 parseECode(evcode
, to
!string(evtype
)~":begin");
167 } else if (ev
.id
== 2) {
169 parseECode(evcode
, to
!string(evtype
)~":end");
173 } else if (evtype
== GMEvent
.Type
.ev_keypress || evtype
== GMEvent
.Type
.ev_keyrelease || evtype
== GMEvent
.Type
.ev_keyboard
) {
174 if (auto keyName
= cast(uint)ev
.id
in evKeyNames
) {
175 import std
.string
: replace
;
176 string kn
= (*keyName
).replace(" ", "_");
177 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
179 parseECode(evcode
, to
!string(evtype
)~":vcode_"~to
!string(ev
.id
));
181 } else if (evtype
== GMEvent
.Type
.ev_mouse
) {
182 if (auto msName
= cast(uint)ev
.id
in evMouseNames
) {
183 import std
.string
: replace
;
184 string kn
= (*msName
).replace(" ", "_");
185 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
187 parseECode(evcode
, to
!string(evtype
)~":mcode_"~to
!string(ev
.id
));
189 } else if (evtype
== GMEvent
.Type
.ev_collision
) {
190 auto co
= gmk
.objByNum(ev
.id
);
191 if (co
is null) assert(0, "no collision object for 'ev_collision' for '"~obj
.name
~"'");
192 parseECode(evcode
, to
!string(evtype
)~":"~co
.name
);
193 } else if (evtype
== GMEvent
.Type
.ev_other
) {
194 auto nmp
= cast(uint)ev
.id
in evOtherNames
;
195 if (nmp
is null) assert(0, "unknown event id "~to
!string(ev
.id
)~" for 'ev_other' for '"~obj
.name
~"'");
196 import std
.string
: replace
;
197 string nm
= (*nmp
).replace(" ", "_");
198 parseECode(evcode
, to
!string(evtype
)~":"~nm
);
199 } else if (evtype
== GMEvent
.Type
.ev_draw || evtype
== GMEvent
.Type
.ev_destroy || evtype
== GMEvent
.Type
.ev_create
) {
200 parseECode(evcode
, baseevname
);
203 { import std
.stdio
; writeln("fuck! ", evtype
, " #", evidx
, " for '", obj
.name
, "'"); }
206 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
)~"_"~to
!string(ev
.id
));
211 foreach (immutable evtype
; 0..GMEvent
.Type
.max
+1) {
212 if (evtype
!= GMEvent
.Type
.ev_create
) {
213 if (obj
.name
== "oGamepad") continue;
215 createEvent(cast(GMEvent
.Type
)evtype
);
219 void processChildren (string parent
) {
220 auto po
= gmk
.objByName(parent
);
221 if (po
is null) assert(0, "wtf?! "~parent
);
222 gmk
.forEachObject((o
) {
223 if (o
.parentobjidx
== po
.idx
) {
224 if (doActions
) setupObject(o
, po
);
225 processChildren(o
.name
);
232 gmk
.forEachObject((o
) {
233 if (o
.parentobjidx
< 0) {
234 if (doActions
) setupObject(o
, null);
235 processChildren(o
.name
);
241 gmk
.forEachScript((sc
) {
242 assert(sc
.name
.length
);
244 NodeFunc fn
= sc
.code
.parseScript(sc
.name
);
245 assert(fn
.ebody
!is null);
255 // ////////////////////////////////////////////////////////////////////////// //
256 void main (string
[] args
) {
259 bool dumpFileNames
= false;
260 bool styleWarnings
= false;
261 bool doScripts
= true, doActions
= true;
265 foreach (string fname
; args
[1..$]) {
271 if (fname
.length
== 0) continue;
272 if (fname
== "--") { nomore
= true; continue; }
273 if (fname
== "-d") { dumpFileNames
= true; continue; }
274 if (fname
== "-w") { styleWarnings
= true; continue; }
275 if (fname
== "-S") { doScripts
= false; continue; }
276 if (fname
== "-A") { doActions
= false; continue; }
277 if (fname
[0] == '@') {
278 if (fname
.length
< 2) assert(0, "gmk file?");
279 auto gmk
= new Gmk(fname
[1..$]);
280 funcs
~= gmkLoadScripts(gmk
, doScripts
:doScripts
, doActions
:doActions
);
284 foreach (auto de; dirEntries(fname
, "*.gm[lx]", SpanMode
.breadth
)) {
286 foreach (auto pt
; pathSplitter(de.dirName
)) {
287 if (pt
.length
&& pt
[0] == '_') { doit
= false; break; }
290 if (dumpFileNames
) { import std
.stdio
; writeln("loading '", de.name
, "'..."); }
291 funcs
~= loadScript(de.name
, true);
295 if (dumpFileNames
) { import std
.stdio
; writeln("loading '", fname
, "'..."); }
296 funcs
~= loadScript(fname
, true);
301 if (funcs
.length
> 0) {
302 writeln(funcs
.length
, " function", (funcs
.length
> 1 ?
"s" : ""), " parsed");
303 foreach (auto fn
; funcs
) {
305 foreach (string name
; [
316 if (fn
.name
== name
) { skip
= true; break; }
319 if (fn
.name
.length
> 3 && fn
.name
[0..3] == "sui") continue;