[Lua] Property access and function call fixes

pull/1110/head
Zef Hemel 2024-10-03 18:52:44 +02:00
parent b2ff858f1d
commit 69c1da3dfb
4 changed files with 52 additions and 25 deletions

View File

@ -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"]);

View File

@ -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);

View File

@ -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))`);

View File

@ -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}`);