Literal patterns

This commit is contained in:
Greg Shuflin 2021-10-25 23:01:32 -07:00
parent 284d7ce383
commit 899a4df55e
4 changed files with 58 additions and 7 deletions

View File

@ -289,8 +289,35 @@ impl<'a> Reducer<'a> {
impl ast::Pattern {
fn reduce(&self, symbol_table: &SymbolTable) -> Result<Pattern, PatternError> {
Ok(match self {
ast::Pattern::Ignored => {
unimplemented!()
},
ast::Pattern::TuplePattern(/*Vec<Pattern>*/..) => {
unimplemented!()
Ok(Pattern::Ignored)
},
ast::Pattern::Literal(lit) => Pattern::Literal(match lit {
ast::PatternLiteral::NumPattern { neg, num } => match (neg, num) {
(false, ast::ExpressionKind::NatLiteral(n)) => Literal::Nat(*n),
(false, ast::ExpressionKind::FloatLiteral(f)) => Literal::Float(*f),
(true, ast::ExpressionKind::NatLiteral(n)) => Literal::Int(-(*n as i64)),
(true, ast::ExpressionKind::FloatLiteral(f)) => Literal::Float(-f),
(_, e) => return Err(format!("Internal error, unexpected pattern literal: {:?}", e).into())
},
ast::PatternLiteral::StringPattern(s) => Literal::StringLit(s.clone()),
ast::PatternLiteral::BoolPattern(b) => Literal::Bool(*b),
}),
ast::Pattern::TupleStruct(_name, _subpatterns) => {
unimplemented!()
},
ast::Pattern::Record(name, /*Vec<(Rc<String>, Pattern)>*/ _) => {
unimplemented!()
},
ast::Pattern::VarOrName(_name) => {
unimplemented!()
},
})
}
}

View File

@ -108,7 +108,7 @@ pub enum Lookup {
Param(u8),
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum Literal {
Nat(u64),
Int(i64),
@ -149,3 +149,9 @@ impl From<&str> for PatternError {
Self { msg: s.to_string() }
}
}
impl From<String> for PatternError {
fn from(msg: String) -> Self {
Self { msg }
}
}

View File

@ -277,12 +277,17 @@ impl<'a> State<'a> {
fn case_match_expression(&mut self, cond: Expression, alternatives: Vec<Alternative>) -> EvalResult<Primitive> {
fn matches(cond: &Expression, matcher: &Pattern) -> bool {
fn matches(scrut: &Primitive, pat: &Pattern) -> bool {
match pat {
Pattern::Ignored => true,
Pattern::Literal(pat_literal) => if let Primitive::Literal(scrut_literal) = scrut {
pat_literal == scrut_literal
} else {
false
},
}
}
let cond = self.expression(cond)?;
for alt in alternatives.into_iter() {
if matches(&cond, &alt.pattern) {

View File

@ -85,6 +85,19 @@ fn basic_if_statement() {
eval_assert(source, "69");
}
#[test]
fn basic_patterns() {
let source =r#"
let x = 10
let a = if x is 10 then { 255 } else { 256 }
let b = if 23 is 99 then { 255 } else { 256 }
let c = if true is false then { 9 } else { 10 }
let d = if "xxx" is "yyy" then { 20 } else { 30 }
(a, b, c, d)
"#;
eval_assert(source, "(255, 256, 10, 30)");
}
#[test]
fn if_is_patterns() {
let source = r#"