Add if expressions
This commit is contained in:
parent
506b406146
commit
fd3ec9e12d
|
@ -1,6 +1,6 @@
|
||||||
use std::str::FromStr;
|
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)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum BinaryOperation {
|
pub enum BinaryOperation {
|
||||||
|
@ -38,13 +38,17 @@ impl FromStr for BinaryOperation {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Constant(Value),
|
Constant(Value),
|
||||||
Variable(String),
|
Variable(String),
|
||||||
Call(String, Vec<Expression>),
|
Call(String, Vec<Expression>),
|
||||||
CallMethod(Box<Expression>, String, Vec<Expression>),
|
CallMethod(Box<Expression>, String, Vec<Expression>),
|
||||||
Binary(Box<Expression>, BinaryOperation, Box<Expression>),
|
Binary(Box<Expression>, BinaryOperation, Box<Expression>),
|
||||||
|
If(
|
||||||
|
Vec<(Expression, Statement, Expression)>,
|
||||||
|
(Box<Statement>, Box<Expression>),
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
|
@ -89,6 +93,19 @@ impl Expression {
|
||||||
BinaryOperation::NotEqual => (lhs != rhs).into(),
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ value = { (const_value | call | identifier | parens) ~ method_call }
|
||||||
|
|
||||||
method_call = { (("." ~ identifier ~ call_params) ~ method_call)? }
|
method_call = { (("." ~ identifier ~ call_params) ~ method_call)? }
|
||||||
|
|
||||||
expression = { equality }
|
expression = { if_block_expr | equality }
|
||||||
|
|
||||||
equality = { inequality ~ ((equals | not_equals) ~ inequality)? }
|
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 = { "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_params = { "(" ~ (identifier ~ ","?)* ~ ")" }
|
||||||
|
|
||||||
def = { "def" ~ identifier ~ def_params ~ func_block }
|
def = { "def" ~ identifier ~ def_params ~ func_block }
|
||||||
|
|
10
src/main.rs
10
src/main.rs
|
@ -50,11 +50,11 @@ impl CustomValue for Foo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn functions(&self) -> Option<FunctionMap> {
|
fn functions(&self) -> Option<FunctionMap> {
|
||||||
let mut map = FunctionMap::new();
|
let mut map = FunctionMap::new();
|
||||||
map.insert_native("edit_foo", Foo::edit);
|
map.insert_native("edit_foo", Foo::edit);
|
||||||
Some(map)
|
Some(map)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
|
|
@ -189,6 +189,36 @@ fn parse_expression(pair: Pair<Rule>) -> Expression {
|
||||||
v
|
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!(),
|
_ => unreachable!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue