silverbullet/common/syscalls/lua.ts

55 lines
1.8 KiB
TypeScript

import type { SysCallMapping } from "$lib/plugos/system.ts";
import { evalExpression } from "$common/space_lua/eval.ts";
import { parse, parseExpressionString } from "../space_lua/parse.ts";
import type { CommonSystem } from "$common/common_system.ts";
import {
LuaStackFrame,
luaToString,
luaValueToJS,
} from "$common/space_lua/runtime.ts";
import { buildThreadLocalEnv } from "$common/space_lua_api.ts";
import { isSendable } from "$lib/plugos/util.ts";
export function luaSyscalls(commonSystem: CommonSystem): SysCallMapping {
return {
"lua.parse": (_ctx, code: string) => {
return parse(code);
},
/**
* Evaluates a Lua expression and returns the result as a JavaScript value
* @param _ctx
* @param expression
* @returns
*/
"lua.evalExpression": async (_ctx, expression: string) => {
try {
const ast = parseExpressionString(expression);
const env = await buildThreadLocalEnv(
commonSystem.system,
commonSystem.spaceLuaEnv.env,
);
const sf = new LuaStackFrame(env, null);
const luaResult = await evalExpression(
ast,
commonSystem.spaceLuaEnv.env,
sf,
);
const jsResult = luaValueToJS(luaResult);
if (isSendable(jsResult)) {
return jsResult;
} else {
// This may evaluate to e.g. a function, which is not sendable, in this case we'll console.warn and return a stringified version of the result
console.warn(
"Lua eval result is not sendable, returning stringified version",
jsResult,
);
return luaToString(luaResult);
}
} catch (e: any) {
console.error("Lua eval error: ", e.message, e.sf?.astCtx);
throw e;
}
},
};
}