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
60 writeln("ERROR at ", e
.loc
, ": ", e
.msg
);
61 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
62 parser
.printCaret(e
.loc
);
65 } catch (Exception e
) {
67 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
74 // ////////////////////////////////////////////////////////////////////////// //
75 NodeFunc
[] gmkLoadScripts (Gmk gmk
, bool doScripts
, bool doActions
, bool warnings
=true, bool checkReturns
=true) {
80 void setupObject (GMObject obj
, GMObject oparent
) {
81 string parent
= (oparent
!is null ? oparent
.name
: null);
83 void parseECode (ref string evcode
, string evname
) {
85 import std
.string
: replace
;
86 scope(exit
) evcode
= null;
87 evcode
= evcode
.replace("\r\n", "\n").replace("\r", "\n").outdentAll
;
88 //while (evcode.length && evcode[0] <= ' ') evcode = evcode[1..$];
89 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
91 auto fn
= evcode
.parseScript(obj
.name
~":"~evname
, warnings
:warnings
);
93 if (checkReturns
&& hasReturn(fn
)) throw new Exception("event '"~evname
~"' for object '"~obj
.name
~"' contains `return`");
99 void createEvent (GMEvent
.Type evtype
) {
100 import std
.conv
: to
;
102 foreach (immutable evidx
, auto ev
; obj
.events
[evtype
]) {
103 foreach (immutable aidx
, auto act
; ev
.actions
) {
104 if (act
.type
== act
.Type
.Nothing
) continue; // comment
105 if (act
.kind
== act
.Kind
.act_normal
) {
107 if (act
.type
== act
.Type
.Function
) {
108 if (act
.funcname
== "action_inherited") {
109 assert(parent
.length
);
110 evcode
~= "_action_inherited(\""~to
!string(evtype
)~"\", \""~parent
~"\");\n";
113 if (act
.funcname
== "action_kill_object") {
114 evcode
~= "_action_kill_object();\n";
117 if (act
.funcname
== "action_execute_script") {
118 import std
.conv
: to
;
119 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_script
) assert(0, "invalid action function arguments: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
120 string s
= gmk
.scriptByNum(to
!int(act
.argvals
[0])).name
~"(";
121 foreach (immutable idx
; 1..act
.argused
) {
122 if (act
.argtypes
[idx
] != act
.ArgType
.t_expr
) assert(0, "invalid action type for execscript: "~to
!string(act
.argtypes
[idx
])~" for object '"~obj
.name
~"'");
123 if (idx
!= 1) s
~= ", ";
124 s
~= act
.argvals
[idx
];
126 s
~= "); // action_execute_script\n";
130 assert(0, "invalid action function: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
132 assert(0, "invalid normal action type");
134 if (act
.kind
== act
.Kind
.act_code
) {
136 if (act
.type
== act
.Type
.Code
) {
137 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_string
) {
138 import std
.conv
: to
;
139 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
141 import std
.string
: format
;
142 evcode
~= act
.argvals
[0];
143 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
144 if (evcode
.length
> 0) evcode
~= "\n";
147 assert(0, "invalid code action type: "~to
!string(act
.type
));
149 if (act
.kind
== act
.Kind
.act_var
) {
150 // variable assignment
151 if (act
.argused
!= 2 || act
.argtypes
[0] != act
.ArgType
.t_string || act
.argtypes
[1] != act
.ArgType
.t_expr
) {
152 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
154 evcode
~= act
.argvals
[0]~" = "~act
.argvals
[1]~"; // act_var";
158 assert(0, "FUUUCK: "~to
!string(act
.kind
));
161 string baseevname
= to
!string(evtype
);
162 if (evidx
> 0) baseevname
~= to
!string(evidx
);
163 if (evtype
== GMEvent
.Type
.ev_alarm
) {
164 parseECode(evcode
, "ev_alarm:"~to
!string(ev
.id
));
165 //{ import std.stdio; writeln("alarm #", evidx, " for '", obj.name, "'"); }
166 } else if (evtype
== GMEvent
.Type
.ev_step
) {
169 parseECode(evcode
, baseevname
);
170 } else if (ev
.id
== 1) {
172 parseECode(evcode
, to
!string(evtype
)~":begin");
173 } else if (ev
.id
== 2) {
175 parseECode(evcode
, to
!string(evtype
)~":end");
179 } else if (evtype
== GMEvent
.Type
.ev_keypress || evtype
== GMEvent
.Type
.ev_keyrelease || evtype
== GMEvent
.Type
.ev_keyboard
) {
180 if (auto keyName
= cast(uint)ev
.id
in evKeyNames
) {
181 import std
.string
: replace
;
182 string kn
= (*keyName
).replace(" ", "_");
183 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
185 parseECode(evcode
, to
!string(evtype
)~":vcode_"~to
!string(ev
.id
));
187 } else if (evtype
== GMEvent
.Type
.ev_mouse
) {
188 if (auto msName
= cast(uint)ev
.id
in evMouseNames
) {
189 import std
.string
: replace
;
190 string kn
= (*msName
).replace(" ", "_");
191 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
193 parseECode(evcode
, to
!string(evtype
)~":mcode_"~to
!string(ev
.id
));
195 } else if (evtype
== GMEvent
.Type
.ev_collision
) {
196 auto co
= gmk
.objByNum(ev
.id
);
197 if (co
is null) assert(0, "no collision object for 'ev_collision' for '"~obj
.name
~"'");
198 parseECode(evcode
, to
!string(evtype
)~":"~co
.name
);
199 } else if (evtype
== GMEvent
.Type
.ev_other
) {
200 auto nmp
= cast(uint)ev
.id
in evOtherNames
;
201 if (nmp
is null) assert(0, "unknown event id "~to
!string(ev
.id
)~" for 'ev_other' for '"~obj
.name
~"'");
202 import std
.string
: replace
;
203 string nm
= (*nmp
).replace(" ", "_");
204 parseECode(evcode
, to
!string(evtype
)~":"~nm
);
205 } else if (evtype
== GMEvent
.Type
.ev_draw || evtype
== GMEvent
.Type
.ev_destroy || evtype
== GMEvent
.Type
.ev_create
) {
206 parseECode(evcode
, baseevname
);
209 { import std
.stdio
; writeln("fuck! ", evtype
, " #", evidx
, " for '", obj
.name
, "'"); }
210 if (checkReturns
) assert(0);
212 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
)~"_"~to
!string(ev
.id
));
217 foreach (immutable evtype
; 0..GMEvent
.Type
.max
+1) {
218 if (evtype
!= GMEvent
.Type
.ev_create
) {
219 if (obj
.name
== "oGamepad") continue;
221 createEvent(cast(GMEvent
.Type
)evtype
);
225 void processChildren (string parent
) {
226 auto po
= gmk
.objByName(parent
);
227 if (po
is null) assert(0, "wtf?! "~parent
);
228 gmk
.forEachObject((o
) {
229 if (o
.parentobjidx
== po
.idx
) {
230 if (doActions
) setupObject(o
, po
);
231 processChildren(o
.name
);
238 gmk
.forEachObject((o
) {
239 if (o
.parentobjidx
< 0) {
240 if (doActions
) setupObject(o
, null);
241 processChildren(o
.name
);
247 gmk
.forEachScript((sc
) {
248 assert(sc
.name
.length
);
250 NodeFunc fn
= sc
.code
.parseScript(sc
.name
, warnings
:warnings
);
251 assert(fn
.ebody
!is null);