From 4ecf6ed3ebde0dbc4edb113062f2a4b5a2b37f26 Mon Sep 17 00:00:00 2001 From: Sofia Date: Tue, 17 Mar 2026 22:45:43 +0200 Subject: [PATCH] Add indexed access expressions --- examples/test.lua | 1 + src/ast.rs | 35 +++++++++++++++++++++++++---------- src/compile.rs | 22 ++++++++++++++++++++++ 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/examples/test.lua b/examples/test.lua index b71855d..368bf4f 100644 --- a/examples/test.lua +++ b/examples/test.lua @@ -19,6 +19,7 @@ end global sometable = {} sometable["hello"] = {} sometable["hello"].there = "my dude" +print(sometable.hello.there) print(max(11.12345, 9)) print(add(10)(15)) diff --git a/src/ast.rs b/src/ast.rs index c48149f..12dfe0b 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -272,7 +272,7 @@ impl Parse for Statement { Ok(Self::Assignment( None, - vec![(access.0.0, access.0.1)], + vec![(access.0, access.1.0)], ExpressionList(vec![expression]), )) } else if let Ok(expr) = stream.parse() { @@ -290,12 +290,10 @@ pub enum AccessModifier { } #[derive(Debug, Clone)] -pub struct IndexedAccess(Node, Vec>); +pub struct IndexedAccess(Vec>); impl Parse for IndexedAccess { fn parse(mut stream: TokenStream) -> Result { - let name = stream.parse()?; - let mut expressions = Vec::new(); while let Some(Token::Symbol('[') | Token::Symbol('.')) = stream.peek() { match stream.next().unwrap() { @@ -315,18 +313,19 @@ impl Parse for IndexedAccess { } } - Ok(IndexedAccess(name, expressions)) + Ok(IndexedAccess(expressions)) } } #[derive(Debug, Clone)] -pub struct IndexedAssignment(IndexedAccess); +pub struct IndexedAssignment(Node, IndexedAccess); impl Parse for IndexedAssignment { fn parse(mut stream: TokenStream) -> Result { + let name = stream.parse()?; let access = stream.parse()?; stream.expect_symbol('=')?; - Ok(IndexedAssignment(access)) + Ok(IndexedAssignment(name, access)) } } @@ -339,6 +338,7 @@ pub enum Expression { FunctionCall(Box>, Node), Literal(Literal), TableConstructor, + IndexedAccess(Box>, Box>), } impl Parse for Expression { @@ -501,9 +501,11 @@ impl Parse for PrimaryExpression { Expression::ValueRef(stream.parse()?) }; - while let Some(Token::Symbol('(') | Token::Symbol('[')) = stream.peek() { - match stream.next().unwrap() { + while let Some(Token::Symbol('(') | Token::Symbol('[') | Token::Symbol('.')) = stream.peek() + { + match stream.peek().unwrap() { Token::Symbol('(') => { + stream.next(); let expression_list = stream.parse::>()?; stream.expect(Token::Symbol(')'))?; expression = Expression::FunctionCall( @@ -514,7 +516,20 @@ impl Parse for PrimaryExpression { expression_list, ); } - Token::Symbol('[') => todo!(), + Token::Symbol('[') | Token::Symbol('.') => { + let meta = Metadata::produce(&mut stream, pre.clone()); + let IndexedAccess(accesses) = stream.parse()?; + dbg!(&accesses, stream.peek()); + for access in accesses { + expression = Expression::IndexedAccess( + Box::new(Node { + kind: expression, + meta: meta.clone(), + }), + Box::new(access), + ) + } + } _ => panic!(), } } diff --git a/src/compile.rs b/src/compile.rs index a8d5087..4348191 100644 --- a/src/compile.rs +++ b/src/compile.rs @@ -405,6 +405,12 @@ impl Expression { let constants = HashSet::new(); constants } + Expression::IndexedAccess(expr, index) => { + let mut constants = HashSet::new(); + constants.extend(expr.kind.find_constants(scope)); + constants.extend(index.kind.find_constants(scope)); + constants + } } } @@ -630,6 +636,22 @@ impl Expression { instructions.push(Instruction::NewTable(reg)); (instructions, vec![reg]) } + Expression::IndexedAccess(expr, index) => { + let mut instructions = Vec::new(); + let (instr, expr_regs) = expr.kind.compile(state, scope, Some(1)); + instructions.extend(instr); + let (instr, index_regs) = index.kind.compile(state, scope, Some(1)); + instructions.extend(instr); + + let local = scope.register_counter.next(); + instructions.push(Instruction::GetTable( + local, + *expr_regs.first().unwrap(), + *index_regs.first().unwrap(), + )); + + (instructions, vec![local]) + } } } }