diff --git a/common/markdown_parser/parser.test.ts b/common/markdown_parser/parser.test.ts index 0c11be0b..6e79ddfa 100644 --- a/common/markdown_parser/parser.test.ts +++ b/common/markdown_parser/parser.test.ts @@ -160,7 +160,8 @@ Deno.test("Test 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)); }); diff --git a/common/space_lua/eval.ts b/common/space_lua/eval.ts index 11a3363f..970bee18 100644 --- a/common/space_lua/eval.ts +++ b/common/space_lua/eval.ts @@ -312,63 +312,70 @@ function evalPrefixExpression( ); } - // Special handling for f(...) - propagate varargs - if ( - e.args.length === 1 && e.args[0].type === "Variable" && - e.args[0].name === "..." - ) { - const varargs = env.get("..."); - const resolveVarargs = async () => { - const resolvedVarargs = await Promise.resolve(varargs); - if (resolvedVarargs instanceof LuaTable) { - const args = []; - for (let i = 1; i <= resolvedVarargs.length; i++) { - const val = await Promise.resolve(resolvedVarargs.get(i)); - args.push(val); + const handleFunctionCall = (prefixValue: LuaValue) => { + // Special handling for f(...) - propagate varargs + if ( + e.args.length === 1 && e.args[0].type === "Variable" && + e.args[0].name === "..." + ) { + const varargs = env.get("..."); + const resolveVarargs = async () => { + const resolvedVarargs = await Promise.resolve(varargs); + if (resolvedVarargs instanceof LuaTable) { + const args = []; + for (let i = 1; i <= resolvedVarargs.length; i++) { + const val = await Promise.resolve(resolvedVarargs.get(i)); + args.push(val); + } + return args; } - return args; - } - return []; - }; + return []; + }; - if (prefixValue instanceof Promise) { - return prefixValue.then(async (resolvedPrefix) => { - const args = await resolveVarargs(); - return luaCall(resolvedPrefix, args, e.ctx, sf.withCtx(e.ctx)); - }); - } else { - return resolveVarargs().then((args) => - luaCall(prefixValue, args, e.ctx, sf.withCtx(e.ctx)) + if (prefixValue instanceof Promise) { + return prefixValue.then(async (resolvedPrefix) => { + const args = await resolveVarargs(); + return luaCall(resolvedPrefix, args, e.ctx, sf.withCtx(e.ctx)); + }); + } else { + return resolveVarargs().then((args) => + 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), ); } - } - - // 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) + 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) + ); + } else { + return luaCall(prefixValue, [...selfArgs, ...args], e.ctx, sf); + } + }; + if (prefixValue instanceof Promise) { + return prefixValue.then(handleFunctionCall); } else { - return luaCall(prefixValue, [...selfArgs, ...args], e.ctx, sf); + return handleFunctionCall(prefixValue); } } default: diff --git a/common/space_lua/stdlib.ts b/common/space_lua/stdlib.ts index 29a54d5b..cebfffb8 100644 --- a/common/space_lua/stdlib.ts +++ b/common/space_lua/stdlib.ts @@ -3,9 +3,10 @@ import { LuaBuiltinFunction, luaCall, LuaEnv, + luaGet, LuaMultiRes, LuaRuntimeError, - type LuaTable, + LuaTable, luaToString, luaTypeOf, 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 { jsApi } from "$common/space_lua/stdlib/js.ts"; -const printFunction = new LuaBuiltinFunction((_sf, ...args) => { - console.log("[Lua]", ...args.map(luaToString)); +const printFunction = new LuaBuiltinFunction(async (_sf, ...args) => { + console.log("[Lua]", ...(await Promise.all(args.map(luaToString)))); }); 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; - return () => { + return async () => { if (i > ar.length) { return; } - const result = new LuaMultiRes([i, ar.get(i)]); + const result = new LuaMultiRes([i, await luaGet(ar, i, sf)]); i++; return result; }; }); -const pairsFunction = new LuaBuiltinFunction((_sf, t: LuaTable) => { +const pairsFunction = new LuaBuiltinFunction((sf, t: LuaTable) => { const keys = t.keys(); let i = 0; - return () => { + return async () => { if (i >= keys.length) { return; } const key = keys[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[] = []; for (let i = 1; i <= t.length; i++) { - values.push(t.get(i)); + values.push(await luaGet(t, i, sf)); } return new LuaMultiRes(values); });