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;