Basic conditionals working

This commit is contained in:
Greg Shuflin 2021-10-25 20:26:53 -07:00
parent 856e74cb5e
commit 77cdfc229f
4 changed files with 51 additions and 7 deletions

View File

@ -108,7 +108,7 @@ impl<'a> Reducer<'a> {
let symbol = self.symbol_table.lookup_symbol(item_id).unwrap();
let def_id = symbol.def_id().unwrap();
let function_def = FunctionDefinition {
body: self.function(statements)
body: self.function_internal_block(statements)
};
self.functions.insert(def_id, function_def);
}
@ -136,7 +136,7 @@ impl<'a> Reducer<'a> {
Lambda { params, body, .. } => {
Expression::Callable(Callable::Lambda {
arity: params.len() as u8,
body: self.function(body),
body: self.function_internal_block(body),
})
},
NamedStruct { .. } => Expression::ReductionError("NamedStruct not implemented".to_string()), //self.reduce_named_struct(name, fields),
@ -147,8 +147,29 @@ impl<'a> Reducer<'a> {
}
}
fn reduce_if_expression(&mut self, _discriminator: Option<&ast::Expression>, _body: &ast::IfExpressionBody) -> Expression {
Expression::ReductionError("if expr".to_string())
fn reduce_if_expression(&mut self, discriminator: Option<&ast::Expression>, body: &ast::IfExpressionBody) -> Expression {
let cond = Box::new(match discriminator {
Some(expr) => self.expression(expr),
None => return Expression::ReductionError("blank cond if-expr not supported".to_string()),
});
match body {
ast::IfExpressionBody::SimpleConditional {
then_case,
else_case,
} => {
let then_clause = self.function_internal_block(then_case);
let else_clause = match else_case.as_ref() {
None => vec![],
Some(stmts) => self.function_internal_block(stmts),
};
Expression::Conditional {
cond,
then_clause,
else_clause,
}
},
_ => Expression::ReductionError("if expr".to_string())
}
}
fn invocation_argument(&mut self, invoc: &ast::InvocationArgument) -> Expression {
@ -160,7 +181,7 @@ impl<'a> Reducer<'a> {
}
}
fn function(&mut self, statements: &ast::Block) -> Vec<Statement> {
fn function_internal_block(&mut self, statements: &ast::Block) -> Vec<Statement> {
statements.iter().filter_map(|stmt| self.function_internal_statement(stmt)).collect()
}

View File

@ -61,6 +61,11 @@ pub enum Expression {
f: Box<Expression>,
args: Vec<Expression>
},
Conditional {
cond: Box<Expression>,
then_clause: Vec<Statement>,
else_clause: Vec<Statement>,
},
ReductionError(String),
}

View File

@ -262,6 +262,14 @@ impl<'a> State<'a> {
type_id, tag, items: vec![]
},
Expression::Callable(func) => Primitive::Callable(func),
Expression::Conditional { box cond, then_clause, else_clause } => {
let cond = self.expression(cond)?;
match cond {
Primitive::Literal(Literal::Bool(true)) => self.block(then_clause)?,
Primitive::Literal(Literal::Bool(false)) => self.block(else_clause)?,
v => return Err(format!("Non-boolean value {:?} in if-statement", v).into())
}
},
Expression::ReductionError(e) => return Err(e.into()),
})
}

View File

@ -75,9 +75,19 @@ let b = Option::Some(10)
eval_assert(source, "(Some(10), None)");
}
/*
#[test]
fn basic_if_statement() {
let source = r#"
let a = 10
let b = 10
if a == b then { 69 } else { 420 }
"#;
eval_assert(source, "69");
}
#[test]
fn if_is_patterns() {
/*
let source = r#"
type Option<T> = Some(T) | None
let x = Option::Some(9); if x is Option::Some(q) then { q } else { 0 }"#;
@ -88,8 +98,8 @@ let x = Option::Some(9); if x is Option::Some(q) then { q } else { 0 }"#;
type Option<T> = Some(T) | None
let x = Option::None; if x is Option::Some(q) then { q } else { 0 }"#;
eval_assert(source, "0");
}
*/
}
#[test]