Skip to content

Commit 538032e

Browse files
committed
Cleanup eval a bit
1 parent 5ca0e98 commit 538032e

File tree

1 file changed

+103
-120
lines changed

1 file changed

+103
-120
lines changed

common/space_lua/eval.ts

Lines changed: 103 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,91 @@ import {
3838
import { luaValueToJS } from "$common/space_lua/runtime.ts";
3939
import { jsToLuaValue } from "$common/space_lua/runtime.ts";
4040

41+
function handleVarargSync(env: LuaEnv): LuaValue[] | Promise<LuaValue[]> {
42+
const varargs = env.get("...");
43+
if (varargs instanceof Promise) {
44+
return handleVarargAsync(varargs);
45+
}
46+
if (varargs instanceof LuaTable) {
47+
const args = [];
48+
for (let i = 1; i <= varargs.length; i++) {
49+
const val = varargs.get(i);
50+
if (val instanceof Promise) {
51+
return handleVarargAsync(varargs);
52+
}
53+
args.push(val);
54+
}
55+
return args;
56+
}
57+
return [];
58+
}
59+
60+
async function handleVarargAsync(
61+
varargs: Promise<LuaValue> | LuaTable,
62+
): Promise<LuaValue[]> {
63+
const resolvedVarargs = await varargs;
64+
if (resolvedVarargs instanceof LuaTable) {
65+
const args = [];
66+
for (let i = 1; i <= resolvedVarargs.length; i++) {
67+
args.push(await resolvedVarargs.get(i));
68+
}
69+
return args;
70+
}
71+
return [];
72+
}
73+
74+
function handleTableFieldSync(
75+
table: LuaTable,
76+
field: any,
77+
env: LuaEnv,
78+
sf: LuaStackFrame,
79+
): void | Promise<void> {
80+
switch (field.type) {
81+
case "PropField": {
82+
const value = evalExpression(field.value, env, sf);
83+
if (value instanceof Promise) {
84+
return value.then((v) => table.set(field.key, singleResult(v), sf));
85+
}
86+
table.set(field.key, singleResult(value), sf);
87+
break;
88+
}
89+
case "DynamicField": {
90+
const key = evalExpression(field.key, env, sf);
91+
const value = evalExpression(field.value, env, sf);
92+
if (key instanceof Promise || value instanceof Promise) {
93+
return Promise.all([
94+
key instanceof Promise ? key : Promise.resolve(key),
95+
value instanceof Promise ? value : Promise.resolve(value),
96+
]).then(([k, v]) => {
97+
table.set(singleResult(k), singleResult(v), sf);
98+
});
99+
}
100+
table.set(singleResult(key), singleResult(value), sf);
101+
break;
102+
}
103+
case "ExpressionField": {
104+
if (field.value.type === "Variable" && field.value.name === "...") {
105+
const varargs = handleVarargSync(env);
106+
if (varargs instanceof Promise) {
107+
return varargs.then((args) => {
108+
args.forEach((val, i) => table.set(i + 1, val, sf));
109+
});
110+
}
111+
varargs.forEach((val, i) => table.set(i + 1, val, sf));
112+
} else {
113+
const value = evalExpression(field.value, env, sf);
114+
if (value instanceof Promise) {
115+
return value.then((v) =>
116+
table.set(table.length + 1, singleResult(v), sf)
117+
);
118+
}
119+
table.set(table.length + 1, singleResult(value), sf);
120+
}
121+
break;
122+
}
123+
}
124+
}
125+
41126
export function evalExpression(
42127
e: LuaExpression,
43128
env: LuaEnv,
@@ -138,132 +223,36 @@ export function evalExpression(
138223
return evalPrefixExpression(e, env, sf);
139224
case "TableConstructor": {
140225
const table = new LuaTable();
226+
141227
if (
142228
e.fields.length === 1 &&
143229
e.fields[0].type === "ExpressionField" &&
144230
e.fields[0].value.type === "Variable" &&
145231
e.fields[0].value.name === "..."
146232
) {
147-
const varargs = env.get("...");
233+
const varargs = handleVarargSync(env);
148234
if (varargs instanceof Promise) {
149-
return varargs.then((resolvedVarargs) => {
150-
if (resolvedVarargs instanceof LuaTable) {
151-
const newTable = new LuaTable();
152-
for (let i = 1; i <= resolvedVarargs.length; i++) {
153-
newTable.set(i, resolvedVarargs.get(i), sf);
154-
}
155-
return newTable;
156-
}
235+
return varargs.then((args) => {
236+
args.forEach((val, i) => table.set(i + 1, val, sf));
157237
return table;
158238
});
159-
} else if (varargs instanceof LuaTable) {
160-
for (let i = 1; i <= varargs.length; i++) {
161-
table.set(i, varargs.get(i), sf);
162-
}
163239
}
240+
varargs.forEach((val, i) => table.set(i + 1, val, sf));
164241
return table;
165242
}
243+
166244
const promises: Promise<void>[] = [];
167245
for (const field of e.fields) {
168-
switch (field.type) {
169-
case "PropField": {
170-
const value = evalExpression(field.value, env, sf);
171-
if (value instanceof Promise) {
172-
promises.push(value.then((value) => {
173-
table.set(
174-
field.key,
175-
singleResult(value),
176-
sf,
177-
);
178-
}));
179-
} else {
180-
table.set(field.key, singleResult(value), sf);
181-
}
182-
break;
183-
}
184-
case "DynamicField": {
185-
const key = evalExpression(field.key, env, sf);
186-
const value = evalExpression(field.value, env, sf);
187-
if (
188-
key instanceof Promise || value instanceof Promise
189-
) {
190-
promises.push(
191-
Promise.all([
192-
key instanceof Promise ? key : Promise.resolve(key),
193-
value instanceof Promise ? value : Promise.resolve(value),
194-
]).then(([key, value]) => {
195-
table.set(
196-
singleResult(key),
197-
singleResult(value),
198-
sf,
199-
);
200-
}),
201-
);
202-
} else {
203-
table.set(
204-
singleResult(key),
205-
singleResult(value),
206-
sf,
207-
);
208-
}
209-
break;
210-
}
211-
case "ExpressionField": {
212-
const value = evalExpression(field.value, env, sf);
213-
if (value instanceof Promise) {
214-
promises.push(value.then(async (value) => {
215-
if (
216-
field.value.type === "Variable" &&
217-
field.value.name === "..."
218-
) {
219-
// Special handling for {...}
220-
const varargs = await Promise.resolve(env.get("..."));
221-
if (varargs instanceof LuaTable) {
222-
// Copy all values from varargs table
223-
for (let i = 1; i <= varargs.length; i++) {
224-
const val = await Promise.resolve(varargs.get(i));
225-
table.set(i, val, sf);
226-
}
227-
}
228-
} else {
229-
// Normal case
230-
table.set(table.length + 1, singleResult(value), sf);
231-
}
232-
}));
233-
} else {
234-
if (
235-
field.value.type === "Variable" && field.value.name === "..."
236-
) {
237-
// Special handling for {...}
238-
const varargs = env.get("...");
239-
if (varargs instanceof LuaTable) {
240-
for (let i = 1; i <= varargs.length; i++) {
241-
const val = varargs.get(i);
242-
if (val instanceof Promise) {
243-
promises.push(
244-
Promise.resolve(val).then((val) => {
245-
table.set(i, val, sf);
246-
}),
247-
);
248-
} else {
249-
table.set(i, val, sf);
250-
}
251-
}
252-
}
253-
} else {
254-
// Normal case
255-
table.set(table.length + 1, singleResult(value), sf);
256-
}
257-
}
258-
break;
259-
}
246+
const result = handleTableFieldSync(table, field, env, sf);
247+
if (result instanceof Promise) {
248+
promises.push(result);
260249
}
261250
}
251+
262252
if (promises.length > 0) {
263253
return Promise.all(promises).then(() => table);
264-
} else {
265-
return table;
266254
}
255+
return table;
267256
}
268257
case "FunctionDefinition": {
269258
return new LuaFunction(e.body, env);
@@ -600,25 +589,19 @@ function luaOp(
600589
ctx: ASTCtx,
601590
sf: LuaStackFrame,
602591
): any {
603-
const operatorHandler = operatorsMetaMethods[op];
604-
if (!operatorHandler) {
592+
const handler = operatorsMetaMethods[op];
593+
if (!handler) {
605594
throw new LuaRuntimeError(`Unknown operator ${op}`, sf.withCtx(ctx));
606595
}
607596

608-
if (operatorHandler.metaMethod) {
609-
const result = evalMetamethod(
610-
left,
611-
right,
612-
operatorHandler.metaMethod,
613-
ctx,
614-
sf,
615-
);
616-
if (result !== undefined) {
617-
return result;
597+
if (handler.metaMethod) {
598+
const metaResult = evalMetamethod(left, right, handler.metaMethod, ctx, sf);
599+
if (metaResult !== undefined) {
600+
return metaResult;
618601
}
619602
}
620603

621-
return operatorHandler.nativeImplementation(left, right, ctx, sf);
604+
return handler.nativeImplementation(left, right, ctx, sf);
622605
}
623606

624607
async function evalExpressions(

0 commit comments

Comments
 (0)