From 69c1da3dfb5a450c0d44f6e7f09677bf89379d50 Mon Sep 17 00:00:00 2001 From: Zef Hemel Date: Thu, 3 Oct 2024 18:52:44 +0200 Subject: [PATCH] [Lua] Property access and function call fixes --- common/space_lua/eval.test.ts | 6 ++++ common/space_lua/eval.ts | 20 ++++++++++++++ common/space_lua/parse.test.ts | 1 + common/space_lua/parse.ts | 50 +++++++++++++++++----------------- 4 files changed, 52 insertions(+), 25 deletions(-) diff --git a/common/space_lua/eval.test.ts b/common/space_lua/eval.test.ts index 31c1ccb4..3ef8602c 100644 --- a/common/space_lua/eval.test.ts +++ b/common/space_lua/eval.test.ts @@ -70,6 +70,12 @@ Deno.test("Evaluator test", async () => { assertEquals(singleResult(evalExpr(`test(3)`, env)), 3); assertEquals(singleResult(await evalExpr(`asyncTest(3) + 1`, env)), 4); + // Function expressions and table access + assertEquals( + await evalExpr(`(function() return {name="John"} end)().name`), + "John", + ); + // Function definitions const fn = evalExpr(`function(a, b) return a + b end`); assertEquals(fn.body.parameters, ["a", "b"]); diff --git a/common/space_lua/eval.ts b/common/space_lua/eval.ts index e3a17d23..aa2d36c0 100644 --- a/common/space_lua/eval.ts +++ b/common/space_lua/eval.ts @@ -104,6 +104,26 @@ export function evalExpression( return luaGet(singleResult(values[0]), singleResult(values[1])); } } + case "PropertyAccess": { + const obj = evalPrefixExpression(e.object, env); + if (obj instanceof Promise) { + return obj.then((obj) => { + if (!obj.get) { + throw new Error( + `Not a gettable object: ${obj}`, + ); + } + return obj.get(e.property); + }); + } else { + if (!obj.get) { + throw new Error( + `Not a gettable object: ${obj}`, + ); + } + return obj.get(e.property); + } + } case "Variable": case "FunctionCall": return evalPrefixExpression(e, env); diff --git a/common/space_lua/parse.test.ts b/common/space_lua/parse.test.ts index aaca7b60..93c848ef 100644 --- a/common/space_lua/parse.test.ts +++ b/common/space_lua/parse.test.ts @@ -27,6 +27,7 @@ Deno.test("Test Lua parser", () => { parse(`e({[3] = 1, [10 * 10] = "sup"})`); parse(`e(tbl.name)`); parse(`e(tbl["name" + 10])`); + parse(`e(test().bla)`); // Function calls parse(`e(func(), func(1, 2, 3), a.b(), a.b.c:hello(), (a.b)(7))`); diff --git a/common/space_lua/parse.ts b/common/space_lua/parse.ts index c371ebd5..f50cba99 100644 --- a/common/space_lua/parse.ts +++ b/common/space_lua/parse.ts @@ -184,14 +184,7 @@ function parseStatement(t: ParseTree): LuaStatement { case "FunctionCall": return { type: "FunctionCallStatement", - call: parseExpression( - { - type: "FunctionCall", - children: t.children!, - from: t.from, - to: t.to, - }, - ) as LuaFunctionCallExpression, + call: parseFunctionCall(t), }; case "Assign": return { @@ -223,6 +216,26 @@ function parseStatement(t: ParseTree): LuaStatement { } } +function parseFunctionCall(t: ParseTree): LuaFunctionCallExpression { + if (t.children![1].type === ":") { + return { + type: "FunctionCall", + prefix: parsePrefixExpression(t.children![0]), + name: t.children![2].children![0].text!, + args: parseFunctionArgs(t.children!.slice(3)), + from: t.from, + to: t.to, + }; + } + return { + type: "FunctionCall", + prefix: parsePrefixExpression(t.children![0]), + args: parseFunctionArgs(t.children!.slice(1)), + from: t.from, + to: t.to, + }; +} + function parseAttNames(t: ParseTree): LuaAttName[] { if (t.type !== "AttNameList") { throw new Error(`Expected AttNameList, got ${t.type}`); @@ -373,23 +386,7 @@ function parseExpression(t: ParseTree): LuaExpression { case "Parens": return parseExpression(t.children![1]); case "FunctionCall": { - if (t.children![1].type === ":") { - return { - type: "FunctionCall", - prefix: parsePrefixExpression(t.children![0]), - name: t.children![2].children![0].text!, - args: parseFunctionArgs(t.children!.slice(3)), - from: t.from, - to: t.to, - }; - } - return { - type: "FunctionCall", - prefix: parsePrefixExpression(t.children![0]), - args: parseFunctionArgs(t.children!.slice(1)), - from: t.from, - to: t.to, - }; + return parseFunctionCall(t); } case "FunctionDef": { const body = parseFunctionBody(t.children![1]); @@ -484,6 +481,9 @@ function parsePrefixExpression(t: ParseTree): LuaPrefixExpression { from: t.from, to: t.to, }; + case "FunctionCall": { + return parseFunctionCall(t); + } default: console.error(t); throw new Error(`Unknown prefix expression type: ${t.type}`);