1 module loader
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
) {
26 auto fn
= parser
.parseFunction();
27 fn
.pp
= parser
; // store parsed source
31 string scname
= filename
.baseName(".gml");
32 auto fn
= parser
.parseFunctionBody(scname
);
33 fn
.pp
= parser
; // store parsed source
36 assert(parser
.lex
.empty
);
39 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
40 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
42 } catch (Exception e
) {
44 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
51 // ////////////////////////////////////////////////////////////////////////// //
52 NodeFunc
parseScript (string code
, string scname
, bool warnings
=true) {
53 auto parser
= new Parser(code
, scname
);
54 parser
.warnings
= warnings
;
56 auto fn
= parser
.parseFunctionBody(scname
);
57 fn
.pp
= parser
; // store parsed source
61 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
62 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
63 parser
.printCaret(e
.loc
);
66 } catch (Exception e
) {
68 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
75 // ////////////////////////////////////////////////////////////////////////// //
76 NodeFunc
[] gmkLoadScripts (Gmk gmk
, bool doScripts
, bool doActions
, bool warnings
=true, bool checkReturns
=true) {
81 void setupObject (GMObject obj
, GMObject oparent
) {
82 string parent
= (oparent
!is null ? oparent
.name
: null);
84 void parseECode (ref string evcode
, string evname
) {
86 import std
.string
: replace
;
87 scope(exit
) evcode
= null;
88 evcode
= evcode
.replace("\r\n", "\n").replace("\r", "\n").outdentAll
;
89 //while (evcode.length && evcode[0] <= ' ') evcode = evcode[1..$];
90 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
92 auto fn
= evcode
.parseScript(obj
.name
~":"~evname
, warnings
:warnings
);
94 if (checkReturns
&& hasReturn(fn
)) throw new Exception("event '"~evname
~"' for object '"~obj
.name
~"' contains `return`");
100 void createEvent (GMEvent
.Type evtype
) {
101 import std
.conv
: to
;
103 foreach (immutable evidx
, auto ev
; obj
.events
[evtype
]) {
104 foreach (immutable aidx
, auto act
; ev
.actions
) {
105 if (act
.type
== act
.Type
.Nothing
) continue; // comment
106 if (act
.kind
== act
.Kind
.act_normal
) {
108 if (act
.type
== act
.Type
.Function
) {
109 if (act
.funcname
== "action_inherited") {
110 assert(parent
.length
);
111 evcode
~= "_action_inherited(\""~to
!string(evtype
)~"\", \""~parent
~"\");\n";
114 if (act
.funcname
== "action_kill_object") {
115 evcode
~= "_action_kill_object();\n";
118 if (act
.funcname
== "action_execute_script") {
119 import std
.conv
: to
;
120 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_script
) assert(0, "invalid action function arguments: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
121 string s
= gmk
.scriptByNum(to
!int(act
.argvals
[0])).name
~"(";
122 foreach (immutable idx
; 1..act
.argused
) {
123 if (act
.argtypes
[idx
] != act
.ArgType
.t_expr
) assert(0, "invalid action type for execscript: "~to
!string(act
.argtypes
[idx
])~" for object '"~obj
.name
~"'");
124 if (idx
!= 1) s
~= ", ";
125 s
~= act
.argvals
[idx
];
127 s
~= "); // action_execute_script\n";
131 assert(0, "invalid action function: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
133 assert(0, "invalid normal action type");
135 if (act
.kind
== act
.Kind
.act_code
) {
137 if (act
.type
== act
.Type
.Code
) {
138 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_string
) {
139 import std
.conv
: to
;
140 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
142 import std
.string
: format
;
143 evcode
~= act
.argvals
[0];
144 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
145 if (evcode
.length
> 0) evcode
~= "\n";
148 assert(0, "invalid code action type: "~to
!string(act
.type
));
150 if (act
.kind
== act
.Kind
.act_var
) {
151 // variable assignment
152 if (act
.argused
!= 2 || act
.argtypes
[0] != act
.ArgType
.t_string || act
.argtypes
[1] != act
.ArgType
.t_expr
) {
153 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
155 evcode
~= act
.argvals
[0]~" = "~act
.argvals
[1]~"; // act_var";
159 assert(0, "FUUUCK: "~to
!string(act
.kind
));
162 string baseevname
= to
!string(evtype
);
163 if (evidx
> 0) baseevname
~= to
!string(evidx
);
164 if (evtype
== GMEvent
.Type
.ev_alarm
) {
165 parseECode(evcode
, "ev_alarm:"~to
!string(ev
.id
));
166 //{ import std.stdio; writeln("alarm #", evidx, " for '", obj.name, "'"); }
167 } else if (evtype
== GMEvent
.Type
.ev_step
) {
170 parseECode(evcode
, baseevname
);
171 } else if (ev
.id
== 1) {
173 parseECode(evcode
, to
!string(evtype
)~":begin");
174 } else if (ev
.id
== 2) {
176 parseECode(evcode
, to
!string(evtype
)~":end");
180 } else if (evtype
== GMEvent
.Type
.ev_keypress || evtype
== GMEvent
.Type
.ev_keyrelease || evtype
== GMEvent
.Type
.ev_keyboard
) {
181 if (auto keyName
= cast(uint)ev
.id
in evKeyNames
) {
182 import std
.string
: replace
;
183 string kn
= (*keyName
).replace(" ", "_");
184 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
186 parseECode(evcode
, to
!string(evtype
)~":vcode_"~to
!string(ev
.id
));
188 } else if (evtype
== GMEvent
.Type
.ev_mouse
) {
189 if (auto msName
= cast(uint)ev
.id
in evMouseNames
) {
190 import std
.string
: replace
;
191 string kn
= (*msName
).replace(" ", "_");
192 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
194 parseECode(evcode
, to
!string(evtype
)~":mcode_"~to
!string(ev
.id
));
196 } else if (evtype
== GMEvent
.Type
.ev_collision
) {
197 auto co
= gmk
.objByNum(ev
.id
);
198 if (co
is null) assert(0, "no collision object for 'ev_collision' for '"~obj
.name
~"'");
199 parseECode(evcode
, to
!string(evtype
)~":"~co
.name
);
200 } else if (evtype
== GMEvent
.Type
.ev_other
) {
201 auto nmp
= cast(uint)ev
.id
in evOtherNames
;
202 if (nmp
is null) assert(0, "unknown event id "~to
!string(ev
.id
)~" for 'ev_other' for '"~obj
.name
~"'");
203 import std
.string
: replace
;
204 string nm
= (*nmp
).replace(" ", "_");
205 parseECode(evcode
, to
!string(evtype
)~":"~nm
);
206 } else if (evtype
== GMEvent
.Type
.ev_draw || evtype
== GMEvent
.Type
.ev_destroy || evtype
== GMEvent
.Type
.ev_create
) {
207 parseECode(evcode
, baseevname
);
210 { import std
.stdio
; writeln("fuck! ", evtype
, " #", evidx
, " for '", obj
.name
, "'"); }
211 if (checkReturns
) assert(0);
213 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
)~"_"~to
!string(ev
.id
));
218 foreach (immutable evtype
; 0..GMEvent
.Type
.max
+1) {
219 if (evtype
!= GMEvent
.Type
.ev_create
) {
220 if (obj
.name
== "oGamepad") continue;
222 createEvent(cast(GMEvent
.Type
)evtype
);
226 void processChildren (string parent
) {
227 auto po
= gmk
.objByName(parent
);
228 if (po
is null) assert(0, "wtf?! "~parent
);
229 gmk
.forEachObject((o
) {
230 if (o
.parentobjidx
== po
.idx
) {
231 if (doActions
) setupObject(o
, po
);
232 processChildren(o
.name
);
239 gmk
.forEachObject((o
) {
240 if (o
.parentobjidx
< 0) {
241 if (doActions
) setupObject(o
, null);
242 processChildren(o
.name
);
248 gmk
.forEachScript((sc
) {
249 assert(sc
.name
.length
);
251 NodeFunc fn
= sc
.code
.parseScript(sc
.name
, warnings
:warnings
);
252 assert(fn
.ebody
!is null);