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
) 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
);
55 parser
.printCaret(e
.loc
);
58 } catch (Exception e
) {
60 writeln(typeid(e
).name
, "@", e
.file
, "(", e
.line
, "): ", e
.msg
);
67 // ////////////////////////////////////////////////////////////////////////// //
68 NodeFunc
[] gmkLoadScripts (Gmk gmk
, bool doScripts
, bool doActions
, bool warnings
=true, bool checkReturns
=true) {
73 void setupObject (GMObject obj
, GMObject oparent
) {
74 string parent
= (oparent
!is null ? oparent
.name
: null);
76 void parseECode (ref string evcode
, string evname
) {
78 import std
.string
: replace
;
79 scope(exit
) evcode
= null;
80 evcode
= evcode
.replace("\r\n", "\n").replace("\r", "\n").outdentAll
;
81 //while (evcode.length && evcode[0] <= ' ') evcode = evcode[1..$];
82 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
84 auto fn
= evcode
.parseScript(obj
.name
~":"~evname
, warnings
:warnings
);
86 if (checkReturns
&& hasReturn(fn
)) throw new Exception("event '"~evname
~"' for object '"~obj
.name
~"' contains `return`");
92 void createEvent (GMEvent
.Type evtype
) {
95 foreach (immutable evidx
, auto ev
; obj
.events
[evtype
]) {
96 foreach (immutable aidx
, auto act
; ev
.actions
) {
97 if (act
.type
== act
.Type
.Nothing
) continue; // comment
98 if (act
.kind
== act
.Kind
.act_normal
) {
100 if (act
.type
== act
.Type
.Function
) {
101 if (act
.funcname
== "action_inherited") {
102 assert(parent
.length
);
103 evcode
~= "_action_inherited(\""~to
!string(evtype
)~"\", \""~parent
~"\");\n";
106 if (act
.funcname
== "action_kill_object") {
107 evcode
~= "_action_kill_object();\n";
110 if (act
.funcname
== "action_execute_script") {
111 import std
.conv
: to
;
112 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_script
) assert(0, "invalid action function arguments: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
113 string s
= gmk
.scriptByNum(to
!int(act
.argvals
[0])).name
~"(";
114 foreach (immutable idx
; 1..act
.argused
) {
115 if (act
.argtypes
[idx
] != act
.ArgType
.t_expr
) assert(0, "invalid action type for execscript: "~to
!string(act
.argtypes
[idx
])~" for object '"~obj
.name
~"'");
116 if (idx
!= 1) s
~= ", ";
117 s
~= act
.argvals
[idx
];
119 s
~= "); // action_execute_script\n";
123 assert(0, "invalid action function: '"~act
.funcname
~"' for object '"~obj
.name
~"'");
125 assert(0, "invalid normal action type");
127 if (act
.kind
== act
.Kind
.act_code
) {
129 if (act
.type
== act
.Type
.Code
) {
130 if (act
.argused
< 1 || act
.argtypes
[0] != act
.ArgType
.t_string
) {
131 import std
.conv
: to
;
132 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
134 import std
.string
: format
;
135 evcode
~= act
.argvals
[0];
136 while (evcode
.length
&& evcode
[$-1] <= ' ') evcode
= evcode
[0..$-1];
137 if (evcode
.length
> 0) evcode
~= "\n";
140 assert(0, "invalid code action type: "~to
!string(act
.type
));
142 if (act
.kind
== act
.Kind
.act_var
) {
143 // variable assignment
144 if (act
.argused
!= 2 || act
.argtypes
[0] != act
.ArgType
.t_string || act
.argtypes
[1] != act
.ArgType
.t_expr
) {
145 assert(0, "invalid action code arguments for '"~obj
.name
~"': used="~to
!string(act
.argused
)~"; kinds="~to
!string(act
.argtypes
));
147 evcode
~= act
.argvals
[0]~" = "~act
.argvals
[1]~"; // act_var";
151 assert(0, "FUUUCK: "~to
!string(act
.kind
));
154 string baseevname
= to
!string(evtype
);
155 if (evidx
> 0) baseevname
~= to
!string(evidx
);
156 if (evtype
== GMEvent
.Type
.ev_alarm
) {
157 parseECode(evcode
, "ev_alarm:"~to
!string(ev
.id
));
158 //{ import std.stdio; writeln("alarm #", evidx, " for '", obj.name, "'"); }
159 } else if (evtype
== GMEvent
.Type
.ev_step
) {
162 parseECode(evcode
, baseevname
);
163 } else if (ev
.id
== 1) {
165 parseECode(evcode
, to
!string(evtype
)~":begin");
166 } else if (ev
.id
== 2) {
168 parseECode(evcode
, to
!string(evtype
)~":end");
172 } else if (evtype
== GMEvent
.Type
.ev_keypress || evtype
== GMEvent
.Type
.ev_keyrelease || evtype
== GMEvent
.Type
.ev_keyboard
) {
173 if (auto keyName
= cast(uint)ev
.id
in evKeyNames
) {
174 import std
.string
: replace
;
175 string kn
= (*keyName
).replace(" ", "_");
176 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
178 parseECode(evcode
, to
!string(evtype
)~":vcode_"~to
!string(ev
.id
));
180 } else if (evtype
== GMEvent
.Type
.ev_mouse
) {
181 if (auto msName
= cast(uint)ev
.id
in evMouseNames
) {
182 import std
.string
: replace
;
183 string kn
= (*msName
).replace(" ", "_");
184 parseECode(evcode
, to
!string(evtype
)~":"~kn
);
186 parseECode(evcode
, to
!string(evtype
)~":mcode_"~to
!string(ev
.id
));
188 } else if (evtype
== GMEvent
.Type
.ev_collision
) {
189 auto co
= gmk
.objByNum(ev
.id
);
190 if (co
is null) assert(0, "no collision object for 'ev_collision' for '"~obj
.name
~"'");
191 parseECode(evcode
, to
!string(evtype
)~":"~co
.name
);
192 } else if (evtype
== GMEvent
.Type
.ev_other
) {
193 auto nmp
= cast(uint)ev
.id
in evOtherNames
;
194 if (nmp
is null) assert(0, "unknown event id "~to
!string(ev
.id
)~" for 'ev_other' for '"~obj
.name
~"'");
195 import std
.string
: replace
;
196 string nm
= (*nmp
).replace(" ", "_");
197 parseECode(evcode
, to
!string(evtype
)~":"~nm
);
198 } else if (evtype
== GMEvent
.Type
.ev_draw || evtype
== GMEvent
.Type
.ev_destroy || evtype
== GMEvent
.Type
.ev_create
) {
199 parseECode(evcode
, baseevname
);
202 { import std
.stdio
; writeln("fuck! ", evtype
, " #", evidx
, " for '", obj
.name
, "'"); }
203 if (checkReturns
) assert(0);
205 parseECode(evcode
, to
!string(evtype
)~to
!string(evidx
)~"_"~to
!string(ev
.id
));
210 foreach (immutable evtype
; 0..GMEvent
.Type
.max
+1) {
211 if (evtype
!= GMEvent
.Type
.ev_create
) {
212 if (obj
.name
== "oGamepad") continue;
214 createEvent(cast(GMEvent
.Type
)evtype
);
218 void processChildren (string parent
) {
219 auto po
= gmk
.objByName(parent
);
220 if (po
is null) assert(0, "wtf?! "~parent
);
221 gmk
.forEachObject((o
) {
222 if (o
.parentobjidx
== po
.idx
) {
223 if (doActions
) setupObject(o
, po
);
224 processChildren(o
.name
);
231 gmk
.forEachObject((o
) {
232 if (o
.parentobjidx
< 0) {
233 if (doActions
) setupObject(o
, null);
234 processChildren(o
.name
);
240 gmk
.forEachScript((sc
) {
241 assert(sc
.name
.length
);
243 NodeFunc fn
= sc
.code
.parseScript(sc
.name
, warnings
:warnings
);
244 assert(fn
.ebody
!is null);