1 | // See GazelleV_LeftArrowScriptParser |
2 | |
3 | // TODO: decide whether we allow calling methods/getting fields on |
4 | // a null reference (just returning null), or whether we throw a |
5 | // NullPointerException. Currently we just return null. Probably |
6 | // that's pretty cool. Null propagation as a default, just like in |
7 | // JavaX. Just more automatic! |
8 | |
9 | sclass GazelleV_LeftArrowScript { |
10 | asclass Base is IHasTokenRangeWithSrc { |
11 | TokenRangeWithSrc src; |
12 | |
13 | public void setTokenRangeWithSrc(TokenRangeWithSrc src) { this.src = src; } |
14 | public TokenRangeWithSrc tokenRangeWithSrc() { ret src; } |
15 | |
16 | RuntimeException rethrowWithSrc(Throwable e) { |
17 | if (src != null) |
18 | throw rethrowAndAppendToMessage(e, squareBracketed(str(src))); |
19 | else |
20 | throw rethrow(e); |
21 | } |
22 | } |
23 | |
24 | interface Evaluable { |
25 | public O get(VarContext ctx default new); |
26 | } |
27 | |
28 | /*interface Cmd { |
29 | // returns true if a return was issued |
30 | public bool run(VarContext ctx default new); |
31 | }*/ |
32 | |
33 | static new AtomicLong scriptIDCounter; |
34 | static long scriptID() { ret incAtomicLong(scriptIDCounter); } |
35 | |
36 | sclass Script is Evaluable { |
37 | long id = scriptID(); // just for printing |
38 | Map<S, FunctionDef> functionDefs; |
39 | Evaluable[] steps; |
40 | |
41 | public O get(VarContext ctx) { |
42 | O result = null; |
43 | for (step : steps) { |
44 | ping(); |
45 | result = step.get(ctx); |
46 | |
47 | // exiting from anything? |
48 | |
49 | var exiting = ctx.exitFromScript; |
50 | if (exiting != null) { |
51 | printVars ifdef ReturnFromScript_debug("Checking exitFromScript", |
52 | +ctx, +exiting, script := this); |
53 | |
54 | // we're the exit point |
55 | if (exiting == this) |
56 | ctx.exitFromScript = null; |
57 | |
58 | // exit further |
59 | break; |
60 | } |
61 | } |
62 | ret result; |
63 | } |
64 | |
65 | S toStringLong() { ret pnlToLines(steps); } |
66 | toString { ret "Script " + n2(id); } |
67 | |
68 | FunctionDef getFunction(S name) { ret mapGet(functionDefs, name); } |
69 | } // end of Script |
70 | |
71 | srecord noeq FunctionDef(S name, LS args, Evaluable body) > Base { |
72 | public O call(VarContext ctx, O... args) { |
73 | var ctx2 = new VarContext(ctx); |
74 | int n = min(l(args), l(this.args)); |
75 | for i to n: |
76 | ctx2.put(this.args.get(i), args[i]); |
77 | print ifdef GazelleV_LeftArrowScript_debug(ctx2 := ctx2.vars); |
78 | ret body.get(ctx2); |
79 | } |
80 | } |
81 | |
82 | srecord noeq Assignment(S var, Evaluable expression) > Base is Evaluable { |
83 | public O get(VarContext ctx) { |
84 | O o = expression.get(ctx); |
85 | ctx.set(var, o); |
86 | ret o; |
87 | } |
88 | |
89 | toString { ret var + " <- " + expression; } |
90 | } |
91 | |
92 | persistable sclass NewObject > Base is Evaluable { |
93 | Class c; |
94 | L<Evaluable> args; |
95 | |
96 | *(Class *c) {} |
97 | *(Class *c, L<Evaluable> *args) {} |
98 | |
99 | public O get(VarContext ctx) { |
100 | ret callConstructor(c, mapToArray(args, arg -> arg.get(ctx))); |
101 | } |
102 | |
103 | toString { ret "new " + formatFunctionCall(className(c), args); } |
104 | } |
105 | |
106 | srecord noeq CallFunction(FunctionDef f, L<Evaluable> args) > Base is Evaluable { |
107 | public O get(VarContext ctx) { |
108 | //ping(); |
109 | ret f.call(ctx, mapToArray(args, a -> a.get(ctx)); |
110 | } |
111 | |
112 | toString { ret formatFunctionCall(f.name, args); } |
113 | } |
114 | |
115 | srecord noeq GetVar(S var) > Base is Evaluable { |
116 | public O get(VarContext ctx) { |
117 | ret ctx.get(var); |
118 | } |
119 | |
120 | toString { ret var; } |
121 | } |
122 | |
123 | srecord noeq Const(O value) > Base is Evaluable { |
124 | public O get(VarContext ctx) { |
125 | ret value; |
126 | } |
127 | |
128 | toString { ret strOrClassName(value); } |
129 | } |
130 | |
131 | srecord noeq GetStaticField(Field field) > Base is Evaluable { |
132 | public O get(VarContext ctx) ctex { |
133 | ret field.get(null); |
134 | } |
135 | } |
136 | |
137 | srecord noeq CallMethodOrGetField(Evaluable target, S name) > Base is Evaluable { |
138 | public O get(VarContext ctx) { |
139 | try { |
140 | O object = target.get(ctx); |
141 | if (object == null) |
142 | null; // throw new NullPointerException(); |
143 | |
144 | // could optimize more for sure |
145 | if (canCallWithVarargs(object, name)) |
146 | ret call(object, name); |
147 | |
148 | ret _get(object, name); |
149 | } catch e { |
150 | throw rethrowWithSrc(e); |
151 | } |
152 | } |
153 | } |
154 | |
155 | srecord CallMethod(Evaluable target, S methodName, L<Evaluable> args) > Base is Evaluable { |
156 | public O get(VarContext ctx) { |
157 | ret call(target.get(ctx), methodName, mapToArray(args, arg -> arg.get(ctx))); |
158 | } |
159 | |
160 | toString { ret target + "." + formatFunctionCall(methodName, args); } |
161 | } |
162 | |
163 | srecord While(Evaluable condition, Evaluable body) > Base is Evaluable { |
164 | public O get(VarContext ctx) { |
165 | while (ping() && (Bool) condition.get(ctx)) { |
166 | body.get(ctx); |
167 | } |
168 | |
169 | // while loops don't return anything |
170 | null; |
171 | } |
172 | } |
173 | |
174 | srecord ForEach(Evaluable collection, S var, Evaluable body) > Base is Evaluable { |
175 | public O get(VarContext ctx) { |
176 | var coll = collection.get(ctx); |
177 | Iterator iterator; |
178 | if (coll cast O[]) |
179 | for (element : coll) { |
180 | ping(); |
181 | ctx.set(var, element); |
182 | body.get(ctx); |
183 | } |
184 | else if (coll cast Iterable) { |
185 | for (element : coll) { |
186 | ping(); |
187 | ctx.set(var, element); |
188 | body.get(ctx); |
189 | } |
190 | } else if (coll == null) {} // ok |
191 | else |
192 | fail("Not iterable: " + className(coll)); |
193 | |
194 | ctx.unset(var); |
195 | null; |
196 | } |
197 | } |
198 | |
199 | srecord IfThen(Evaluable condition, Evaluable body) > Base is Evaluable { |
200 | public O get(VarContext ctx) { |
201 | if ((Bool) condition.get(ctx)) |
202 | ret body.get(ctx); |
203 | else |
204 | null; |
205 | } |
206 | } |
207 | |
208 | srecord ReturnFromScript(Script script, Evaluable value) > Base is Evaluable { |
209 | public O get(VarContext ctx) { |
210 | O result = value.get(ctx); |
211 | printVars ifdef ReturnFromScript_debug("ReturnFromScript", |
212 | +result, +ctx, +script); |
213 | ctx.exitFromScript(script); |
214 | ret result; |
215 | } |
216 | |
217 | toString { |
218 | ret formatFunctionCall ReturnFromScript(script, value); |
219 | } |
220 | } |
221 | } |
Began life as a copy of #1033981
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1034292 |
Snippet name: | GazelleV_LeftArrowScript backup before type inference |
Eternal ID of this version: | #1034292/1 |
Text MD5: | 9888e3181940cc2791ed8abc123d53d2 |
Author: | stefan |
Category: | javax |
Type: | JavaX fragment (include) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-02-01 03:12:14 |
Source code size: | 6246 bytes / 221 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 123 / 139 |
Referenced in: | [show references] |