Follow simplifications to sturdy caveats
This commit is contained in:
parent
091ca088e0
commit
f5b1fec90f
|
@ -559,43 +559,29 @@ impl Env {
|
|||
// TODO: properly consolidate constant templates into literals.
|
||||
match self.instantiate_template(binding_names, r.label())? {
|
||||
sturdy::Template::Lit(b) =>
|
||||
sturdy::Template::TCompound(Box::new(sturdy::TCompound {
|
||||
ctor: sturdy::ConstructorSpec::CRec(Box::new(sturdy::CRec {
|
||||
label: b.value,
|
||||
arity: r.fields().len().into(),
|
||||
})),
|
||||
members: sturdy::TCompoundMembers(
|
||||
r.fields().iter().enumerate()
|
||||
.map(|(i, t)| Ok(
|
||||
(AnyValue::new(i),
|
||||
self.instantiate_template(binding_names, t)?)))
|
||||
.collect::<io::Result<Map<_, sturdy::Template>>>()?),
|
||||
sturdy::Template::TCompound(Box::new(sturdy::TCompound::Rec {
|
||||
label: b.value,
|
||||
fields: r.fields().iter()
|
||||
.map(|t| self.instantiate_template(binding_names, t))
|
||||
.collect::<io::Result<Vec<sturdy::Template>>>()?,
|
||||
})),
|
||||
_ => Err(bad_instruction("Record template must have literal label"))?,
|
||||
}
|
||||
}
|
||||
},
|
||||
Value::Sequence(v) =>
|
||||
sturdy::Template::TCompound(Box::new(sturdy::TCompound {
|
||||
ctor: sturdy::ConstructorSpec::CArr(Box::new(sturdy::CArr {
|
||||
arity: v.len().into(),
|
||||
})),
|
||||
members: sturdy::TCompoundMembers(
|
||||
v.iter().enumerate()
|
||||
.map(|(i, p)| Ok(
|
||||
(AnyValue::new(i),
|
||||
self.instantiate_template(binding_names, p)?)))
|
||||
.collect::<io::Result<Map<_, sturdy::Template>>>()?),
|
||||
sturdy::Template::TCompound(Box::new(sturdy::TCompound::Arr {
|
||||
items: v.iter()
|
||||
.map(|p| self.instantiate_template(binding_names, p))
|
||||
.collect::<io::Result<Vec<sturdy::Template>>>()?,
|
||||
})),
|
||||
Value::Set(_) =>
|
||||
Err(bad_instruction(&format!("Sets not permitted in templates: {:?}", template)))?,
|
||||
Value::Dictionary(v) =>
|
||||
sturdy::Template::TCompound(Box::new(sturdy::TCompound {
|
||||
ctor: sturdy::ConstructorSpec::CDict(Box::new(sturdy::CDict)),
|
||||
members: sturdy::TCompoundMembers(
|
||||
v.iter()
|
||||
.map(|(a, b)| Ok((a.clone(), self.instantiate_template(binding_names, b)?)))
|
||||
.collect::<io::Result<Map<_, sturdy::Template>>>()?),
|
||||
sturdy::Template::TCompound(Box::new(sturdy::TCompound::Dict {
|
||||
entries: v.iter()
|
||||
.map(|(a, b)| Ok((a.clone(), self.instantiate_template(binding_names, b)?)))
|
||||
.collect::<io::Result<Map<_, sturdy::Template>>>()?,
|
||||
})),
|
||||
})
|
||||
}
|
||||
|
@ -612,29 +598,17 @@ fn embed_pattern(p: &P::Pattern) -> sturdy::Pattern {
|
|||
})),
|
||||
P::Pattern::DCompound(b) => sturdy::Pattern::PCompound(Box::new(match &**b {
|
||||
P::DCompound::Rec { label, fields } =>
|
||||
sturdy::PCompound {
|
||||
ctor: sturdy::ConstructorSpec::CRec(Box::new(sturdy::CRec {
|
||||
label: label.clone(),
|
||||
arity: fields.len().into(),
|
||||
})),
|
||||
members: sturdy::PCompoundMembers(
|
||||
fields.iter().enumerate().map(
|
||||
|(k, v)| (AnyValue::new(k), embed_pattern(v))).collect()),
|
||||
sturdy::PCompound::Rec {
|
||||
label: label.clone(),
|
||||
fields: fields.iter().map(embed_pattern).collect(),
|
||||
},
|
||||
P::DCompound::Arr { items } =>
|
||||
sturdy::PCompound {
|
||||
ctor: sturdy::ConstructorSpec::CArr(Box::new(sturdy::CArr {
|
||||
arity: items.len().into(),
|
||||
})),
|
||||
members: sturdy::PCompoundMembers(
|
||||
items.iter().enumerate().map(
|
||||
|(k, v)| (AnyValue::new(k), embed_pattern(v))).collect()),
|
||||
sturdy::PCompound::Arr {
|
||||
items: items.iter().map(embed_pattern).collect(),
|
||||
},
|
||||
P::DCompound::Dict { entries } =>
|
||||
sturdy::PCompound {
|
||||
ctor: sturdy::ConstructorSpec::CDict(Box::new(sturdy::CDict)),
|
||||
members: sturdy::PCompoundMembers(
|
||||
entries.iter().map(|(k, v)| (k.clone(), embed_pattern(v))).collect()),
|
||||
sturdy::PCompound::Dict {
|
||||
entries: entries.iter().map(|(k, v)| (k.clone(), embed_pattern(v))).collect(),
|
||||
},
|
||||
})),
|
||||
}
|
||||
|
|
|
@ -26,15 +26,6 @@ pub enum CaveatError {
|
|||
UnboundRef,
|
||||
/// A pattern includes a negation of a subpattern that includes a binding.
|
||||
BindingUnderNegation,
|
||||
/// A constructor specification includes an arity that exceeds the range of a [`usize`].
|
||||
LudicrousArity,
|
||||
/// A member index in a compound pattern exceeds the arity limit of the constructor.
|
||||
IndexOutOfBounds,
|
||||
/// A member index for a sequence-like compound is not an integer.
|
||||
InvalidIndex,
|
||||
/// A compound template does not specify a subtemplate for each of
|
||||
/// the slots of the compound value being constructed.
|
||||
IncompleteTemplate,
|
||||
}
|
||||
|
||||
impl Attenuation {
|
||||
|
@ -78,37 +69,6 @@ impl Caveat {
|
|||
}
|
||||
}
|
||||
|
||||
impl ConstructorSpec {
|
||||
fn arity(&self) -> Result<Option<usize>, CaveatError> {
|
||||
match self {
|
||||
ConstructorSpec::CRec(b) => match usize::try_from(&(&**b).arity) {
|
||||
Err(_) => Err(CaveatError::LudicrousArity),
|
||||
Ok(a) => Ok(Some(a)),
|
||||
}
|
||||
ConstructorSpec::CArr(b) => match usize::try_from(&(&**b).arity) {
|
||||
Err(_) => return Err(CaveatError::LudicrousArity),
|
||||
Ok(a) => Ok(Some(a)),
|
||||
}
|
||||
ConstructorSpec::CDict(_) => Ok(None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_member_key(limit: usize, k: &_Any) -> Result<(), CaveatError> {
|
||||
match k.value().as_signedinteger() {
|
||||
None => Err(CaveatError::InvalidIndex),
|
||||
Some(k) => match usize::try_from(k) {
|
||||
Err(_) => Err(CaveatError::IndexOutOfBounds),
|
||||
Ok(k) =>
|
||||
if k >= limit {
|
||||
Err(CaveatError::IndexOutOfBounds)
|
||||
} else {
|
||||
Ok(())
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Pattern {
|
||||
fn binding_count(&self) -> Result<usize, CaveatError> {
|
||||
match self {
|
||||
|
@ -132,17 +92,22 @@ impl Pattern {
|
|||
}
|
||||
Ok(count)
|
||||
}
|
||||
Pattern::PCompound(b) => {
|
||||
let PCompound { ctor, members: PCompoundMembers(ms) } = &**b;
|
||||
let arity = ctor.arity()?;
|
||||
let mut count = 0;
|
||||
for (k, p) in ms.iter() {
|
||||
if let Some(limit) = arity {
|
||||
check_member_key(limit, k)?;
|
||||
Pattern::PCompound(b) => match &**b {
|
||||
PCompound::Rec { fields: items, .. } |
|
||||
PCompound::Arr { items } => {
|
||||
let mut count = 0;
|
||||
for p in items.iter() {
|
||||
count += p.binding_count()?;
|
||||
}
|
||||
count += p.binding_count()?
|
||||
Ok(count)
|
||||
}
|
||||
PCompound::Dict { entries } => {
|
||||
let mut count = 0;
|
||||
for (_k, p) in entries.iter() {
|
||||
count += p.binding_count()?;
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
Ok(count)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,42 +138,34 @@ impl Pattern {
|
|||
Pattern::PNot(b) => !(&**b).pattern.matches(a, bindings),
|
||||
Pattern::Lit(b) => &(&**b).value == a,
|
||||
Pattern::PCompound(b) => match &**b {
|
||||
PCompound { ctor: ConstructorSpec::CRec(b), members: PCompoundMembers(ms) } => {
|
||||
let CRec { label, arity } = &**b;
|
||||
let arity = usize::try_from(arity).expect("in-range arity");
|
||||
match a.value().as_record(Some(arity)) {
|
||||
PCompound::Rec { label, fields } => {
|
||||
match a.value().as_record(Some(fields.len())) {
|
||||
Some(r) => {
|
||||
if r.label() != label { return false; }
|
||||
for (k, p) in ms.iter() {
|
||||
let k = k.value().as_signedinteger().expect("integer index");
|
||||
let k = usize::try_from(k).expect("in-range index");
|
||||
if !p.matches(&r.fields()[k], bindings) { return false; }
|
||||
for (i, p) in fields.iter().enumerate() {
|
||||
if !p.matches(&r.fields()[i], bindings) { return false; }
|
||||
}
|
||||
true
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
PCompound { ctor: ConstructorSpec::CArr(b), members: PCompoundMembers(ms) } => {
|
||||
let CArr { arity } = &**b;
|
||||
let arity = usize::try_from(arity).expect("in-range arity");
|
||||
PCompound::Arr { items } => {
|
||||
match a.value().as_sequence() {
|
||||
Some(vs) => {
|
||||
if vs.len() < arity { return false; }
|
||||
for (k, p) in ms.iter() {
|
||||
let k = k.value().as_signedinteger().expect("integer index");
|
||||
let k = usize::try_from(k).expect("in-range index");
|
||||
if !p.matches(&vs[k], bindings) { return false; }
|
||||
if vs.len() < items.len() { return false; }
|
||||
for (i, p) in items.iter().enumerate() {
|
||||
if !p.matches(&vs[i], bindings) { return false; }
|
||||
}
|
||||
true
|
||||
},
|
||||
None => false,
|
||||
}
|
||||
}
|
||||
PCompound { ctor: ConstructorSpec::CDict(_), members: PCompoundMembers(ms) } => {
|
||||
PCompound::Dict { entries } => {
|
||||
match a.value().as_dictionary() {
|
||||
Some(es) => {
|
||||
for (k, p) in ms.iter() {
|
||||
for (k, p) in entries.iter() {
|
||||
match es.get(k) {
|
||||
Some(v) => if !p.matches(v, bindings) { return false; },
|
||||
None => return false,
|
||||
|
@ -237,22 +194,22 @@ impl Template {
|
|||
Err(_) => Err(CaveatError::UnboundRef),
|
||||
},
|
||||
Template::Lit(_) => Ok(0),
|
||||
Template::TCompound(b) => {
|
||||
let TCompound { ctor, members: TCompoundMembers(ms) } = &**b;
|
||||
let arity = ctor.arity()?;
|
||||
let mut max = 0;
|
||||
if let Some(limit) = arity {
|
||||
if ms.len() != limit {
|
||||
return Err(CaveatError::IncompleteTemplate);
|
||||
Template::TCompound(b) => match &**b {
|
||||
TCompound::Rec { fields: items, .. } |
|
||||
TCompound::Arr { items } => {
|
||||
let mut max = 0;
|
||||
for t in items.iter() {
|
||||
max = max.max(t.implied_binding_count()?);
|
||||
}
|
||||
Ok(max)
|
||||
}
|
||||
for (k, t) in ms.iter() {
|
||||
if let Some(limit) = arity {
|
||||
check_member_key(limit, k)?;
|
||||
TCompound::Dict { entries } => {
|
||||
let mut max = 0;
|
||||
for (_k, t) in entries.iter() {
|
||||
max = max.max(t.implied_binding_count()?);
|
||||
}
|
||||
max = max.max(t.implied_binding_count()?);
|
||||
Ok(max)
|
||||
}
|
||||
Ok(max)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -267,48 +224,27 @@ impl Template {
|
|||
}
|
||||
Template::TRef(b) => Some(bindings[usize::try_from(&(&**b).binding).expect("in-range index")].clone()),
|
||||
Template::Lit(b) => Some((&**b).value.clone()),
|
||||
Template::TCompound(b) => {
|
||||
let TCompound { ctor, members: TCompoundMembers(ms) } = &**b;
|
||||
match ctor {
|
||||
ConstructorSpec::CRec(b) => {
|
||||
let CRec { label, arity } = &**b;
|
||||
let arity = usize::try_from(arity).expect("in-range arity");
|
||||
let mut r = Value::record(label.clone(), arity);
|
||||
for i in 0..arity {
|
||||
let t = ms.get(&Value::from(i).wrap()).expect("entry for each index");
|
||||
match t.instantiate(bindings) {
|
||||
None => return None,
|
||||
Some(v) => r.fields_vec_mut().push(v),
|
||||
}
|
||||
}
|
||||
Some(r.finish().wrap())
|
||||
Template::TCompound(b) => match &**b {
|
||||
TCompound::Rec { label, fields } => {
|
||||
let mut r = Value::record(label.clone(), fields.len());
|
||||
for t in fields.iter() {
|
||||
r.fields_vec_mut().push(t.instantiate(bindings)?);
|
||||
}
|
||||
ConstructorSpec::CArr(b) => {
|
||||
let CArr { arity } = &**b;
|
||||
let arity = usize::try_from(arity).expect("in-range arity");
|
||||
let mut r = Vec::with_capacity(arity);
|
||||
for i in 0..arity {
|
||||
let t = ms.get(&Value::from(i).wrap()).expect("entry for each index");
|
||||
match t.instantiate(bindings) {
|
||||
None => return None,
|
||||
Some(v) => r.push(v),
|
||||
}
|
||||
}
|
||||
Some(Value::from(r).wrap())
|
||||
Some(r.finish().wrap())
|
||||
}
|
||||
TCompound::Arr { items } => {
|
||||
let mut r = Vec::with_capacity(items.len());
|
||||
for t in items.iter() {
|
||||
r.push(t.instantiate(bindings)?);
|
||||
}
|
||||
ConstructorSpec::CDict(_) => {
|
||||
let mut r = Map::new();
|
||||
for (k, t) in ms.iter() {
|
||||
match t.instantiate(bindings) {
|
||||
None => return None,
|
||||
Some(v) => {
|
||||
r.insert(k.clone(), v);
|
||||
()
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Value::from(r).wrap())
|
||||
Some(Value::from(r).wrap())
|
||||
}
|
||||
TCompound::Dict { entries } => {
|
||||
let mut r = Map::new();
|
||||
for (k, t) in entries.iter() {
|
||||
r.insert(k.clone(), t.instantiate(bindings)?);
|
||||
}
|
||||
Some(Value::from(r).wrap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue