[meta] Add the ability to bind any type to an instruction;
This commit is contained in:
@@ -376,11 +376,17 @@ pub struct Apply {
|
||||
|
||||
impl Apply {
|
||||
pub fn new(target: InstSpec, args: Vec<Expr>) -> Self {
|
||||
let (inst, value_types) = match target.into() {
|
||||
let (inst, value_types) = match target {
|
||||
InstSpec::Inst(inst) => (inst, Vec::new()),
|
||||
InstSpec::Bound(bound_inst) => (bound_inst.inst, bound_inst.value_types),
|
||||
};
|
||||
|
||||
// Apply should only operate on concrete value types, not "any".
|
||||
let value_types = value_types
|
||||
.into_iter()
|
||||
.map(|vt| vt.expect("shouldn't be Any"))
|
||||
.collect();
|
||||
|
||||
// Basic check on number of arguments.
|
||||
assert!(
|
||||
inst.operands_in.len() == args.len(),
|
||||
|
||||
@@ -183,7 +183,10 @@ impl Instruction {
|
||||
}
|
||||
|
||||
pub fn bind(&self, lane_type: impl Into<LaneType>) -> BoundInstruction {
|
||||
bind(self.clone(), lane_type.into(), Vec::new())
|
||||
bind(self.clone(), Some(lane_type.into()), Vec::new())
|
||||
}
|
||||
pub fn bind_any(&self) -> BoundInstruction {
|
||||
bind(self.clone(), None, Vec::new())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,15 +383,34 @@ impl InstructionBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// A thin wrapper like Option<ValueType>, but with more precise semantics.
|
||||
#[derive(Clone)]
|
||||
pub enum ValueTypeOrAny {
|
||||
ValueType(ValueType),
|
||||
Any,
|
||||
}
|
||||
|
||||
impl ValueTypeOrAny {
|
||||
pub fn expect(self, msg: &str) -> ValueType {
|
||||
match self {
|
||||
ValueTypeOrAny::ValueType(vt) => vt,
|
||||
ValueTypeOrAny::Any => panic!(format!("Unexpected Any: {}", msg)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct BoundInstruction {
|
||||
pub inst: Instruction,
|
||||
pub value_types: Vec<ValueType>,
|
||||
pub value_types: Vec<ValueTypeOrAny>,
|
||||
}
|
||||
|
||||
impl BoundInstruction {
|
||||
pub fn bind(self, lane_type: impl Into<LaneType>) -> BoundInstruction {
|
||||
bind(self.inst, lane_type.into(), self.value_types)
|
||||
bind(self.inst, Some(lane_type.into()), self.value_types)
|
||||
}
|
||||
pub fn bind_any(self) -> BoundInstruction {
|
||||
bind(self.inst, None, self.value_types)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -712,6 +734,12 @@ impl InstSpec {
|
||||
InstSpec::Bound(bound_inst) => &bound_inst.inst,
|
||||
}
|
||||
}
|
||||
pub fn bind(&self, lane_type: impl Into<LaneType>) -> BoundInstruction {
|
||||
match self {
|
||||
InstSpec::Inst(inst) => inst.bind(lane_type),
|
||||
InstSpec::Bound(inst) => inst.clone().bind(lane_type),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<InstSpec> for &Instruction {
|
||||
@@ -729,10 +757,18 @@ impl Into<InstSpec> for BoundInstruction {
|
||||
/// Helper bind reused by {Bound,}Instruction::bind.
|
||||
fn bind(
|
||||
inst: Instruction,
|
||||
lane_type: LaneType,
|
||||
mut value_types: Vec<ValueType>,
|
||||
lane_type: Option<LaneType>,
|
||||
mut value_types: Vec<ValueTypeOrAny>,
|
||||
) -> BoundInstruction {
|
||||
value_types.push(ValueType::from(lane_type));
|
||||
match lane_type {
|
||||
Some(lane_type) => {
|
||||
value_types.push(ValueTypeOrAny::ValueType(lane_type.into()));
|
||||
}
|
||||
None => {
|
||||
value_types.push(ValueTypeOrAny::Any);
|
||||
}
|
||||
}
|
||||
|
||||
match &inst.polymorphic_info {
|
||||
Some(poly) => {
|
||||
assert!(
|
||||
@@ -747,5 +783,6 @@ fn bind(
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
BoundInstruction { inst, value_types }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user