234 lines
9.4 KiB
Rust
234 lines
9.4 KiB
Rust
use crate::gen::schema::*;
|
|
|
|
use preserves::value::Map;
|
|
use preserves::value::NestedValue;
|
|
use preserves::value::Value;
|
|
use preserves::value::merge::merge2;
|
|
|
|
pub type Env<V> = Map<Vec<String>, Schema<V>>;
|
|
|
|
#[derive(Debug)]
|
|
pub struct Context<'a, V: NestedValue> {
|
|
pub env: &'a Env<V>,
|
|
module: Vec<String>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
enum DynField<V: NestedValue> {
|
|
Simple(V),
|
|
Compound(Map<V, V>),
|
|
}
|
|
|
|
impl<'a, V: NestedValue> Context<'a, V> {
|
|
pub fn new(env: &'a Env<V>) -> Self {
|
|
Context {
|
|
env,
|
|
module: Vec::new(),
|
|
}
|
|
}
|
|
|
|
pub fn dynamic_parse(&mut self, module: &Vec<String>, name: &str, v: &V) -> Option<V> {
|
|
let old_module = (module.len() > 0).then(|| std::mem::replace(&mut self.module, module.clone()));
|
|
let schema = self.env.get(&self.module);
|
|
let definition = schema.and_then(|s| s.definitions.0.get(name));
|
|
let result = definition.and_then(|d| d.dynamic_parse(self, v));
|
|
if let Some(m) = old_module {
|
|
self.module = m;
|
|
}
|
|
result
|
|
}
|
|
|
|
pub fn dynamic_unparse(&mut self, module: &Vec<String>, name: &str, w: &V) -> Option<V> {
|
|
panic!("Not yet implemented");
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> Definition<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<V> {
|
|
match self {
|
|
Definition::Or { pattern_0, pattern_1, pattern_n } =>
|
|
pattern_0.dynamic_parse(ctxt, v)
|
|
.or_else(|| pattern_1.dynamic_parse(ctxt, v))
|
|
.or_else(|| pattern_n.iter().find_map(|p| p.dynamic_parse(ctxt, v))),
|
|
Definition::And { pattern_0, pattern_1, pattern_n } =>
|
|
pattern_0.dynamic_parse(ctxt, v)
|
|
.and_then(|w0| pattern_1.dynamic_parse(ctxt, v)
|
|
.and_then(|w1| pattern_n.iter().fold(merge(w0, w1), |w, p| {
|
|
w.and_then(|w| p.dynamic_parse(ctxt, v).and_then(
|
|
|wn| merge(w, wn)))
|
|
})))
|
|
.map(|w| DynField::Compound(w).finish()),
|
|
Definition::Pattern(p) => p.dynamic_parse(ctxt, v).map(|w| w.finish()),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> NamedAlternative<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<V> {
|
|
self.pattern.dynamic_parse(ctxt, v).map(|w| {
|
|
let mut r = Value::simple_record(&self.variant_label, 1);
|
|
match w {
|
|
DynField::Simple(field) => r.fields_vec_mut().push(field),
|
|
DynField::Compound(fields) => if fields.len() > 0 {
|
|
r.fields_vec_mut().push(V::new(fields))
|
|
}
|
|
}
|
|
r.finish().wrap()
|
|
})
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> NamedPattern<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<Map<V, V>> {
|
|
match self {
|
|
NamedPattern::Named(b) => {
|
|
let binding = &**b;
|
|
binding.pattern.dynamic_parse(ctxt, v).map(|w| w.to_map(Some(&binding.name)))
|
|
}
|
|
NamedPattern::Anonymous(b) => b.dynamic_parse(ctxt, v).map(|w| w.to_map(None))
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> NamedSimplePattern<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<DynField<V>> {
|
|
match self {
|
|
NamedSimplePattern::Named(b) => {
|
|
let binding = &**b;
|
|
binding.pattern.dynamic_parse(ctxt, v).map(
|
|
|w| DynField::Compound(w.to_map(Some(&binding.name))))
|
|
}
|
|
NamedSimplePattern::Anonymous(b) =>
|
|
b.dynamic_parse(ctxt, v),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> SimplePattern<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<DynField<V>> {
|
|
match self {
|
|
SimplePattern::Any => Some(DynField::Simple(v.clone())),
|
|
SimplePattern::Atom { atom_kind } => match &**atom_kind {
|
|
AtomKind::Boolean => v.value().is_boolean().then(|| DynField::Simple(v.clone())),
|
|
AtomKind::Float => v.value().is_float().then(|| DynField::Simple(v.clone())),
|
|
AtomKind::Double => v.value().is_double().then(|| DynField::Simple(v.clone())),
|
|
AtomKind::SignedInteger => v.value().is_signedinteger().then(|| DynField::Simple(v.clone())),
|
|
AtomKind::String => v.value().is_string().then(|| DynField::Simple(v.clone())),
|
|
AtomKind::ByteString => v.value().is_bytestring().then(|| DynField::Simple(v.clone())),
|
|
AtomKind::Symbol => v.value().is_symbol().then(|| DynField::Simple(v.clone())),
|
|
},
|
|
SimplePattern::Embedded { .. } => v.value().is_embedded().then(|| DynField::Simple(v.clone())),
|
|
SimplePattern::Lit { value } => (v == value).then(|| DynField::Compound(Map::new())),
|
|
SimplePattern::Seqof { pattern } =>
|
|
v.value().as_sequence()
|
|
.and_then(|vs| vs.iter().map(|v| (**pattern).dynamic_parse(ctxt, v).map(|w| w.finish()))
|
|
.collect::<Option<Vec<V>>>())
|
|
.map(|ws| DynField::Simple(V::new(ws))),
|
|
SimplePattern::Setof { pattern } =>
|
|
v.value().as_set()
|
|
.and_then(|vs| vs.iter().map(|v| (**pattern).dynamic_parse(ctxt, v).map(|w| w.finish()))
|
|
.collect::<Option<Vec<V>>>())
|
|
.map(|ws| DynField::Simple(V::new(ws))),
|
|
SimplePattern::Dictof { key, value } =>
|
|
v.value().as_dictionary()
|
|
.and_then(|d| {
|
|
d.iter().map(|(k, v)| {
|
|
(**key).dynamic_parse(ctxt, k)
|
|
.and_then(|kw| (**value).dynamic_parse(ctxt, v)
|
|
.map(|vw| (kw.finish(), vw.finish())))
|
|
}).collect::<Option<Map<V, V>>>()
|
|
})
|
|
.map(|d| DynField::Simple(V::new(d))),
|
|
SimplePattern::Ref(r) =>
|
|
ctxt.dynamic_parse(&r.module.0, &r.name, v).map(DynField::Simple),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> CompoundPattern<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<Map<V, V>> {
|
|
match self {
|
|
CompoundPattern::Rec { label, fields } =>
|
|
v.value().as_record(None).and_then(
|
|
|r| (**label).dynamic_parse(ctxt, r.label()).and_then(
|
|
|lw| (**fields).dynamic_parse(ctxt, &V::new(r.fields().to_vec())).and_then(
|
|
|fsw| merge(lw, fsw)))),
|
|
CompoundPattern::Tuple { patterns } =>
|
|
v.value().as_sequence().and_then(
|
|
|vs| if vs.len() == patterns.len() {
|
|
patterns.iter().zip(vs)
|
|
.fold(Some(Map::new()), |acc, (p, v)| {
|
|
acc.and_then(|acc| p.dynamic_parse(ctxt, v).and_then(
|
|
|w| merge(acc, w)))
|
|
})
|
|
} else {
|
|
None
|
|
}),
|
|
CompoundPattern::TuplePrefix { fixed, variable } =>
|
|
v.value().as_sequence().and_then(
|
|
|vs| if vs.len() >= fixed.len() {
|
|
fixed.iter().zip(vs)
|
|
.fold(Some(Map::new()), |acc, (p, v)| {
|
|
acc.and_then(|acc| p.dynamic_parse(ctxt, v).and_then(
|
|
|w| merge(acc, w)))
|
|
}).and_then(|fixed_ws| {
|
|
let remainder = V::new(vs[fixed.len()..].to_vec());
|
|
(**variable).dynamic_parse(ctxt, &remainder).and_then(
|
|
|variable_ws| merge(fixed_ws, variable_ws.unwrap_compound()))
|
|
})
|
|
} else {
|
|
None
|
|
}),
|
|
CompoundPattern::Dict { entries } =>
|
|
v.value().as_dictionary().and_then(
|
|
|d| (**entries).0.iter().fold(Some(Map::new()), |acc, (k, p)| {
|
|
acc.and_then(|acc| d.get(k).and_then(|v| p.dynamic_parse(ctxt, v).and_then(
|
|
|w| merge(acc, w.unwrap_compound()))))
|
|
})),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> Pattern<V> {
|
|
fn dynamic_parse(&self, ctxt: &mut Context<V>, v: &V) -> Option<DynField<V>> {
|
|
match self {
|
|
Pattern::SimplePattern(b) => (**b).dynamic_parse(ctxt, v),
|
|
Pattern::CompoundPattern(b) => (**b).dynamic_parse(ctxt, v).map(DynField::Compound),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<V: NestedValue> DynField<V> {
|
|
fn finish(self) -> V {
|
|
match self {
|
|
DynField::Simple(v) => v,
|
|
DynField::Compound(v) => V::new(v),
|
|
}
|
|
}
|
|
|
|
fn to_map(self, key: Option<&str>) -> Map<V, V> {
|
|
match self {
|
|
DynField::Simple(v) => {
|
|
let mut d = Map::new();
|
|
if let Some(k) = key {
|
|
d.insert(V::symbol(k), v);
|
|
}
|
|
d
|
|
}
|
|
DynField::Compound(d) => d,
|
|
}
|
|
}
|
|
|
|
fn unwrap_compound(self) -> Map<V, V> {
|
|
match self {
|
|
DynField::Simple(_) => panic!("Cannot unwrap DynField::Simple to compound fields"),
|
|
DynField::Compound(d) => d,
|
|
}
|
|
}
|
|
}
|
|
|
|
fn merge<V: NestedValue>(a: Map<V, V>, b: Map<V, V>) -> Option<Map<V, V>> {
|
|
merge2(V::new(a), V::new(b))
|
|
.map(|d| d.value_owned().into_dictionary().expect("merge to yield Dictionary"))
|
|
}
|