Skip to content

Instantly share code, notes, and snippets.

@Lapz
Created February 14, 2019 19:07
Show Gist options
  • Save Lapz/bdfd164b55b8f2735a3450ce97a15a15 to your computer and use it in GitHub Desktop.
Save Lapz/bdfd164b55b8f2735a3450ce97a15a15 to your computer and use it in GitHub Desktop.
Peter Sesoft
use std::collections::HashMap;
use std::hash::Hash;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Value {
True,
False,
String(String),
Var(String),
}
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
struct TypeName(pub String);
#[derive(Debug, Clone, PartialEq, Hash, Eq)]
struct Constructor {
name: String,
arity: i32,
span: i32,
}
fn tt() -> Pattern {
Pattern::Con(Constructor::new("true", 0, 2), vec![])
}
fn ff() -> Pattern {
Pattern::Con(Constructor::new("false", 0, 2), vec![])
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum Pattern {
Var(String), // e.g foo /vars
Con(Constructor, Vec<Pattern>), //e.g. List(10,Nil)
}
impl Constructor {
pub fn new(name: &str, arity: i32, span: i32) -> Self {
Self {
name: name.to_string(),
arity,
span,
}
}
}
/// Attempts to match the expression against each pattern from a rule in rules.
/// It succeds with the rhs if the rule matches; it fails otherwise
fn fail(expr: Pattern, rules: &mut Vec<(Pattern, Pattern)>) -> Option<Pattern> {
if rules.is_empty() {
return None;
} else {
let (pat1, rhs1) = rules.pop().unwrap();
_match(pat1, expr, vec![], rhs1, rules)
}
}
fn succed(
mut work: Vec<(Pattern, Pattern)>,
rhs: Pattern,
rules: &mut Vec<(Pattern, Pattern)>,
) -> Option<Pattern> {
for rule in rules.iter() {
work.push(rule.clone());
}
if work.is_empty() {
Some(rhs)
} else {
let (pat1, obj1) = work.pop().unwrap();
_match(pat1, obj1, work, rhs, rules)
}
}
fn _match(
pat1: Pattern,
obj1: Pattern,
mut work: Vec<(Pattern, Pattern)>,
rhs: Pattern,
rules: &mut Vec<(Pattern, Pattern)>,
) -> Option<Pattern> {
match pat1 {
Pattern::Var(_) => succed(work, rhs, rules),
Pattern::Con(ref pcon, ref pargs) => match obj1 {
Pattern::Con(ref ocon, ref oargs) => {
if ocon == pcon {
let both = oargs
.clone()
.into_iter()
.zip(pargs.clone().into_iter())
.collect::<Vec<(Pattern, Pattern)>>();
work.extend(both);
succed(work, rhs, rules)
} else {
fail(obj1, rules)
}
}
Pattern::Var(_) => succed(work, rhs, rules),
},
}
}
fn main() {
//allmrules -refers to the decleration patterns
//origobj refers to the match expression
/*
enum Billy {
Bob(String,i32),
Busey(Billy)
}
*/
let origobj = Pattern::Con(
Constructor::new("Bob", 2, 3),
vec![Pattern::Var("x".into()), Pattern::Var("y".into())],
);
let mut allmrules = vec![
(
Pattern::Con(
Constructor::new("Bob", 2, 3),
vec![Pattern::Var("x".into()), Pattern::Var("y".into())],
),
tt(),
),
(
Pattern::Con(
Constructor::new("Busey", 1, 3),
vec![Pattern::Con(
Constructor::new("Busey", 1, 3),
vec![Pattern::Var("z".into())],
)],
),
ff(),
),
(
Pattern::Con(
Constructor::new("Busey", 1, 3),
vec![Pattern::Con(
Constructor::new("Bob", 2, 3),
vec![Pattern::Var("x".into()), Pattern::Var("y".into())],
)],
),
tt(),
),
];
println!("{:#?}", fail(origobj, &mut allmrules))
//example
/*
match billy {
Bob(x,y) => {....},
Busey(Busey (z)) => {....},
Busey(Bob(x,y)) => {....},
}
*/
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment