diff --git a/src/expression.rs b/src/expression.rs index dd0b7a7..a5645b6 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use crate::{env::Env, function::FunctionMap, value::Value}; +use crate::{env::Env, function::FunctionMap, statement::Statement, value::Value}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum BinaryOperation { @@ -38,13 +38,17 @@ impl FromStr for BinaryOperation { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq)] pub enum Expression { Constant(Value), Variable(String), Call(String, Vec), CallMethod(Box, String, Vec), Binary(Box, BinaryOperation, Box), + If( + Vec<(Expression, Statement, Expression)>, + (Box, Box), + ), } impl Expression { @@ -89,6 +93,19 @@ impl Expression { BinaryOperation::NotEqual => (lhs != rhs).into(), } } + Expression::If(ifs, (else_statement, else_expr)) => { + for (expr, statement, ret) in ifs { + let e = Env::new_with_parent(e); + if expr.eval(&e, f).is_truthy() { + statement.eval(&e, f); + return ret.eval(&e, f); + } + } + + let e = Env::new_with_parent(e); + else_statement.eval(&e, f); + else_expr.eval(&e, f) + } } } } diff --git a/src/grammar.pest b/src/grammar.pest index cf3d42a..15457c4 100644 --- a/src/grammar.pest +++ b/src/grammar.pest @@ -38,7 +38,7 @@ value = { (const_value | call | identifier | parens) ~ method_call } method_call = { (("." ~ identifier ~ call_params) ~ method_call)? } -expression = { equality } +expression = { if_block_expr | equality } equality = { inequality ~ ((equals | not_equals) ~ inequality)? } @@ -67,6 +67,10 @@ while_block = { "while" ~ expression ~ block } if_block = { "if" ~ expression ~ block ~ ("else if" ~ expression ~ block)* ~ ("else" ~ block)? } +if_block_expr = { "if" ~ expression ~ if_block_expr_block ~ ("else if" ~ expression ~ if_block_expr_block)* ~ "else" ~ if_block_expr_block } + +if_block_expr_block = { "{" ~ statement* ~ expression ~ "}" } + def_params = { "(" ~ (identifier ~ ","?)* ~ ")" } def = { "def" ~ identifier ~ def_params ~ func_block } diff --git a/src/main.rs b/src/main.rs index 57e1912..09fe26c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,11 +50,11 @@ impl CustomValue for Foo { } } -fn functions(&self) -> Option { - let mut map = FunctionMap::new(); - map.insert_native("edit_foo", Foo::edit); - Some(map) -} + fn functions(&self) -> Option { + let mut map = FunctionMap::new(); + map.insert_native("edit_foo", Foo::edit); + Some(map) + } } fn main() { diff --git a/src/pest_parser.rs b/src/pest_parser.rs index 43958fb..bd28a72 100644 --- a/src/pest_parser.rs +++ b/src/pest_parser.rs @@ -189,6 +189,36 @@ fn parse_expression(pair: Pair) -> Expression { v } } + Rule::if_block_expr => { + let mut inner = pair.into_inner(); + let mut the_list = vec![]; + let mut the_else = None; + while let Some(expr) = inner.next() { + if let Some(if_block) = inner.next() { + let expr = parse_expression(expr); + let if_block_body = if_block.into_inner(); + let (a, b): (Vec<_>, Vec<_>) = + if_block_body.partition(|a| a.as_rule() == Rule::statement); + let (statements, _): (_, FuncHolder) = + a.into_iter().map(parse_statement).unzip(); + let z = b.into_iter().map(parse_expression).collect::>(); + the_list.push((expr, Statement::Body(statements), z[0].clone())); + } else { + let if_block_body = expr.into_inner(); + let (a, b): (Vec<_>, Vec<_>) = + if_block_body.partition(|a| a.as_rule() == Rule::statement); + let (statements, _): (_, FuncHolder) = + a.into_iter().map(parse_statement).unzip(); + let z = b.into_iter().map(parse_expression).collect::>(); + the_else = Some(( + Box::new(Statement::Body(statements)), + Box::new(z[0].clone()), + )); + } + } + + Expression::If(the_list, the_else.unwrap()) + } _ => unreachable!(), } } diff --git a/test.foo b/test.foo index 61efb6d..2379aca 100644 --- a/test.foo +++ b/test.foo @@ -25,3 +25,11 @@ print(x); print(add_one(41)); +let x = 0; +if x == 0 { + x = x + 10; +} +print(x); + +let x = 5; +print(if x < 10 { 20 } else { 30 }); \ No newline at end of file