From 70e59fea39914ab39ff530298efd77532e899e7a Mon Sep 17 00:00:00 2001 From: ghostly_zsh Date: Sat, 31 Aug 2024 13:10:34 -0500 Subject: [PATCH] subscript assignment parsing --- kabel/grammar.ebnf | 4 +- kabel/opcodes.txt | 4 - kabel/src/ast.rs | 24 ++--- kabel/src/codegen.rs | 20 ++--- kabel/src/debug.rs | 20 ++++- kabel/src/macros.rs | 47 ++++++---- kabel/src/name_resolution.rs | 92 +++++++++++-------- kabel/src/parser.rs | 169 ++++++++++++++++++----------------- kabel/tmp.kab | 6 +- 9 files changed, 219 insertions(+), 167 deletions(-) diff --git a/kabel/grammar.ebnf b/kabel/grammar.ebnf index 496d3d66b01a9b13528c5d3531a3b679e7c94249..fa6fefb2601fbe0354c64f4c997e9b6b20703b8e 100644 --- a/kabel/grammar.ebnf +++ b/kabel/grammar.ebnf @@ -22,7 +22,7 @@ expression_statement = expression , ";" ; expression = assignment ; -assignment = ( identifier , ( "=" | "+=" | "-=" | "*=" +assignment = ( assignment_pattern , ( "=" | "+=" | "-=" | "*=" | "/=" | "%=" | "&=" | "^=" | "|=" ) , assignment ) | anonymous_function ; anonymous_function = ( "(" , { identifier , "," , } ")" , "=>" , block ) | ternary ; @@ -64,3 +64,5 @@ group = "(" , expression , ")" ; identifier = alphabetic , { alphabetic | digit } ; string = '"' , { character - '"' } , '"' ; number = digit , { digit } , [ "." , digit , { digit } ] ; + +assignment_pattern = identifier | subscript ; diff --git a/kabel/opcodes.txt b/kabel/opcodes.txt index 89196d4deccbf4e4abf613d230defd824fabe056..a95da8e84be7eeda43eabe9cce2eb0adffbb2f97 100644 --- a/kabel/opcodes.txt +++ b/kabel/opcodes.txt @@ -18,17 +18,13 @@ LS ; 0x0F LE ; 0x10 OR ; 0x11 AND ; 0x12 - NOT ; 0x13 NEG ; 0x14 - JMP LOC ; 0x15 JMP_UP LOC ; 0x16 JNE ELSE ; 0x17 - CALL ARITY ; 0x18 RET ; 0x19 - LIST LEN ; 0x1A SCR ; 0x1B diff --git a/kabel/src/ast.rs b/kabel/src/ast.rs index 92f42d3f570f7f11079de797d60dd604d6837975..bff6c3b1abadb3d9bfe5f56f756307ecf49b8ebc 100644 --- a/kabel/src/ast.rs +++ b/kabel/src/ast.rs @@ -1,14 +1,9 @@ use crate::extension::Extension; -#[derive(Debug, Clone)] -pub struct AST { - pub ast_type: ASTType, - pub extensions: Vec, - pub start_line: usize, - pub end_line: usize, - pub start_column: usize, - pub end_column: usize, -} +crate::ast!(AST { + kind: ASTType, + extensions: Vec +}); #[derive(Debug, Clone)] pub enum ASTType { @@ -35,7 +30,7 @@ pub enum ASTType { Print(Box), // expressions - Assign(Name, Box), + Assign(LhsAssign, Box), Anonymous(Vec, Box), Ternary(Box, Box, Box), Subscript(Box, Box), @@ -90,3 +85,12 @@ pub enum UnOp { Not, Neg, } + +crate::ast!(LhsAssign { kind: LhsAssignType, extensions: Vec }); + +#[derive(Debug, Clone)] +pub enum LhsAssignType { + Ident(String), + Subscript(Box, Box), +} + diff --git a/kabel/src/codegen.rs b/kabel/src/codegen.rs index 0f0d7699f0775f4fdda642d1b5f1d5b1842017a3..449ce001aae51b57f5782579b9ff352849dde2d2 100644 --- a/kabel/src/codegen.rs +++ b/kabel/src/codegen.rs @@ -1,4 +1,4 @@ -use crate::{ast::{ASTType, BinOp, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Function, Unit, Value, VM}}; +use crate::{ast::{ASTType, BinOp, LhsAssign, Lit, Name, UnOp, AST}, codegen_binary, codegen_unary, extension::Extension, opcodes::OpCode, vm::{Function, Unit, Value, VM}}; pub struct Codegen { pub vm: VM, @@ -19,7 +19,7 @@ impl Codegen { } pub fn visit(&mut self, ast: AST) { use crate::ast::ASTType::*; - match ast.ast_type { + match ast.kind { Program(asts) => { for ast in asts { self.visit(ast); @@ -114,7 +114,7 @@ impl Codegen { })); self.scopes.last_mut().expect("codegen scopes vec was empty").1 += args.len(); - if let ASTType::Block(ref stmts) = block.ast_type { + if let ASTType::Block(ref stmts) = block.kind { self.visit_block(&block, stmts.clone(), ScopeType::Function); } match self.vm.units[self.vm.unit_ptr].code.last() { @@ -184,7 +184,7 @@ impl Codegen { } else { self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } - if let ASTType::Block(ref stmts) = block.ast_type { + if let ASTType::Block(ref stmts) = block.kind { self.visit_block(&block, stmts.clone(), ScopeType::Loop); } self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP_UP.into()); @@ -234,7 +234,7 @@ impl Codegen { self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 3; } } - if let ASTType::Block(ref stmts) = block.ast_type { + if let ASTType::Block(ref stmts) = block.kind { self.visit_block(&block, stmts.clone(), ScopeType::Loop); } let continues = self.continue_stack.pop().expect("continue stack empty on pop"); @@ -344,11 +344,11 @@ impl Codegen { } else { self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 5; } - if let ASTType::Block(ref stmts) = block.ast_type { + if let ASTType::Block(ref stmts) = block.kind { self.visit_block(&block, stmts.clone(), ScopeType::If); } if let Some(ast) = else_expr { - match ast.ast_type { + match ast.kind { ASTType::If(_, _, _) => { self.vm.units[self.vm.unit_ptr].code.push(OpCode::JMP.into()); self.vm.units[self.vm.unit_ptr].code.push(0xFF); // placeholder @@ -377,7 +377,7 @@ impl Codegen { let end_jmp_loc = self.vm.units[self.vm.unit_ptr].code.len()-2; self.patch_jump(start_jmp_loc, 0); // jmp to else - if let ASTType::Block(ref stmts) = ast.ast_type { + if let ASTType::Block(ref stmts) = ast.kind { self.visit_block(&ast, stmts.clone(), ScopeType::If); } self.patch_jump(end_jmp_loc, 0); // jmp to after else @@ -432,7 +432,7 @@ impl Codegen { self.vm.units[self.vm.unit_ptr].lines.last_mut().unwrap().1 += 1; } } - pub fn visit_assign(&mut self, ast: &AST, _name: Name, expr: AST) { + pub fn visit_assign(&mut self, ast: &AST, _name: LhsAssign, expr: AST) { self.visit(expr); // pop stack to get value. then find variable in stack. set variable to value. self.vm.units[self.vm.unit_ptr].code.push(OpCode::ASSIGN.into()); @@ -479,7 +479,7 @@ impl Codegen { // update scopes with number of parameters self.scopes.last_mut().expect("codegen scopes vec was empty").1 += params.len(); - if let ASTType::Block(ref stmts) = block.ast_type { + if let ASTType::Block(ref stmts) = block.kind { self.visit_block(&block, stmts.clone(), ScopeType::Function); } // add implicit RET diff --git a/kabel/src/debug.rs b/kabel/src/debug.rs index 22dea802a0ae4aeae9d8c0a5fb9ca16a33b2981b..f48fe0e4d145ff4ea1aa80ef524da3f8b01f4155 100644 --- a/kabel/src/debug.rs +++ b/kabel/src/debug.rs @@ -1,4 +1,4 @@ -use crate::{ast::AST, lexer::Token, push_codegen, push_output, vm::{Value, VM}}; +use crate::{ast::{LhsAssignType, AST}, lexer::Token, push_codegen, push_output, vm::{Value, VM}}; pub fn debug_token_array(tokens: Vec) -> String { let mut output = "".to_string(); @@ -14,7 +14,7 @@ pub fn debug_ast(ast: AST, level: usize) -> String { use crate::ast::UnOp::*; use crate::ast::Lit::*; let mut output = "".to_string(); - match ast.ast_type { + match ast.kind { Program(asts) => { output += &"| ".repeat(level); output += "Program"; @@ -123,10 +123,22 @@ pub fn debug_ast(ast: AST, level: usize) -> String { output += "\n"; output += &debug_ast(*expr, level+1); } - Assign(name, expr) => { + Assign(lhs, expr) => { output += &"| ".repeat(level); output += "Assign "; - output += &name.name; + match lhs.kind { + LhsAssignType::Ident(name) => { + output += &name; + } + LhsAssignType::Subscript(name, index) => { + output += "\n"; + output += &"| ".repeat(level+1); + output += "Subscript\n"; + output += &debug_ast(*name, level+2); + output += "\n"; + output += &debug_ast(*index, level+2); + } + } output += &format!(" {:?}", ast.extensions); output += "\n"; output += &debug_ast(*expr, level+1); diff --git a/kabel/src/macros.rs b/kabel/src/macros.rs index 8f74e8197ff61c717d49a8c7b4804695fa409b51..7f9431846cc7c00f761be9a267e2fef8c01109e7 100644 --- a/kabel/src/macros.rs +++ b/kabel/src/macros.rs @@ -20,11 +20,26 @@ macro_rules! token_display { } } +#[macro_export] +macro_rules! ast { + ( $ast:ident { $field:ident: $ast_type:ty $( , $extra_field:ident: $extra_type:ty )* } ) => { + #[derive(::std::fmt::Debug, ::std::clone::Clone)] + pub struct $ast { + pub $field: $ast_type, + pub start_line: usize, + pub end_line: usize, + pub start_column: usize, + pub end_column: usize, + $( pub $extra_field: $extra_type ),* + } + } +} + #[macro_export] macro_rules! lit { ($type:ident, $data:expr, $token:expr) => { $crate::parser::AST { - ast_type: $crate::parser::ASTType::Lit($crate::parser::Lit::$type($data)), + kind: $crate::parser::ASTType::Lit($crate::parser::Lit::$type($data)), extensions: Vec::new(), start_line: $token.line, end_line: $token.line, @@ -36,9 +51,9 @@ macro_rules! lit { #[macro_export] macro_rules! ast_from_token { - ($ast_type:expr, $start:expr, $end:expr) => { - $crate::parser::AST { - ast_type: $ast_type, + ($ast:tt, $kind:expr, $start:expr, $end:expr) => { + $ast { + kind: $kind, extensions: Vec::new(), start_line: $start.line, end_line: $end.line, @@ -49,9 +64,9 @@ macro_rules! ast_from_token { } #[macro_export] macro_rules! ast_from_token_ast { - ($ast_type:expr, $start:expr, $end:expr) => { - $crate::parser::AST { - ast_type: $ast_type, + ($ast:tt, $kind:expr, $start:expr, $end:expr) => { + $ast { + kind: $kind, extensions: Vec::new(), start_line: $start.line, end_line: $end.end_line, @@ -62,9 +77,9 @@ macro_rules! ast_from_token_ast { } #[macro_export] macro_rules! ast_from_ast { - ($ast_type:expr, $start:expr, $end:expr) => { - AST { - ast_type: $ast_type, + ($ast:tt, $kind:expr, $start:expr, $end:expr) => { + $ast { + kind: $kind, extensions: Vec::new(), start_line: $start.start_line, end_line: $end.end_line, @@ -75,9 +90,9 @@ macro_rules! ast_from_ast { } #[macro_export] macro_rules! ast_from_ast_token { - ($ast_type:expr, $start:expr, $end:expr) => { - AST { - ast_type: $ast_type, + ($ast:tt, $kind:expr, $start:expr, $end:expr) => { + $ast { + kind: $kind, extensions: Vec::new(), start_line: $start.start_line, end_line: $end.line, @@ -177,17 +192,17 @@ macro_rules! out_of_scope_var { format!($message, $name.name), Some(format!($hint, $( $hint_fmt ),*)), $expr.start_line, - $name.start_column, + $expr.start_column, $crate::collect_lines!($self.text[$expr.start_line..$expr.end_line+1]), ) }; ($self:expr, $type:expr, $expr:expr, $message:expr, $name:expr) => { $crate::error::KabelError::new( $type, - format!($message, $name.name), + format!($message, $name), None, $expr.start_line, - $name.start_column, + $expr.start_column, $crate::collect_lines!($self.text[$expr.start_line..$expr.end_line+1]), ) }; diff --git a/kabel/src/name_resolution.rs b/kabel/src/name_resolution.rs index aef3a592e173b104222958c5694477375a9f6787..558214ef4c54bfe357d20ea14521facd15d4826f 100644 --- a/kabel/src/name_resolution.rs +++ b/kabel/src/name_resolution.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::{ast::{ASTType, AST}, ast_error, ast_from_ast, error::{ErrorKind, KabelError}, extension::Extension, out_of_scope_var}; +use crate::{ast::{ASTType, LhsAssign, LhsAssignType, AST}, ast_error, ast_from_ast, error::{ErrorKind, KabelError}, extension::Extension, out_of_scope_var}; pub struct Resolver { text: Vec, @@ -22,7 +22,7 @@ impl Resolver { } pub fn visit(&mut self, ast: AST) -> AST { use ASTType::*; - match ast.ast_type { + match ast.kind { Program(asts) => { let mut program = Vec::new(); for ast in asts { @@ -30,7 +30,7 @@ impl Resolver { program.push(ast) } AST { - ast_type: ASTType::Program(program), + kind: ASTType::Program(program), extensions: Vec::new(), start_line: 0, end_line: 0, @@ -77,7 +77,7 @@ impl Resolver { self.symbol_table.pop(); self.locals.pop(); AST { - ast_type: Function(name, args, Box::new(block)), + kind: Function(name, args, Box::new(block)), extensions: vec![Extension::Resolution(self.scope, self.locals.last().expect("locals last in function ast len").len()-1)], start_line: ast.start_line, end_line: ast.end_line, @@ -88,21 +88,21 @@ impl Resolver { Return(expr) => { if let Some(expr) = *expr { let expr = self.visit(expr); - return ast_from_ast!(Return(Box::new(Some(expr))), ast, ast); + return ast_from_ast!(AST, Return(Box::new(Some(expr))), ast, ast); } - ast_from_ast!(Return(Box::new(None)), ast, ast) + ast_from_ast!(AST, Return(Box::new(None)), ast, ast) } Loop(block) => { let block = self.visit(*block); - ast_from_ast!(Loop(Box::new(block)), ast, ast) + ast_from_ast!(AST, Loop(Box::new(block)), ast, ast) } While(condition, block) => { let condition = self.visit(*condition); let block = self.visit(*block); - ast_from_ast!(While(Box::new(condition), Box::new(block)), ast, ast) + ast_from_ast!(AST, While(Box::new(condition), Box::new(block)), ast, ast) } - Break => { ast_from_ast!(Break, ast, ast) } - Continue => { ast_from_ast!(Continue, ast, ast) } + Break => { ast_from_ast!(AST, Break, ast, ast) } + Continue => { ast_from_ast!(AST, Continue, ast, ast) } For(expr1, expr2, expr3, block) => { self.symbol_table.push(HashMap::new()); self.scope += 1; @@ -128,7 +128,7 @@ impl Resolver { } self.scope -= 1; self.symbol_table.pop(); - ast_from_ast!(For(Box::new(n_expr1), Box::new(n_expr2), Box::new(n_expr3), Box::new(block)), ast, ast) + ast_from_ast!(AST, For(Box::new(n_expr1), Box::new(n_expr2), Box::new(n_expr3), Box::new(block)), ast, ast) } If(condition, block, else_expr) => { let condition = self.visit(*condition); @@ -137,7 +137,7 @@ impl Resolver { if let Some(else_expr) = *else_expr { n_else_expr = Some(self.visit(else_expr)); } - ast_from_ast!(If(Box::new(condition), Box::new(block), Box::new(n_else_expr)), ast, ast) + ast_from_ast!(AST, If(Box::new(condition), Box::new(block), Box::new(n_else_expr)), ast, ast) } Block(stmts) => { self.symbol_table.push(HashMap::new()); @@ -160,7 +160,7 @@ impl Resolver { } self.scope -= 1; self.symbol_table.pop(); - ast_from_ast!(Block(n_stmts), ast, ast) + ast_from_ast!(AST, Block(n_stmts), ast, ast) } Decl(name, expr) => { let expr = self.visit(*expr); @@ -190,7 +190,7 @@ impl Resolver { } self.symbol_table.last_mut().unwrap().insert(name.name.clone(), (Symbol::Var, self.locals.last().expect("locals last in decl symbol").len()-1)); AST { - ast_type: Decl(name, Box::new(expr)), + kind: Decl(name, Box::new(expr)), extensions: vec![Extension::Resolution(self.scope, self.locals.last().expect("locals last in decl ast").len()-1)], start_line: ast.start_line, end_line: ast.end_line, @@ -200,28 +200,44 @@ impl Resolver { } Expr(expr) => { let expr = self.visit(*expr); - ast_from_ast!(Expr(Box::new(expr)), ast, ast) + ast_from_ast!(AST, Expr(Box::new(expr)), ast, ast) } // REMOVE LATER Print(expr) => { let expr = self.visit(*expr); - ast_from_ast!(Print(Box::new(expr)), ast, ast) + ast_from_ast!(AST, Print(Box::new(expr)), ast, ast) } - Assign(name, expr) => { + Assign(lhs , expr) => { let expr = self.visit(*expr); - let resolution = self.resolve_var(&name.name); - if !resolution.0 { - self.errors.push(out_of_scope_var!(self, - ErrorKind::OutOfScope, ast, - "Variable \"{}\" not in scope", name)); - } - AST { - ast_type: Assign(name, Box::new(expr)), - extensions: vec![Extension::Resolution(self.scope, resolution.1)], - start_line: ast.start_line, - end_line: ast.end_line, - start_column: ast.start_column, - end_column: ast.end_column, + match lhs.kind.clone() { + LhsAssignType::Ident(name) => { + let resolution = self.resolve_var(&name); + if !resolution.0 { + self.errors.push(out_of_scope_var!(self, + ErrorKind::OutOfScope, lhs, + "Variable \"{}\" not in scope", name)); + } + AST { + kind: Assign(lhs, Box::new(expr)), + extensions: vec![Extension::Resolution(self.scope, resolution.1)], + start_line: ast.start_line, + end_line: ast.end_line, + start_column: ast.start_column, + end_column: ast.end_column, + } + } + LhsAssignType::Subscript(name, index) => { + let name = self.visit(*name); + let index = self.visit(*index); + AST { + kind: Assign(ast_from_ast!(LhsAssign, LhsAssignType::Subscript(Box::new(name), Box::new(index)), lhs, lhs), Box::new(expr)), + extensions: Vec::new(), + start_line: ast.start_line, + end_line: ast.end_line, + start_column: ast.start_column, + end_column: ast.end_column, + } + } } } Anonymous(params, block) => { @@ -235,27 +251,27 @@ impl Resolver { let block = self.visit(*block); self.symbol_table.pop(); self.locals.pop(); - ast_from_ast!(Anonymous(params, Box::new(block)), ast, ast) + ast_from_ast!(AST, Anonymous(params, Box::new(block)), ast, ast) } Ternary(condition, true_expr, false_expr) => { let condition = self.visit(*condition); let true_expr = self.visit(*true_expr); let false_expr = self.visit(*false_expr); - ast_from_ast!(Ternary(Box::new(condition), Box::new(true_expr), Box::new(false_expr)), ast, ast) + ast_from_ast!(AST, Ternary(Box::new(condition), Box::new(true_expr), Box::new(false_expr)), ast, ast) } Subscript(array, index) => { let array = self.visit(*array); let index = self.visit(*index); - ast_from_ast!(Subscript(Box::new(array), Box::new(index)), ast, ast) + ast_from_ast!(AST, Subscript(Box::new(array), Box::new(index)), ast, ast) } Binary(left, oper, right) => { let left = self.visit(*left); let right = self.visit(*right); - ast_from_ast!(Binary(Box::new(left), oper, Box::new(right)), ast, ast) + ast_from_ast!(AST, Binary(Box::new(left), oper, Box::new(right)), ast, ast) } Unary(oper, right) => { let right = self.visit(*right); - ast_from_ast!(Unary(oper, Box::new(right)), ast, ast) + ast_from_ast!(AST, Unary(oper, Box::new(right)), ast, ast) } Lit(ref lit) => { let lit = lit.clone(); @@ -266,7 +282,7 @@ impl Resolver { self.errors.push(ast_error!(self, ErrorKind::OutOfScope, ast, "Variable \"{}\" not in scope", name)) } else { return AST { - ast_type: Lit(lit), + kind: Lit(lit), extensions: vec![Extension::Resolution(self.scope, resolution.1)], start_line: ast.start_line, end_line: ast.end_line, @@ -277,7 +293,7 @@ impl Resolver { } _ => {} } - ast_from_ast!(Lit(lit), ast, ast) + ast_from_ast!(AST, Lit(lit), ast, ast) } Call(ident, args) => { let ident = self.visit(*ident.clone()); @@ -286,7 +302,7 @@ impl Resolver { n_args.push(self.visit(arg)); } return AST { - ast_type: Call(Box::new(ident), n_args), + kind: Call(Box::new(ident), n_args), extensions: Vec::new(), start_line: ast.start_line, end_line: ast.end_line, diff --git a/kabel/src/parser.rs b/kabel/src/parser.rs index 6b4a461115724c4c6d910f3660dc70117d5689d3..82c9dbd1e3dcb52a2d49d60ac7c52eae486c8047 100644 --- a/kabel/src/parser.rs +++ b/kabel/src/parser.rs @@ -1,5 +1,5 @@ use crate::{ - ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, name, unexpected_token + ast::{LhsAssign, LhsAssignType}, ast_from_ast, ast_from_ast_token, ast_from_token, ast_from_token_ast, collect_lines, error::{ErrorKind, KabelError}, lexer::{Token, TokenType}, lit, name, unexpected_token }; use crate::ast::{AST, ASTType, BinOp, UnOp, Lit}; @@ -34,7 +34,7 @@ impl Parser { } } AST { - ast_type: ASTType::Program(program), + kind: ASTType::Program(program), extensions: Vec::new(), start_line: 0, end_line: 0, @@ -81,7 +81,7 @@ impl Parser { let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Function( name!(name, ident), expressions, @@ -109,7 +109,7 @@ impl Parser { let return_ident = self.read_token()?; if let TokenType::Semicolon = self.peek()?.token_type { let semicolon = self.read_token()?; - return Ok(ast_from_token!( + return Ok(ast_from_token!(AST, ASTType::Return(Box::new(None)), return_ident, semicolon @@ -118,7 +118,7 @@ impl Parser { let expression = self.expression()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { - Ok(ast_from_token!( + Ok(ast_from_token!(AST, ASTType::Return(Box::new(Some(expression))), return_ident, semicolon @@ -131,7 +131,7 @@ impl Parser { pub fn loop_statement(&mut self) -> Result { let loop_ident = self.read_token()?; let block = self.block()?; - Ok(ast_from_token_ast!( + Ok(ast_from_token_ast!(AST, ASTType::Loop(Box::new(block.clone())), loop_ident, block @@ -146,7 +146,7 @@ impl Parser { let right_paren = self.read_token()?; if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::While(Box::new(condition), Box::new(block.clone())), while_ident, block @@ -195,7 +195,7 @@ impl Parser { if let TokenType::RightParen = right_paren.token_type { let block = self.block()?; //return Ok(Self::build_for(for_ident, semicolon_2, expression1, expression2, expression3, block)); - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::For( Box::new(expression1), Box::new(expression2), @@ -222,7 +222,7 @@ impl Parser { } let mut new_block = block.clone(); if let Some(expression3) = expression3 { - if let ASTType::Block(inner) = block.clone().ast_type { + if let ASTType::Block(inner) = block.clone().kind { let mut new_inner = inner; new_inner.push(ast_from_ast!(ASTType::Expr(Box::new(expression3.clone())), expression3, expression3)); new_block = ast_from_ast!(ASTType::Block(new_inner), block, block); @@ -241,7 +241,7 @@ impl Parser { let break_ident = self.read_token()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { - Ok(ast_from_token!(ASTType::Break, break_ident, semicolon)) + Ok(ast_from_token!(AST, ASTType::Break, break_ident, semicolon)) } else { Err(unexpected_token!(self, "Expected ; but found {}", semicolon)) } @@ -251,7 +251,7 @@ impl Parser { let continue_ident = self.read_token()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { - Ok(ast_from_token!(ASTType::Continue, continue_ident, semicolon)) + Ok(ast_from_token!(AST, ASTType::Continue, continue_ident, semicolon)) } else { Err(unexpected_token!(self, "Expected ; but found {}", semicolon)) } @@ -271,7 +271,7 @@ impl Parser { self.read_token()?; if let TokenType::LeftBrace = self.peek()?.token_type { let else_block = self.block()?; - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::If( Box::new(condition), Box::new(block.clone()), @@ -284,7 +284,7 @@ impl Parser { let else_if_ident = self.peek()?; if let TokenType::If = else_if_ident.token_type { let else_if = self.if_statement()?; - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::If( Box::new(condition), Box::new(block.clone()), @@ -297,7 +297,7 @@ impl Parser { return Err(unexpected_token!(self, "Unexpected token {}", else_ident)); } } - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::If(Box::new(condition), Box::new(block.clone()), Box::new(None)), if_ident, block @@ -318,7 +318,7 @@ impl Parser { stmts.push(self.statement()?); } let right_brace = self.read_token()?; - return Ok(ast_from_token!(ASTType::Block(stmts), left_brace, right_brace)); + return Ok(ast_from_token!(AST, ASTType::Block(stmts), left_brace, right_brace)); } else { return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace)); } @@ -333,7 +333,7 @@ impl Parser { let expr = self.expression()?; let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { - return Ok(ast_from_token!( + return Ok(ast_from_token!(AST, ASTType::Decl(name!(name, ident), Box::new(expr.clone())), var, semicolon @@ -359,7 +359,7 @@ impl Parser { let expression = self.expression()?; let semicolon = self.read_token()?; if matches!(semicolon.token_type, TokenType::Semicolon) { - Ok(ast_from_token!(ASTType::Print(Box::new(expression)), print_ident, semicolon)) + Ok(ast_from_token!(AST, ASTType::Print(Box::new(expression)), print_ident, semicolon)) } else { Err(unexpected_token!(self, "Expected ; but found {}", semicolon)) } @@ -380,7 +380,7 @@ impl Parser { } let semicolon = self.read_token()?; if let TokenType::Semicolon = semicolon.token_type { - return Ok(ast_from_ast_token!(ASTType::Expr(Box::new(expression.clone())), + return Ok(ast_from_ast_token!(AST, ASTType::Expr(Box::new(expression.clone())), expression, semicolon)); } else { self.current -= 1; @@ -396,6 +396,15 @@ impl Parser { pub fn assignment(&mut self) -> Result { if let TokenType::Ident(name) = self.peek()?.token_type { let ident = self.read_token()?; + let lhs_type; + if let TokenType::LeftSquare = self.peek()?.token_type { + self.read_token()?; + let index = self.expression()?; + let right_square = self.read_token()?; + lhs_type = ast_from_token!(LhsAssign, LhsAssignType::Subscript(Box::new(lit!(Ident, name.clone(), ident)), Box::new(index)), ident, right_square); + } else { + lhs_type = ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident); + } if self.current >= self.input.len() { self.current -= 1; return self.ternary(); @@ -413,20 +422,20 @@ impl Parser { let binop = self.read_token()?; let expr = self.expression()?; if binop.token_type == TokenType::Equal { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name, ident), + lhs_type, Box::new(expr.clone()) ), ident, expr )); } else if binop.token_type == TokenType::PlusEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Add, @@ -442,11 +451,11 @@ impl Parser { expr )); } else if binop.token_type == TokenType::MinusEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Sub, @@ -462,11 +471,11 @@ impl Parser { expr )); } else if binop.token_type == TokenType::StarEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Mul, @@ -482,13 +491,13 @@ impl Parser { expr )); } else if binop.token_type == TokenType::SlashEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( - Box::new(lit!(Ident, name.clone(), ident)), + Box::new(lit!(Ident, name, ident)), BinOp::Div, Box::new(expr.clone()) ), @@ -502,11 +511,11 @@ impl Parser { expr )); } else if binop.token_type == TokenType::PercentEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Mod, @@ -522,11 +531,11 @@ impl Parser { expr )); } else if binop.token_type == TokenType::AndEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::BitAnd, @@ -542,11 +551,11 @@ impl Parser { expr )); } else if binop.token_type == TokenType::CaretEqual { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::BitXor, @@ -562,11 +571,11 @@ impl Parser { expr )); } else { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Assign( - name!(name.clone(), ident), + lhs_type, Box::new( - ast_from_ast!( + ast_from_ast!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::BitOr, @@ -615,7 +624,7 @@ impl Parser { self.read_token()?; if let TokenType::LeftBrace = self.peek()?.token_type { let block = self.block()?; - return Ok(ast_from_token_ast!(ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block)); + return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block)); } else { let left_brace = self.read_token()?; return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace)); @@ -631,7 +640,7 @@ impl Parser { self.read_token()?; if let TokenType::LeftBrace = self.peek()?.token_type { let block = self.block()?; - return Ok(ast_from_token_ast!(ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block)); + return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(params, Box::new(block.clone())), left_paren, block)); } else { let left_brace = self.read_token()?; return Err(unexpected_token!(self, "Expected {{ but found {}", left_brace)); @@ -650,7 +659,7 @@ impl Parser { if let TokenType::Arrow = self.peek()?.token_type { self.read_token()?; let block = self.block()?; - return Ok(ast_from_token_ast!(ASTType::Anonymous(Vec::new(), Box::new(block.clone())), left_paren, block)); + return Ok(ast_from_token_ast!(AST, ASTType::Anonymous(Vec::new(), Box::new(block.clone())), left_paren, block)); } else { let arrow = self.read_token()?; return Err(unexpected_token!(self, "Expected => but found {}", arrow)); @@ -673,7 +682,7 @@ impl Parser { if let TokenType::Colon = self.peek()?.token_type { self.read_token()?; let false_expr = self.expression()?; - return Ok(ast_from_ast!( + return Ok(ast_from_ast!(AST, ASTType::Ternary( Box::new(condition.clone()), Box::new(true_expr), @@ -696,7 +705,7 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::OrOr { self.read_token()?; let right = self.logical_and()?; - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Or, Box::new(right.clone())), left, right @@ -711,7 +720,7 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::AndAnd { self.read_token()?; let right = self.bit_and()?; - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::And, Box::new(right.clone())), left, right @@ -726,7 +735,7 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::And { self.read_token()?; let right = self.bit_xor()?; - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary( Box::new(left.clone()), BinOp::BitAnd, @@ -745,7 +754,7 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::Caret { self.read_token()?; let right = self.bit_or()?; - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary( Box::new(left.clone()), BinOp::BitXor, @@ -764,7 +773,7 @@ impl Parser { while self.current < self.input.len() && self.peek()?.token_type == TokenType::Or { self.read_token()?; let right = self.equality()?; - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary( Box::new(left.clone()), BinOp::BitOr, @@ -787,13 +796,13 @@ impl Parser { let binop = self.read_token()?; let right = self.comparison()?; if binop.token_type == TokenType::EqualEqual { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Eq, Box::new(right.clone())), left, right ); } else { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Ne, Box::new(right.clone())), left, right @@ -816,25 +825,25 @@ impl Parser { let binop = self.read_token()?; let right = self.term()?; if binop.token_type == TokenType::Less { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Ls, Box::new(right.clone())), left, right ); } else if binop.token_type == TokenType::LessEqual { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Le, Box::new(right.clone())), left, right ); } else if binop.token_type == TokenType::Greater { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Gr, Box::new(right.clone())), left, right ); } else { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Ge, Box::new(right.clone())), left, right @@ -856,13 +865,13 @@ impl Parser { let right = self.factor()?; if binop.token_type == TokenType::Plus { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Add, Box::new(right.clone())), left, right ); } else { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Sub, Box::new(right.clone())), left, right @@ -883,19 +892,19 @@ impl Parser { let right = self.unary()?; if binop.token_type == TokenType::Star { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Mul, Box::new(right.clone())), left, right ); } else if binop.token_type == TokenType::Slash { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Div, Box::new(right.clone())), left, right ); } else { - left = ast_from_ast!( + left = ast_from_ast!(AST, ASTType::Binary(Box::new(left.clone()), BinOp::Mod, Box::new(right.clone())), left, right @@ -909,13 +918,13 @@ impl Parser { let token = self.read_token()?; let unary = self.unary()?; if token.token_type == TokenType::Bang { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Unary(UnOp::Not, Box::new(unary.clone())), token, unary )); } else { - return Ok(ast_from_token_ast!( + return Ok(ast_from_token_ast!(AST, ASTType::Unary(UnOp::Neg, Box::new(unary.clone())), token, unary @@ -933,7 +942,7 @@ impl Parser { let expr = self.expression()?; let right_brace = self.read_token()?; if let TokenType::RightSquare = right_brace.token_type { - primary = ast_from_ast_token!( + primary = ast_from_ast_token!(AST, ASTType::Subscript(Box::new(primary.clone()), Box::new(expr)), primary, right_brace @@ -992,7 +1001,7 @@ impl Parser { } } let right_square = self.read_token()?; - Ok(ast_from_token!( + Ok(ast_from_token!(AST, ASTType::Lit(Lit::Array(expressions)), left_square, right_square @@ -1009,7 +1018,7 @@ impl Parser { if self.current < self.input.len() { if let TokenType::LeftParen = self.peek()?.token_type { let call = self.call(child)?; - expr = ast_from_ast!( + expr = ast_from_ast!(AST, ASTType::Member(Box::new(expr.clone()), Box::new(call.clone())), expr, call @@ -1020,7 +1029,7 @@ impl Parser { continue; } } - expr = ast_from_ast_token!( + expr = ast_from_ast_token!(AST, ASTType::Member( Box::new(expr.clone()), Box::new(lit!(Ident, child_str, child)) @@ -1051,7 +1060,7 @@ impl Parser { } let right_paren = self.read_token()?; if let TokenType::Ident(name) = ident.token_type { - return Ok(ast_from_token!( + return Ok(ast_from_token!(AST, ASTType::Call(Box::new(lit!(Ident, name, ident)), expressions), ident, right_paren @@ -1063,10 +1072,10 @@ impl Parser { if let TokenType::Ident(name) = ident.token_type { let oper = self.read_token()?; if oper.token_type == TokenType::PlusPlus { - return Ok(ast_from_token!( + return Ok(ast_from_token!(AST, ASTType::Assign( - name!(name.clone(), ident), - Box::new(ast_from_token!( + ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident), + Box::new(ast_from_token!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Add, @@ -1080,10 +1089,10 @@ impl Parser { oper )); } else { - return Ok(ast_from_token!( + return Ok(ast_from_token!(AST, ASTType::Assign( - name!(name.clone(), ident), - Box::new(ast_from_token!( + ast_from_token!(LhsAssign, LhsAssignType::Ident(name.clone()), ident, ident), + Box::new(ast_from_token!(AST, ASTType::Binary( Box::new(lit!(Ident, name, ident)), BinOp::Sub, @@ -1116,8 +1125,8 @@ impl Parser { )); } self.read_token()?; - return Ok(ast_from_token!( - expr.ast_type, + return Ok(ast_from_token!(AST, + expr.kind, left_paren, right_paren )); diff --git a/kabel/tmp.kab b/kabel/tmp.kab index b1c15739a79a219627756fba7639500a71d5b212..f2db6779ae5fbd2bd4234bd60c4fa55e05eda1ee 100644 --- a/kabel/tmp.kab +++ b/kabel/tmp.kab @@ -1,4 +1,2 @@ -function apply(fn, value) { - return fn(value); -} -print apply((value) => { return value + 1; }, 1); +var i = [3, 2]; +i[0] = 3;