Files
plainleaf/client/plugos/syscalls/lua.ts
T

59 lines
2.0 KiB
TypeScript

import type { SysCallMapping } from "../system.ts";
import { evalExpression } from "../../space_lua/eval.ts";
import { parse, parseExpressionString } from "../../space_lua/parse.ts";
import {
LuaStackFrame,
luaToString,
luaValueToJS,
} from "../../space_lua/runtime.ts";
import { buildThreadLocalEnv } from "../../space_lua_api.ts";
import { isSendable } from "../util.ts";
import type { LuaBlock, LuaExpression } from "../../space_lua/ast.ts";
import type { ClientSystem } from "../../client_system.ts";
export function luaSyscalls(clientSystem: ClientSystem): SysCallMapping {
return {
"lua.parse": (_ctx, code: string): LuaBlock => {
return parse(code);
},
"lua.parseExpression": (_ctx, expression: string): LuaExpression => {
return parseExpressionString(expression);
},
/**
* 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(
clientSystem.system,
clientSystem.spaceLuaEnv.env,
);
const sf = new LuaStackFrame(env, null);
const luaResult = await evalExpression(
ast,
clientSystem.spaceLuaEnv.env,
sf,
);
const jsResult = luaValueToJS(luaResult, sf);
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;
}
},
};
}