[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 {
|
impl Apply {
|
||||||
pub fn new(target: InstSpec, args: Vec<Expr>) -> Self {
|
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::Inst(inst) => (inst, Vec::new()),
|
||||||
InstSpec::Bound(bound_inst) => (bound_inst.inst, bound_inst.value_types),
|
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.
|
// Basic check on number of arguments.
|
||||||
assert!(
|
assert!(
|
||||||
inst.operands_in.len() == args.len(),
|
inst.operands_in.len() == args.len(),
|
||||||
|
|||||||
@@ -183,7 +183,10 @@ impl Instruction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn bind(&self, lane_type: impl Into<LaneType>) -> BoundInstruction {
|
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)]
|
#[derive(Clone)]
|
||||||
pub struct BoundInstruction {
|
pub struct BoundInstruction {
|
||||||
pub inst: Instruction,
|
pub inst: Instruction,
|
||||||
pub value_types: Vec<ValueType>,
|
pub value_types: Vec<ValueTypeOrAny>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BoundInstruction {
|
impl BoundInstruction {
|
||||||
pub fn bind(self, lane_type: impl Into<LaneType>) -> 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,
|
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 {
|
impl Into<InstSpec> for &Instruction {
|
||||||
@@ -729,10 +757,18 @@ impl Into<InstSpec> for BoundInstruction {
|
|||||||
/// Helper bind reused by {Bound,}Instruction::bind.
|
/// Helper bind reused by {Bound,}Instruction::bind.
|
||||||
fn bind(
|
fn bind(
|
||||||
inst: Instruction,
|
inst: Instruction,
|
||||||
lane_type: LaneType,
|
lane_type: Option<LaneType>,
|
||||||
mut value_types: Vec<ValueType>,
|
mut value_types: Vec<ValueTypeOrAny>,
|
||||||
) -> BoundInstruction {
|
) -> 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 {
|
match &inst.polymorphic_info {
|
||||||
Some(poly) => {
|
Some(poly) => {
|
||||||
assert!(
|
assert!(
|
||||||
@@ -747,5 +783,6 @@ fn bind(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BoundInstruction { inst, value_types }
|
BoundInstruction { inst, value_types }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user