Lua runtime fixes

main
Zef Hemel 2025-01-09 10:27:41 +01:00
parent 821dddff5e
commit b6f1977cec
3 changed files with 72 additions and 63 deletions

View File

@ -160,7 +160,8 @@ Deno.test("Test directive parser", () => {
}); });
Deno.test("Test lua directive parser", () => { Deno.test("Test lua directive parser", () => {
const simpleExample = `Simple \${{a=}}`; const simpleExample = `Simple \${query_coll("page limit 3", template[==[
* Hello there {name}]==])}`;
console.log(JSON.stringify(parseMarkdown(simpleExample), null, 2)); console.log(JSON.stringify(parseMarkdown(simpleExample), null, 2));
}); });

View File

@ -312,63 +312,70 @@ function evalPrefixExpression(
); );
} }
// Special handling for f(...) - propagate varargs const handleFunctionCall = (prefixValue: LuaValue) => {
if ( // Special handling for f(...) - propagate varargs
e.args.length === 1 && e.args[0].type === "Variable" && if (
e.args[0].name === "..." e.args.length === 1 && e.args[0].type === "Variable" &&
) { e.args[0].name === "..."
const varargs = env.get("..."); ) {
const resolveVarargs = async () => { const varargs = env.get("...");
const resolvedVarargs = await Promise.resolve(varargs); const resolveVarargs = async () => {
if (resolvedVarargs instanceof LuaTable) { const resolvedVarargs = await Promise.resolve(varargs);
const args = []; if (resolvedVarargs instanceof LuaTable) {
for (let i = 1; i <= resolvedVarargs.length; i++) { const args = [];
const val = await Promise.resolve(resolvedVarargs.get(i)); for (let i = 1; i <= resolvedVarargs.length; i++) {
args.push(val); const val = await Promise.resolve(resolvedVarargs.get(i));
args.push(val);
}
return args;
} }
return args; return [];
} };
return [];
};
if (prefixValue instanceof Promise) { if (prefixValue instanceof Promise) {
return prefixValue.then(async (resolvedPrefix) => { return prefixValue.then(async (resolvedPrefix) => {
const args = await resolveVarargs(); const args = await resolveVarargs();
return luaCall(resolvedPrefix, args, e.ctx, sf.withCtx(e.ctx)); return luaCall(resolvedPrefix, args, e.ctx, sf.withCtx(e.ctx));
}); });
} else { } else {
return resolveVarargs().then((args) => return resolveVarargs().then((args) =>
luaCall(prefixValue, args, e.ctx, sf.withCtx(e.ctx)) luaCall(prefixValue, args, e.ctx, sf.withCtx(e.ctx))
);
}
}
// Normal argument handling
let selfArgs: LuaValue[] = [];
if (e.name && !prefixValue.get) {
throw new LuaRuntimeError(
`Attempting to index a non-table: ${prefixValue}`,
sf.withCtx(e.prefix.ctx),
);
} else if (e.name) {
selfArgs = [prefixValue];
prefixValue = prefixValue.get(e.name);
}
if (!prefixValue.call) {
throw new LuaRuntimeError(
`Attempting to call ${prefixValue} as a function`,
sf.withCtx(e.prefix.ctx),
); );
} }
} const args = evalPromiseValues(
e.args.map((arg) => evalExpression(arg, env, sf)),
// Normal argument handling
let selfArgs: LuaValue[] = [];
if (e.name && !prefixValue.get) {
throw new LuaRuntimeError(
`Attempting to index a non-table: ${prefixValue}`,
sf.withCtx(e.prefix.ctx),
);
} else if (e.name) {
selfArgs = [prefixValue];
prefixValue = prefixValue.get(e.name);
}
if (!prefixValue.call) {
throw new LuaRuntimeError(
`Attempting to call ${prefixValue} as a function`,
sf.withCtx(e.prefix.ctx),
);
}
const args = evalPromiseValues(
e.args.map((arg) => evalExpression(arg, env, sf)),
);
if (args instanceof Promise) {
return args.then((args) =>
luaCall(prefixValue, [...selfArgs, ...args], e.ctx, sf)
); );
if (args instanceof Promise) {
return args.then((args) =>
luaCall(prefixValue, [...selfArgs, ...args], e.ctx, sf)
);
} else {
return luaCall(prefixValue, [...selfArgs, ...args], e.ctx, sf);
}
};
if (prefixValue instanceof Promise) {
return prefixValue.then(handleFunctionCall);
} else { } else {
return luaCall(prefixValue, [...selfArgs, ...args], e.ctx, sf); return handleFunctionCall(prefixValue);
} }
} }
default: default:

View File

@ -3,9 +3,10 @@ import {
LuaBuiltinFunction, LuaBuiltinFunction,
luaCall, luaCall,
LuaEnv, LuaEnv,
luaGet,
LuaMultiRes, LuaMultiRes,
LuaRuntimeError, LuaRuntimeError,
type LuaTable, LuaTable,
luaToString, luaToString,
luaTypeOf, luaTypeOf,
type LuaValue, type LuaValue,
@ -15,8 +16,8 @@ import { tableApi } from "$common/space_lua/stdlib/table.ts";
import { osApi } from "$common/space_lua/stdlib/os.ts"; import { osApi } from "$common/space_lua/stdlib/os.ts";
import { jsApi } from "$common/space_lua/stdlib/js.ts"; import { jsApi } from "$common/space_lua/stdlib/js.ts";
const printFunction = new LuaBuiltinFunction((_sf, ...args) => { const printFunction = new LuaBuiltinFunction(async (_sf, ...args) => {
console.log("[Lua]", ...args.map(luaToString)); console.log("[Lua]", ...(await Promise.all(args.map(luaToString))));
}); });
const assertFunction = new LuaBuiltinFunction( const assertFunction = new LuaBuiltinFunction(
@ -27,35 +28,35 @@ const assertFunction = new LuaBuiltinFunction(
}, },
); );
const ipairsFunction = new LuaBuiltinFunction((_sf, ar: LuaTable) => { const ipairsFunction = new LuaBuiltinFunction((sf, ar: LuaTable) => {
let i = 1; let i = 1;
return () => { return async () => {
if (i > ar.length) { if (i > ar.length) {
return; return;
} }
const result = new LuaMultiRes([i, ar.get(i)]); const result = new LuaMultiRes([i, await luaGet(ar, i, sf)]);
i++; i++;
return result; return result;
}; };
}); });
const pairsFunction = new LuaBuiltinFunction((_sf, t: LuaTable) => { const pairsFunction = new LuaBuiltinFunction((sf, t: LuaTable) => {
const keys = t.keys(); const keys = t.keys();
let i = 0; let i = 0;
return () => { return async () => {
if (i >= keys.length) { if (i >= keys.length) {
return; return;
} }
const key = keys[i]; const key = keys[i];
i++; i++;
return new LuaMultiRes([key, t.get(key)]); return new LuaMultiRes([key, await luaGet(t, key, sf)]);
}; };
}); });
const unpackFunction = new LuaBuiltinFunction((_sf, t: LuaTable) => { const unpackFunction = new LuaBuiltinFunction(async (sf, t: LuaTable) => {
const values: LuaValue[] = []; const values: LuaValue[] = [];
for (let i = 1; i <= t.length; i++) { for (let i = 1; i <= t.length; i++) {
values.push(t.get(i)); values.push(await luaGet(t, i, sf));
} }
return new LuaMultiRes(values); return new LuaMultiRes(values);
}); });