Part 1: implement type narrowing and broadening.
This commit is contained in:
parent
b117e2c463
commit
9df18e4286
1 changed files with 68 additions and 22 deletions
|
@ -304,28 +304,7 @@ impl ConjoiningClauses {
|
||||||
numeric_types.insert(ValueType::Double);
|
numeric_types.insert(ValueType::Double);
|
||||||
numeric_types.insert(ValueType::Long);
|
numeric_types.insert(ValueType::Long);
|
||||||
|
|
||||||
let entry = self.known_types.entry(variable);
|
self.narrow_types_for_var(variable, numeric_types);
|
||||||
match entry {
|
|
||||||
Entry::Vacant(vacant) => {
|
|
||||||
vacant.insert(numeric_types);
|
|
||||||
},
|
|
||||||
Entry::Occupied(mut occupied) => {
|
|
||||||
let narrowed: HashSet<ValueType> = numeric_types.intersection(occupied.get()).cloned().collect();
|
|
||||||
match narrowed.len() {
|
|
||||||
0 => {
|
|
||||||
// TODO: can't borrow as mutable more than once!
|
|
||||||
//self.mark_known_empty(EmptyBecause::TypeMismatch(occupied.key().clone(), occupied.get().clone(), ValueType::Double)); // I know…
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
// Hooray!
|
|
||||||
self.extracted_types.remove(occupied.key());
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
},
|
|
||||||
};
|
|
||||||
occupied.insert(narrowed);
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constrains the var if there's no existing type.
|
/// Constrains the var if there's no existing type.
|
||||||
|
@ -355,6 +334,73 @@ impl ConjoiningClauses {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `constrain_var_to_type` but in reverse: this expands the set of types
|
||||||
|
/// with which a variable is associated.
|
||||||
|
fn broaden_types(&mut self, additional_types: BTreeMap<Variable, HashSet<ValueType>>) {
|
||||||
|
for (var, new_types) in additional_types {
|
||||||
|
match self.known_types.entry(var) {
|
||||||
|
Entry::Vacant(e) => {
|
||||||
|
if new_types.len() == 1 {
|
||||||
|
self.extracted_types.remove(e.key());
|
||||||
|
}
|
||||||
|
e.insert(new_types);
|
||||||
|
},
|
||||||
|
Entry::Occupied(mut e) => {
|
||||||
|
e.get_mut().extend(new_types.into_iter());
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn narrow_types_for_var(&mut self, var: Variable, types: HashSet<ValueType>) {
|
||||||
|
if types.is_empty() {
|
||||||
|
// We hope this never occurs; we should catch this case earlier.
|
||||||
|
self.mark_known_empty(EmptyBecause::NoValidTypes(var));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if types.len() == 1 {
|
||||||
|
self.extracted_types.remove(&var);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut empty_because: Option<EmptyBecause> = None;
|
||||||
|
match self.known_types.entry(var) {
|
||||||
|
Entry::Vacant(e) => {
|
||||||
|
e.insert(types);
|
||||||
|
},
|
||||||
|
Entry::Occupied(mut e) => {
|
||||||
|
// TODO: we shouldn't need to clone here.
|
||||||
|
let intersected: HashSet<_> = types.intersection(e.get()).cloned().collect();
|
||||||
|
if intersected.is_empty() {
|
||||||
|
empty_because = Some(EmptyBecause::TypeMismatch(e.key().clone(),
|
||||||
|
e.get().clone(),
|
||||||
|
types.iter()
|
||||||
|
.next()
|
||||||
|
.cloned()
|
||||||
|
.unwrap()));
|
||||||
|
} else {
|
||||||
|
e.insert(intersected);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(e) = empty_because {
|
||||||
|
self.mark_known_empty(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn narrow_types(&mut self, additional_types: BTreeMap<Variable, HashSet<ValueType>>) {
|
||||||
|
if additional_types.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (var, new_types) in additional_types {
|
||||||
|
self.narrow_types_for_var(var, new_types);
|
||||||
|
if self.is_known_empty {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Ensure that the given place has the correct types to be a tx-id.
|
/// Ensure that the given place has the correct types to be a tx-id.
|
||||||
/// Right now this is mostly unimplemented: we fail hard if anything but a placeholder is
|
/// Right now this is mostly unimplemented: we fail hard if anything but a placeholder is
|
||||||
/// present.
|
/// present.
|
||||||
|
|
Loading…
Reference in a new issue