Add if expressions

main
Julius 2022-07-04 21:49:08 +02:00
parent 506b406146
commit fd3ec9e12d
Signed by: j00lz
GPG Key ID: AF241B0AA237BBA2
5 changed files with 67 additions and 8 deletions

View File

@ -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<Expression>),
CallMethod(Box<Expression>, String, Vec<Expression>),
Binary(Box<Expression>, BinaryOperation, Box<Expression>),
If(
Vec<(Expression, Statement, Expression)>,
(Box<Statement>, Box<Expression>),
),
}
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)
}
}
}
}

View File

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

View File

@ -50,11 +50,11 @@ impl CustomValue for Foo {
}
}
fn functions(&self) -> Option<FunctionMap> {
let mut map = FunctionMap::new();
map.insert_native("edit_foo", Foo::edit);
Some(map)
}
fn functions(&self) -> Option<FunctionMap> {
let mut map = FunctionMap::new();
map.insert_native("edit_foo", Foo::edit);
Some(map)
}
}
fn main() {

View File

@ -189,6 +189,36 @@ fn parse_expression(pair: Pair<Rule>) -> 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::<Vec<_>>();
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::<Vec<_>>();
the_else = Some((
Box::new(Statement::Body(statements)),
Box::new(z[0].clone()),
));
}
}
Expression::If(the_list, the_else.unwrap())
}
_ => unreachable!(),
}
}

View File

@ -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 });