diff --git a/kalk/src/analysis.rs b/kalk/src/analysis.rs index 65d4f50..c3a87e0 100644 --- a/kalk/src/analysis.rs +++ b/kalk/src/analysis.rs @@ -234,7 +234,11 @@ fn analyse_expr(context: &mut Context, expr: Expr) -> Result { analysed_values.push(analyse_expr(context, value)?); } - Expr::Vector(analysed_values) + if analysed_values.len() == 1 && matches!(analysed_values[0], Expr::Comprehension(_, _, _)) { + analysed_values.pop().unwrap() + } else { + Expr::Vector(analysed_values) + } } Expr::Matrix(rows) => { let mut analysed_rows = Vec::new(); @@ -259,6 +263,7 @@ fn analyse_expr(context: &mut Context, expr: Expr) -> Result { } Expr::Comprehension(left, right, vars) => Expr::Comprehension(left, right, vars), Expr::Equation(left, right, identifier) => Expr::Equation(left, right, identifier), + Expr::Preevaluated(_) => expr, }) } diff --git a/kalk/src/ast.rs b/kalk/src/ast.rs index d0fe2a3..fda6351 100644 --- a/kalk/src/ast.rs +++ b/kalk/src/ast.rs @@ -1,4 +1,4 @@ -use crate::{kalk_value::KalkFloat, lexer::TokenKind}; +use crate::{kalk_value::{KalkFloat, KalkValue}, lexer::TokenKind}; /// A tree structure of a statement. #[derive(Debug, Clone, PartialEq)] @@ -27,6 +27,7 @@ pub enum Expr { Indexer(Box, Vec), Comprehension(Box, Vec, Vec), Equation(Box, Box, Identifier), + Preevaluated(KalkValue), } #[derive(Debug, Clone, PartialEq)] diff --git a/kalk/src/interpreter.rs b/kalk/src/interpreter.rs index cf3ae71..e85af82 100644 --- a/kalk/src/interpreter.rs +++ b/kalk/src/interpreter.rs @@ -166,6 +166,7 @@ pub(crate) fn eval_expr( context, left, conditions, vars, )?)), Expr::Equation(left, right, identifier) => eval_equation(context, left, right, identifier), + Expr::Preevaluated(value) => Ok(value.clone()), } } @@ -548,7 +549,7 @@ pub(crate) fn eval_fn_call_expr( }; let var_decl = Stmt::VarDecl( argument_identifier, - Box::new(crate::ast::build_literal_ast(&eval_expr( + Box::new(Expr::Preevaluated(eval_expr( context, &expressions[i], None, diff --git a/kalk/src/inverter.rs b/kalk/src/inverter.rs index 3b78587..1907de9 100644 --- a/kalk/src/inverter.rs +++ b/kalk/src/inverter.rs @@ -94,6 +94,7 @@ fn invert( Err(KalkError::UnableToInvert(String::from("Comprehension"))) } Expr::Equation(_, _, _) => Err(KalkError::UnableToInvert(String::from("Equation"))), + Expr::Preevaluated(_) => Err(KalkError::UnableToInvert(String::from("Equation"))), } } @@ -402,6 +403,7 @@ pub fn contains_var(symbol_table: &SymbolTable, expr: &Expr, var_name: &str) -> Expr::Indexer(_, _) => false, Expr::Comprehension(_, _, _) => false, Expr::Equation(_, _, _) => false, + Expr::Preevaluated(_) => false, } } diff --git a/kalk/src/parser.rs b/kalk/src/parser.rs index e9f7369..6770e0e 100644 --- a/kalk/src/parser.rs +++ b/kalk/src/parser.rs @@ -564,6 +564,11 @@ fn parse_group_fn(context: &mut Context) -> Result { fn parse_vector(context: &mut Context) -> Result { let kind = advance(context).kind; + if match_token(context, TokenKind::ClosedBracket) { + advance(context); + + return Ok(Expr::Vector(vec![])); + } if kind == TokenKind::OpenBracket { skip_newlines(context); @@ -617,7 +622,7 @@ fn parse_vector(context: &mut Context) -> Result { if rows.len() == 1 { let mut values = rows.pop().unwrap(); - if values.len() == 1 { + if values.len() == 1 && kind == TokenKind::OpenParenthesis { Ok(Expr::Group(Box::new(values.pop().unwrap()))) } else { Ok(Expr::Vector(values)) diff --git a/kalk/src/prelude/mod.rs b/kalk/src/prelude/mod.rs index b925980..d473349 100644 --- a/kalk/src/prelude/mod.rs +++ b/kalk/src/prelude/mod.rs @@ -90,6 +90,7 @@ lazy_static! { }; pub static ref BINARY_FUNCS: HashMap<&'static str, (BinaryFuncInfo, &'static str)> = { let mut m = HashMap::new(); + m.insert("append", (BinaryFuncInfo(append, Other), "")); m.insert("bitand", (BinaryFuncInfo(bitand, Other), "")); m.insert("bitor", (BinaryFuncInfo(bitor, Other), "")); m.insert("bitxor", (BinaryFuncInfo(bitxor, Other), "")); @@ -700,6 +701,17 @@ pub mod funcs { )) } + pub fn append(x: KalkValue, y: KalkValue) -> Result { + if let KalkValue::Vector(items) = x { + let mut new_items = items.clone(); + new_items.push(y); + + Ok(KalkValue::Vector(new_items)) + } else { + Err(KalkError::Expected(String::from("Vector"))) + } + } + // ⎛ ⎞ // ⎜ ⎜a⎜ ⎟ // lcm(a, b) = ⎜ ───────── ⎟ × ⎜b⎜