Bunch of messing-around with case matching
This commit is contained in:
parent
6162d05b60
commit
284d7ce383
@ -3,7 +3,7 @@ use std::fmt::Write;
|
|||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
use crate::reduced_ast::{BoundVars, ReducedAST, Stmt, Expr, Lit, Func, Alternative, Subpattern};
|
use crate::reduced_ast::{BoundVars, ReducedAST, Stmt, Expr, Lit, Func, Alternative, Pattern};
|
||||||
use crate::builtin::Builtin;
|
use crate::builtin::Builtin;
|
||||||
|
|
||||||
mod test;
|
mod test;
|
||||||
|
@ -177,15 +177,14 @@ impl<'a> Reducer<'a> {
|
|||||||
} => {
|
} => {
|
||||||
let alternatives = vec![
|
let alternatives = vec![
|
||||||
Alternative {
|
Alternative {
|
||||||
matchable: pattern.to_subpattern(self.symbol_table),
|
pattern: match pattern.reduce(self.symbol_table) {
|
||||||
|
Ok(p) => p,
|
||||||
|
Err(e) => return Expression::ReductionError(format!("Bad pattern: {:?}", e)),
|
||||||
|
},
|
||||||
item: self.function_internal_block(then_case),
|
item: self.function_internal_block(then_case),
|
||||||
},
|
},
|
||||||
Alternative {
|
Alternative {
|
||||||
matchable: Subpattern {
|
pattern: Pattern::Ignored,
|
||||||
tag: None,
|
|
||||||
subpatterns: vec![],
|
|
||||||
guard: None,
|
|
||||||
},
|
|
||||||
item: match else_case.as_ref() {
|
item: match else_case.as_ref() {
|
||||||
Some(else_case) => self.function_internal_block(else_case),
|
Some(else_case) => self.function_internal_block(else_case),
|
||||||
None => vec![],
|
None => vec![],
|
||||||
@ -289,33 +288,44 @@ impl<'a> Reducer<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl ast::Pattern {
|
impl ast::Pattern {
|
||||||
|
fn reduce(&self, symbol_table: &SymbolTable) -> Result<Pattern, PatternError> {
|
||||||
|
|
||||||
|
Ok(Pattern::Ignored)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl ast::Pattern {
|
||||||
fn to_subpattern(&self, symbol_table: &SymbolTable) -> Subpattern {
|
fn to_subpattern(&self, symbol_table: &SymbolTable) -> Subpattern {
|
||||||
Subpattern {
|
use ast::Pattern::*;
|
||||||
|
use Expression::ReductionError;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Ignored => Subpattern {
|
||||||
tag: None,
|
tag: None,
|
||||||
subpatterns: vec![],
|
subpatterns: vec![],
|
||||||
guard: None,
|
guard: None,
|
||||||
}
|
},
|
||||||
|
Literal(lit) => lit.to_subpattern(symbol_table),
|
||||||
/*
|
/*
|
||||||
use self::Pattern::*;
|
|
||||||
match self {
|
|
||||||
TupleStruct(QualifiedName { components, id }, inner_patterns) => {
|
TupleStruct(QualifiedName { components, id }, inner_patterns) => {
|
||||||
match symbol_table.lookup_symbol(id) {
|
match symbol_table.lookup_symbol(id) {
|
||||||
Some(symbol) => handle_symbol(Some(symbol), inner_patterns, symbol_table),
|
Some(symbol) => handle_symbol(Some(symbol), inner_patterns, symbol_table),
|
||||||
None => panic!("Symbol {:?} not found", components),
|
None => panic!("Symbol {:?} not found", components),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
_ => Subpattern {
|
||||||
|
tag: None,
|
||||||
|
subpatterns: vec![],
|
||||||
|
guard: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
TuplePattern(inner_patterns) => handle_symbol(None, inner_patterns, symbol_table),
|
TuplePattern(inner_patterns) => handle_symbol(None, inner_patterns, symbol_table),
|
||||||
Record(_name, _pairs) => {
|
Record(_name, _pairs) => {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
Ignored => Subpattern {
|
|
||||||
tag: None,
|
|
||||||
subpatterns: vec![],
|
|
||||||
guard: None,
|
|
||||||
bound_vars: vec![],
|
|
||||||
},
|
|
||||||
Literal(lit) => lit.to_subpattern(symbol_table),
|
|
||||||
VarOrName(QualifiedName { components, id }) => {
|
VarOrName(QualifiedName { components, id }) => {
|
||||||
// if symbol is Some, treat this as a symbol pattern. If it's None, treat it
|
// if symbol is Some, treat this as a symbol pattern. If it's None, treat it
|
||||||
// as a variable.
|
// as a variable.
|
||||||
@ -337,7 +347,139 @@ impl ast::Pattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
fn handle_symbol(
|
||||||
|
symbol: Option<&Symbol>,
|
||||||
|
inner_patterns: &[Pattern],
|
||||||
|
symbol_table: &SymbolTable,
|
||||||
|
) -> Subpattern {
|
||||||
|
use ast::Pattern::*;
|
||||||
|
|
||||||
|
let tag = symbol.map(|symbol| match symbol.spec {
|
||||||
|
SymbolSpec::DataConstructor { index, .. } => index,
|
||||||
|
_ => {
|
||||||
|
panic!("Symbol is not a data constructor - this should've been caught in type-checking")
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let bound_vars = inner_patterns
|
||||||
|
.iter()
|
||||||
|
.map(|p| match p {
|
||||||
|
VarOrName(qualified_name) => {
|
||||||
|
let symbol_exists = symbol_table.lookup_symbol(&qualified_name.id).is_some();
|
||||||
|
if symbol_exists {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let QualifiedName { components, .. } = qualified_name;
|
||||||
|
if components.len() == 1 {
|
||||||
|
Some(components[0].clone())
|
||||||
|
} else {
|
||||||
|
panic!("Bad variable name in pattern");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let subpatterns = inner_patterns
|
||||||
|
.iter()
|
||||||
|
.map(|p| match p {
|
||||||
|
Ignored => None,
|
||||||
|
VarOrName(_) => None,
|
||||||
|
Literal(other) => Some(other.to_subpattern(symbol_table)),
|
||||||
|
tp @ TuplePattern(_) => Some(tp.to_subpattern(symbol_table)),
|
||||||
|
ts @ TupleStruct(_, _) => Some(ts.to_subpattern(symbol_table)),
|
||||||
|
Record(..) => unimplemented!(),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let guard = None;
|
||||||
|
/*
|
||||||
|
let guard_equality_exprs: Vec<Expr> = subpatterns.iter().map(|p| match p {
|
||||||
|
Literal(lit) => match lit {
|
||||||
|
_ => unimplemented!()
|
||||||
|
},
|
||||||
|
_ => unimplemented!()
|
||||||
|
}).collect();
|
||||||
|
*/
|
||||||
|
|
||||||
|
Subpattern {
|
||||||
|
tag,
|
||||||
|
subpatterns,
|
||||||
|
guard,
|
||||||
|
bound_vars,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
impl ast::PatternLiteral {
|
||||||
|
fn to_subpattern(&self, _symbol_table: &SymbolTable) -> Subpattern {
|
||||||
|
use ast::PatternLiteral::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
NumPattern { neg, num } => {
|
||||||
|
let comparison = Expression::Literal(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),
|
||||||
|
_ => panic!("This should never happen"),
|
||||||
|
});
|
||||||
|
unimplemented!()
|
||||||
|
/*
|
||||||
|
let guard = Some(Expr::Call {
|
||||||
|
f: Box::new(Expr::Func(Func::BuiltIn(Builtin::Equality))),
|
||||||
|
args: vec![comparison, Expr::ConditionalTargetSigilValue],
|
||||||
|
});
|
||||||
|
Subpattern {
|
||||||
|
tag: None,
|
||||||
|
subpatterns: vec![],
|
||||||
|
guard,
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
_ => unimplemented!()
|
||||||
|
/*
|
||||||
|
StringPattern(s) => {
|
||||||
|
let guard = Some(Expr::Call {
|
||||||
|
f: Box::new(Expr::Func(Func::BuiltIn(Builtin::Equality))),
|
||||||
|
args: vec![
|
||||||
|
Expr::Lit(Lit::StringLit(s.clone())),
|
||||||
|
Expr::ConditionalTargetSigilValue,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
Subpattern {
|
||||||
|
tag: None,
|
||||||
|
subpatterns: vec![],
|
||||||
|
guard,
|
||||||
|
bound_vars: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BoolPattern(b) => {
|
||||||
|
let guard = Some(if *b {
|
||||||
|
Expr::ConditionalTargetSigilValue
|
||||||
|
} else {
|
||||||
|
Expr::Call {
|
||||||
|
f: Box::new(Expr::Func(Func::BuiltIn(Builtin::BooleanNot))),
|
||||||
|
args: vec![Expr::ConditionalTargetSigilValue],
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Subpattern {
|
||||||
|
tag: None,
|
||||||
|
subpatterns: vec![],
|
||||||
|
guard,
|
||||||
|
bound_vars: vec![],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::convert::From;
|
||||||
|
|
||||||
use crate::builtin::Builtin;
|
use crate::builtin::Builtin;
|
||||||
use crate::symbol_table::{DefId, SymbolTable};
|
use crate::symbol_table::{DefId, SymbolTable};
|
||||||
@ -118,10 +119,17 @@ pub enum Literal {
|
|||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Alternative {
|
pub struct Alternative {
|
||||||
pub matchable: Subpattern,
|
pub pattern: Pattern,
|
||||||
pub item: Vec<Statement>,
|
pub item: Vec<Statement>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Pattern {
|
||||||
|
Literal(Literal),
|
||||||
|
Ignored,
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Subpattern {
|
pub struct Subpattern {
|
||||||
pub tag: Option<usize>,
|
pub tag: Option<usize>,
|
||||||
@ -129,3 +137,15 @@ pub struct Subpattern {
|
|||||||
//pub bound_vars: BoundVars,
|
//pub bound_vars: BoundVars,
|
||||||
pub guard: Option<Expression>,
|
pub guard: Option<Expression>,
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PatternError {
|
||||||
|
msg: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for PatternError {
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
Self { msg: s.to_string() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::reduced_ir::{ReducedIR, Expression, Lookup, Callable, FunctionDefinition, Statement, Literal};
|
use crate::reduced_ir::{ReducedIR, Expression, Lookup, Callable, FunctionDefinition, Statement, Literal, Alternative, Pattern};
|
||||||
use crate::symbol_table::{DefId};
|
use crate::symbol_table::{DefId};
|
||||||
use crate::util::ScopeStack;
|
use crate::util::ScopeStack;
|
||||||
use crate::builtin::Builtin;
|
use crate::builtin::Builtin;
|
||||||
@ -270,13 +270,29 @@ impl<'a> State<'a> {
|
|||||||
v => return Err(format!("Non-boolean value {:?} in if-statement", v).into())
|
v => return Err(format!("Non-boolean value {:?} in if-statement", v).into())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Expression::CaseMatch { cond, alternatives } => {
|
Expression::CaseMatch { box cond, alternatives } => self.case_match_expression(cond, alternatives)?,
|
||||||
panic!()
|
|
||||||
},
|
|
||||||
Expression::ReductionError(e) => return Err(e.into()),
|
Expression::ReductionError(e) => return Err(e.into()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn case_match_expression(&mut self, cond: Expression, alternatives: Vec<Alternative>) -> EvalResult<Primitive> {
|
||||||
|
|
||||||
|
fn matches(cond: &Expression, matcher: &Pattern) -> bool {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
for alt in alternatives.into_iter() {
|
||||||
|
if matches(&cond, &alt.pattern) {
|
||||||
|
// Set up local vars
|
||||||
|
return self.block(alt.item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err("No valid match in match expression".into())
|
||||||
|
}
|
||||||
|
|
||||||
fn call_expression(&mut self, f: Expression, args: Vec<Expression>) -> EvalResult<Primitive> {
|
fn call_expression(&mut self, f: Expression, args: Vec<Expression>) -> EvalResult<Primitive> {
|
||||||
let func = match self.expression(f)? {
|
let func = match self.expression(f)? {
|
||||||
Primitive::Callable(func) => func,
|
Primitive::Callable(func) => func,
|
||||||
|
@ -87,13 +87,13 @@ fn basic_if_statement() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn if_is_patterns() {
|
fn if_is_patterns() {
|
||||||
/*
|
|
||||||
let source = r#"
|
let source = r#"
|
||||||
type Option<T> = Some(T) | None
|
type Option<T> = Some(T) | None
|
||||||
let x = Option::Some(9); if x is Option::Some(q) then { q } else { 0 }"#;
|
let x = Option::Some(9); if x is Option::Some(q) then { q } else { 0 }"#;
|
||||||
|
|
||||||
eval_assert(source, "9");
|
eval_assert(source, "9");
|
||||||
|
|
||||||
|
/*
|
||||||
let source = r#"
|
let source = r#"
|
||||||
type Option<T> = Some(T) | None
|
type Option<T> = Some(T) | None
|
||||||
let x = Option::None; if x is Option::Some(q) then { q } else { 0 }"#;
|
let x = Option::None; if x is Option::Some(q) then { q } else { 0 }"#;
|
||||||
|
Loading…
Reference in New Issue
Block a user