~starkingdoms/starkingdoms

70e59fea39914ab39ff530298efd77532e899e7a — ghostly_zsh 1 year, 3 months ago a5b0bc0
subscript assignment parsing
M kabel/grammar.ebnf => kabel/grammar.ebnf +3 -1
@@ 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 ;

M kabel/opcodes.txt => kabel/opcodes.txt +0 -4
@@ 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


M kabel/src/ast.rs => kabel/src/ast.rs +14 -10
@@ 1,14 1,9 @@
use crate::extension::Extension;

#[derive(Debug, Clone)]
pub struct AST {
    pub ast_type: ASTType,
    pub extensions: Vec<Extension>,
    pub start_line: usize,
    pub end_line: usize,
    pub start_column: usize,
    pub end_column: usize,
}
crate::ast!(AST {
    kind: ASTType,
    extensions: Vec<Extension>
});

#[derive(Debug, Clone)]
pub enum ASTType {


@@ 35,7 30,7 @@ pub enum ASTType {
    Print(Box<AST>),

    // expressions
    Assign(Name, Box<AST>),
    Assign(LhsAssign, Box<AST>),
    Anonymous(Vec<Name>, Box<AST>),
    Ternary(Box<AST>, Box<AST>, Box<AST>),
    Subscript(Box<AST>, Box<AST>),


@@ 90,3 85,12 @@ pub enum UnOp {
    Not,
    Neg,
}

crate::ast!(LhsAssign { kind: LhsAssignType, extensions: Vec<Extension> });

#[derive(Debug, Clone)]
pub enum LhsAssignType {
    Ident(String),
    Subscript(Box<AST>, Box<AST>),
}


M kabel/src/codegen.rs => kabel/src/codegen.rs +10 -10
@@ 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

M kabel/src/debug.rs => kabel/src/debug.rs +16 -4
@@ 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<Token>) -> 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);

M kabel/src/macros.rs => kabel/src/macros.rs +31 -16
@@ 21,10 21,25 @@ 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]),
        )
    };

M kabel/src/name_resolution.rs => kabel/src/name_resolution.rs +54 -38
@@ 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<String>,


@@ 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,

M kabel/src/parser.rs => kabel/src/parser.rs +89 -80
@@ 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<AST, KabelError> {
        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<AST, KabelError> {
        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
            ));

M kabel/tmp.kab => kabel/tmp.kab +2 -4
@@ 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;