More work on pattern-matching
This commit is contained in:
parent
e52d0bf515
commit
9e799c23ba
3
TODO.md
3
TODO.md
@ -4,6 +4,7 @@
|
||||
|
||||
* Get a test library for running many unit tests working
|
||||
* Write a human-readable display of the AST
|
||||
* Make an automatic (macro-based?) system for numbering compiler errors, this should be every type of error
|
||||
|
||||
## Symbols
|
||||
|
||||
@ -13,6 +14,8 @@
|
||||
* dealing with variable lookup w/in functions/closures should probably happen in AST -> ReducedAST
|
||||
* b/c that's where we go from a string name to a canonical ID (for e.g. 2nd param in 3rd enclosing scope)
|
||||
|
||||
* In fact to prove this works, the symbol table shoudl _parallelize_ the process of checking subscopes for local items
|
||||
|
||||
* Old notes on a plan of attack:
|
||||
|
||||
1. modify visitor so it can handle scopes
|
||||
|
@ -308,14 +308,15 @@ impl<'a> Reducer<'a> {
|
||||
impl ast::Pattern {
|
||||
fn reduce(&self, symbol_table: &SymbolTable) -> Result<Pattern, PatternError> {
|
||||
Ok(match self {
|
||||
ast::Pattern::Ignored => {
|
||||
Pattern::Ignored
|
||||
},
|
||||
ast::Pattern::Ignored => Pattern::Ignored,
|
||||
ast::Pattern::TuplePattern(subpatterns) => {
|
||||
let pats: Vec<_> = subpatterns.iter().map(|pat| pat.reduce(symbol_table)).collect();
|
||||
let pats: Result<Vec<Pattern>, PatternError> = pats.into_iter().collect();
|
||||
let pats = pats?;
|
||||
Pattern::Tuple(pats)
|
||||
let items: Vec<_> = subpatterns.iter().map(|pat| pat.reduce(symbol_table)).collect();
|
||||
let items: Result<Vec<Pattern>, PatternError> = items.into_iter().collect();
|
||||
let items = items?;
|
||||
Pattern::Tuple {
|
||||
tag: None,
|
||||
subpatterns: items,
|
||||
}
|
||||
},
|
||||
ast::Pattern::Literal(lit) => Pattern::Literal(match lit {
|
||||
ast::PatternLiteral::NumPattern { neg, num } => match (neg, num) {
|
||||
@ -328,15 +329,31 @@ impl ast::Pattern {
|
||||
ast::PatternLiteral::StringPattern(s) => Literal::StringLit(s.clone()),
|
||||
ast::PatternLiteral::BoolPattern(b) => Literal::Bool(*b),
|
||||
}),
|
||||
ast::Pattern::TupleStruct(_name, _subpatterns) => {
|
||||
unimplemented!()
|
||||
ast::Pattern::TupleStruct(name, subpatterns) => {
|
||||
let symbol = symbol_table.lookup_symbol(&name.id).unwrap();
|
||||
if let SymbolSpec::DataConstructor { index: tag, type_id, arity } = symbol.spec() {
|
||||
|
||||
let items: Vec<_> = subpatterns.iter().map(|pat| pat.reduce(symbol_table)).collect();
|
||||
let items: Result<Vec<Pattern>, PatternError> = items.into_iter().collect();
|
||||
let items = items?;
|
||||
|
||||
Pattern::Tuple {
|
||||
tag: Some(tag as u32),
|
||||
subpatterns: items,
|
||||
}
|
||||
} else {
|
||||
return Err("Internal error, trying to match something that's not a DataConstructor".into());
|
||||
}
|
||||
},
|
||||
ast::Pattern::VarOrName(name) => {
|
||||
//TODO fix this symbol not existing
|
||||
let symbol = symbol_table.lookup_symbol(&name.id).unwrap();
|
||||
println!("VarOrName symbol: {:?}", symbol);
|
||||
Pattern::Ignored
|
||||
},
|
||||
ast::Pattern::Record(name, /*Vec<(Rc<String>, Pattern)>*/ _) => {
|
||||
unimplemented!()
|
||||
},
|
||||
ast::Pattern::VarOrName(_name) => {
|
||||
unimplemented!()
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -125,7 +125,10 @@ pub struct Alternative {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Pattern {
|
||||
Tuple(Vec<Pattern>),
|
||||
Tuple {
|
||||
subpatterns: Vec<Pattern>,
|
||||
tag: Option<u32>,
|
||||
},
|
||||
Literal(Literal),
|
||||
Ignored,
|
||||
}
|
||||
|
@ -284,10 +284,19 @@ impl<'a> State<'a> {
|
||||
} else {
|
||||
false
|
||||
},
|
||||
Pattern::Tuple(subpatterns) => match scrut {
|
||||
Pattern::Tuple { subpatterns, tag } => match tag {
|
||||
None => match scrut {
|
||||
Primitive::Tuple(items) if items.len() == subpatterns.len() =>
|
||||
items.iter().zip(subpatterns.iter()).all(|(item, subpat)| matches(item, subpat)),
|
||||
_ => false //TODO should be a type error
|
||||
},
|
||||
Some(pattern_tag) => match scrut {
|
||||
//TODO should test type_ids for runtime type checking, once those work
|
||||
Primitive::Object { tag, items, .. } if tag == pattern_tag && items.len() == subpatterns.len() => {
|
||||
items.iter().zip(subpatterns.iter()).all(|(item, subpat)| matches(item, subpat))
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ use crate::tree_walk_eval::State;
|
||||
|
||||
fn evaluate_input(input: &str) -> Result<String, String> {
|
||||
let ast = crate::util::quick_ast(input);
|
||||
println!("AST: {:?}", ast);
|
||||
let mut symbol_table = SymbolTable::new();
|
||||
symbol_table.process_ast(&ast).unwrap();
|
||||
let reduced_ir = crate::reduced_ir::reduce(&ast, &symbol_table);
|
||||
|
Loading…
Reference in New Issue
Block a user