value.rs 36.57 KiB
#![allow(unused)]
extern crate derive_more;
use derive_more::{From};
/* Defines semantic meaning of IR operations. */
extern crate itertools;
use crate::dyn_const_value;
use self::itertools::Itertools;
use std::clone;
use std::convert::TryInto;
use std::panic;
extern crate hercules_ir;
extern crate hercules_opt;
use self::hercules_ir::*;
use self::hercules_opt::*;
#[derive(PartialEq, Debug, Clone, Eq)]
pub enum InterpreterVal {
Boolean(bool),
Integer8(i8),
Integer16(i16),
Integer32(i32),
Integer64(i64),
UnsignedInteger8(u8),
UnsignedInteger16(u16),
UnsignedInteger32(u32),
UnsignedInteger64(u64),
Float32(ordered_float::OrderedFloat<f32>),
Float64(ordered_float::OrderedFloat<f64>),
Product(TypeID, Box<[InterpreterVal]>),
Summation(TypeID, u32, Box<[InterpreterVal]>),
Array(TypeID, Box<[InterpreterVal]>), // TypeID of the array Type (not the element type)
// These can be freely? casted
DynamicConstant(usize),
ThreadID(usize),
}
#[derive(Clone)]
pub enum InterpreterWrapper {
Boolean(bool),
Integer8(i8),
Integer16(i16),
Integer32(i32),
Integer64(i64),
UnsignedInteger8(u8),
UnsignedInteger16(u16),
UnsignedInteger32(u32),
UnsignedInteger64(u64),
Float32(ordered_float::OrderedFloat<f32>),
Float64(ordered_float::OrderedFloat<f64>),
Product(Box<[InterpreterWrapper]>),
Summation(u32, Box<[InterpreterWrapper]>),
Array(Box<[InterpreterWrapper]>), // TypeID of the array Type (not the element type)
}
impl <T> From<&Vec<T>> for InterpreterWrapper
where T: Into<InterpreterWrapper> + Clone
{
fn from(value: &Vec<T>) -> Self {
let mut values = vec![];
for i in 0..value.len() {
values[i] = value[i].clone().into()
}
InterpreterWrapper::Array(values.into_boxed_slice())
}
}
impl <T> From<Vec<T>> for InterpreterWrapper
where T: Into<InterpreterWrapper> + Clone
{
fn from(value: Vec<T>) -> Self {
let mut values = vec![];
for i in 0..value.len() {
values.push(value[i].clone().into());
}
InterpreterWrapper::Array(values.into_boxed_slice())
}
}
impl <T> From<&[T]> for InterpreterWrapper
where T: Into<InterpreterWrapper> + Clone
{
fn from(value: &[T]) -> Self {
let mut values = vec![];
for i in 0..value.len() {
values[i] = value[i].clone().into()
}
InterpreterWrapper::Array(values.into_boxed_slice())
}
}
// Map rust types to interpreter values.
macro_rules! from_impl {
($rust:ty, $variant:tt) => {
impl From<$rust> for InterpreterWrapper {
fn from(value: $rust) -> Self {
InterpreterWrapper::$variant(value)
}
}
};
}
from_impl!(bool, Boolean);
from_impl!(i8, Integer8);
from_impl!(i16, Integer16);
from_impl!(i32, Integer32);
from_impl!(i64, Integer64);
from_impl!(u8, UnsignedInteger8);
from_impl!(u16, UnsignedInteger16);
from_impl!(u32, UnsignedInteger32);
from_impl!(u64, UnsignedInteger64);
impl<'a> InterpreterVal {
pub fn from_constant(
constant: &Constant,
constants: &'a Vec<Constant>,
types: &'a Vec<Type>,
dynamic_constants: &'a [DynamicConstant],
dynamic_constant_params: &'a [usize],
) -> Self {
match *constant {
Constant::Boolean(v) => Self::Boolean(v),
Constant::Integer8(v) => Self::Integer8(v),
Constant::Integer16(v) => Self::Integer16(v),
Constant::Integer32(v) => Self::Integer32(v),
Constant::Integer64(v) => Self::Integer64(v),
Constant::UnsignedInteger8(v) => Self::UnsignedInteger8(v),
Constant::UnsignedInteger16(v) => Self::UnsignedInteger16(v),
Constant::UnsignedInteger32(v) => Self::UnsignedInteger32(v),
Constant::UnsignedInteger64(v) => Self::UnsignedInteger64(v),
Constant::Float32(v) => Self::Float32(v),
Constant::Float64(v) => Self::Float64(v),
Constant::Product(_, _) => todo!(),
Constant::Summation(_, _, _) => todo!(),
Constant::Array(type_id) => {
// TODO: This is currently only implemented for arrays of primitive types, implement zero initializers for other types.
let ty = &types[type_id.idx()];
let extents: Vec<_> = ty
.try_extents()
.expect("PANIC: wrong type for array")
.into_iter()
.map(|extent| dyn_const_value(&dynamic_constants[extent.idx()], &dynamic_constant_params))
.collect();
let size = InterpreterVal::array_size(&extents);
// Need to recurse here, ugh.
let element_type_id = ty.try_element_type().expect("PANIC: no element type");
let element_type = &types[element_type_id.idx()];
// TODO Need a seperate funciton to handle this, as arrays w/ non-primitive elements should use Constant::Zero(element_id),
// and arrays w/ primitive elements should use the zero-initializer for those.
let element_zeroed = InterpreterVal::zero_initialized(&element_type);
let backing_array = vec![element_zeroed; size];
Self::Array(type_id, backing_array.into_boxed_slice())
}
}
}
/* Zero initialized interpreter value of a hercules type, only supported for primitive types. */
pub fn zero_initialized(ty: &'a Type) -> InterpreterVal {
match ty {
Type::Boolean => Self::Boolean(false),
Type::Integer8 => Self::Integer8(0),
Type::Integer16 => Self::Integer16(0),
Type::Integer32 => Self::Integer32(0),
Type::Integer64 => Self::Integer64(0),
Type::UnsignedInteger8 => Self::UnsignedInteger8(0),
Type::UnsignedInteger16 => Self::UnsignedInteger16(0),
Type::UnsignedInteger32 => Self::UnsignedInteger32(0),
Type::UnsignedInteger64 => Self::UnsignedInteger64(0),
//Type::Float32 => Self::Float32(0.0),
//Type::Float64 => Self::Float64(0.0),
_ => todo!("Zero initializer not implemented yet for this type"),
}
}
// TODO: Find some way to reuse this code and conditional constant prop code.
pub fn binary_op(
op: BinaryOperator,
left: InterpreterVal,
right: InterpreterVal,
) -> InterpreterVal {
// Do some type conversion first.
let left = match left {
InterpreterVal::DynamicConstant(v) => match right {
InterpreterVal::Integer8(_) => InterpreterVal::Integer8(v.try_into().unwrap()),
InterpreterVal::Integer16(_) => InterpreterVal::Integer16(v.try_into().unwrap()),
InterpreterVal::Integer32(_) => InterpreterVal::Integer32(v.try_into().unwrap()),
InterpreterVal::Integer64(_) => InterpreterVal::Integer64(v.try_into().unwrap()),
InterpreterVal::UnsignedInteger8(_) => {
InterpreterVal::UnsignedInteger8(v.try_into().unwrap())
}
InterpreterVal::UnsignedInteger16(_) => {
InterpreterVal::UnsignedInteger16(v.try_into().unwrap())
}
InterpreterVal::UnsignedInteger32(_) => {
InterpreterVal::UnsignedInteger64(v.try_into().unwrap())
}
InterpreterVal::UnsignedInteger64(_) => {
InterpreterVal::UnsignedInteger64(v.try_into().unwrap())
}
InterpreterVal::DynamicConstant(_) => {
panic!("PANIC: Some math on dynamic constants is unimplemented")
}
// InterpreterVal::ThreadID(_) => InterpreterVal::Boolean(v),
_ => panic!("PANIC: Some math on dynamic constants is unimplemented"),
},
// InterpreterVal::ThreadID(v) => todo!(),
_ => left,
};
let right = match right {
InterpreterVal::DynamicConstant(v) => match left {
InterpreterVal::Integer8(_) => InterpreterVal::Integer8(v.try_into().unwrap()),
InterpreterVal::Integer16(_) => InterpreterVal::Integer16(v.try_into().unwrap()),
InterpreterVal::Integer32(_) => InterpreterVal::Integer32(v.try_into().unwrap()),
InterpreterVal::Integer64(_) => InterpreterVal::Integer64(v.try_into().unwrap()),
InterpreterVal::UnsignedInteger8(_) => {
InterpreterVal::UnsignedInteger8(v.try_into().unwrap())
}
InterpreterVal::UnsignedInteger16(_) => {
InterpreterVal::UnsignedInteger16(v.try_into().unwrap())
}
InterpreterVal::UnsignedInteger32(_) => {
InterpreterVal::UnsignedInteger32(v.try_into().unwrap())
}
InterpreterVal::UnsignedInteger64(_) => {
InterpreterVal::UnsignedInteger64(v.try_into().unwrap())
}
InterpreterVal::DynamicConstant(_) => {
panic!("PANIC: Some math on dynamic constants is unimplemented")
}
_ => panic!("PANIC: Some math on dynamic constants is unimplemented"),
},
// InterpreterVal::ThreadID(v) => todo!(),
_ => right,
};
match (op, left.clone(), right.clone()) {
(BinaryOperator::Add, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val + right_val)
}
(BinaryOperator::Add, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val + right_val)
}
(BinaryOperator::Add, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val + right_val)
}
(BinaryOperator::Add, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val + right_val)
}
(
BinaryOperator::Add,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val + right_val),
(
BinaryOperator::Add,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val + right_val),
(
BinaryOperator::Add,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val + right_val),
(
BinaryOperator::Add,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val + right_val),
(BinaryOperator::Add, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Float32(left_val + right_val)
}
(BinaryOperator::Add, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Float64(left_val + right_val)
}
(BinaryOperator::Sub, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val - right_val)
}
(BinaryOperator::Sub, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val - right_val)
}
(BinaryOperator::Sub, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val - right_val)
}
(BinaryOperator::Sub, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val - right_val)
}
(
BinaryOperator::Sub,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val - right_val),
(
BinaryOperator::Sub,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val - right_val),
(
BinaryOperator::Sub,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val - right_val),
(
BinaryOperator::Sub,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val - right_val),
(BinaryOperator::Sub, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Float32(left_val - right_val)
}
(BinaryOperator::Sub, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Float64(left_val - right_val)
}
(BinaryOperator::Mul, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val * right_val)
}
(BinaryOperator::Mul, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val * right_val)
}
(BinaryOperator::Mul, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val * right_val)
}
(BinaryOperator::Mul, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val * right_val)
}
(
BinaryOperator::Mul,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val * right_val),
(
BinaryOperator::Mul,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val * right_val),
(
BinaryOperator::Mul,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val * right_val),
(
BinaryOperator::Mul,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val * right_val),
(BinaryOperator::Mul, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Float32(left_val * right_val)
}
(BinaryOperator::Mul, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Float64(left_val * right_val)
}
(BinaryOperator::Div, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val / right_val)
}
(BinaryOperator::Div, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val / right_val)
}
(BinaryOperator::Div, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val / right_val)
}
(BinaryOperator::Div, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val / right_val)
}
(
BinaryOperator::Div,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val / right_val),
(
BinaryOperator::Div,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val / right_val),
(
BinaryOperator::Div,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val / right_val),
(
BinaryOperator::Div,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val / right_val),
(BinaryOperator::Div, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Float32(left_val / right_val)
}
(BinaryOperator::Div, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Float64(left_val / right_val)
}
(BinaryOperator::Rem, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val % right_val)
}
(BinaryOperator::Rem, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val % right_val)
}
(BinaryOperator::Rem, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val % right_val)
}
(BinaryOperator::Rem, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val % right_val)
}
(
BinaryOperator::Rem,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val % right_val),
(
BinaryOperator::Rem,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val % right_val),
(
BinaryOperator::Rem,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val % right_val),
(
BinaryOperator::Rem,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val % right_val),
(BinaryOperator::Rem, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Float32(left_val % right_val)
}
(BinaryOperator::Rem, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Float64(left_val % right_val)
}
(BinaryOperator::LT, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Boolean(left_val < right_val)
}
(BinaryOperator::LT, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Boolean(left_val < right_val)
}
(BinaryOperator::LT, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Boolean(left_val < right_val)
}
(BinaryOperator::LT, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Boolean(left_val < right_val)
}
(
BinaryOperator::LT,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::Boolean(left_val < right_val),
(
BinaryOperator::LT,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::Boolean(left_val < right_val),
(
BinaryOperator::LT,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::Boolean(left_val < right_val),
(
BinaryOperator::LT,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::Boolean(left_val < right_val),
(BinaryOperator::LT, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Boolean(*left_val < *right_val)
}
(BinaryOperator::LT, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Boolean(*left_val < *right_val)
}
(BinaryOperator::LTE, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Boolean(left_val <= right_val)
}
(BinaryOperator::LTE, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Boolean(left_val <= right_val)
}
(BinaryOperator::LTE, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Boolean(left_val <= right_val)
}
(BinaryOperator::LTE, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Boolean(left_val <= right_val)
}
(
BinaryOperator::LTE,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::Boolean(left_val <= right_val),
(
BinaryOperator::LTE,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::Boolean(left_val <= right_val),
(
BinaryOperator::LTE,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::Boolean(left_val <= right_val),
(
BinaryOperator::LTE,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::Boolean(left_val <= right_val),
(BinaryOperator::LTE, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Boolean(*left_val <= *right_val)
}
(BinaryOperator::LTE, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Boolean(*left_val <= *right_val)
}
(BinaryOperator::GT, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Boolean(left_val > right_val)
}
(BinaryOperator::GT, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Boolean(left_val > right_val)
}
(BinaryOperator::GT, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Boolean(left_val > right_val)
}
(BinaryOperator::GT, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Boolean(left_val > right_val)
}
(
BinaryOperator::GT,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::Boolean(left_val > right_val),
(
BinaryOperator::GT,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::Boolean(left_val > right_val),
(
BinaryOperator::GT,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::Boolean(left_val > right_val),
(
BinaryOperator::GT,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::Boolean(left_val > right_val),
(BinaryOperator::GT, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Boolean(*left_val > *right_val)
}
(BinaryOperator::GT, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Boolean(*left_val > *right_val)
}
(BinaryOperator::GTE, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Boolean(left_val >= right_val)
}
(BinaryOperator::GTE, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Boolean(left_val >= right_val)
}
(BinaryOperator::GTE, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Boolean(left_val >= right_val)
}
(BinaryOperator::GTE, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Boolean(left_val >= right_val)
}
(
BinaryOperator::GTE,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::Boolean(left_val >= right_val),
(
BinaryOperator::GTE,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::Boolean(left_val >= right_val),
(
BinaryOperator::GTE,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::Boolean(left_val >= right_val),
(
BinaryOperator::GTE,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::Boolean(left_val >= right_val),
(BinaryOperator::GTE, Self::Float32(left_val), Self::Float32(right_val)) => {
Self::Boolean(*left_val >= *right_val)
}
(BinaryOperator::GTE, Self::Float64(left_val), Self::Float64(right_val)) => {
Self::Boolean(*left_val >= *right_val)
}
// EQ and NE can be implemented more easily, since we don't
// need to unpack the left and right values.
(BinaryOperator::EQ, left_val, right_val) => Self::Boolean(left_val == right_val),
(BinaryOperator::NE, left_val, right_val) => Self::Boolean(left_val != right_val),
(BinaryOperator::Or, Self::Boolean(left_val), Self::Boolean(right_val)) => {
Self::Boolean(left_val || right_val)
}
(BinaryOperator::Or, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val | right_val)
}
(BinaryOperator::Or, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val | right_val)
}
(BinaryOperator::Or, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val | right_val)
}
(BinaryOperator::Or, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val | right_val)
}
(
BinaryOperator::Or,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val | right_val),
(
BinaryOperator::Or,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val | right_val),
(
BinaryOperator::Or,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val | right_val),
(
BinaryOperator::Or,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val | right_val),
(BinaryOperator::And, Self::Boolean(left_val), Self::Boolean(right_val)) => {
Self::Boolean(left_val && right_val)
}
(BinaryOperator::And, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val & right_val)
}
(BinaryOperator::And, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val & right_val)
}
(BinaryOperator::And, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val & right_val)
}
(BinaryOperator::And, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val & right_val)
}
(
BinaryOperator::And,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val & right_val),
(
BinaryOperator::And,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val & right_val),
(
BinaryOperator::And,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val & right_val),
(
BinaryOperator::And,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val & right_val),
(BinaryOperator::Xor, Self::Boolean(left_val), Self::Boolean(right_val)) => {
Self::Boolean(left_val ^ right_val)
}
(BinaryOperator::Xor, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val ^ right_val)
}
(BinaryOperator::Xor, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val ^ right_val)
}
(BinaryOperator::Xor, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val ^ right_val)
}
(BinaryOperator::Xor, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val ^ right_val)
}
(
BinaryOperator::Xor,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val ^ right_val),
(
BinaryOperator::Xor,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val ^ right_val),
(
BinaryOperator::Xor,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val ^ right_val),
(
BinaryOperator::Xor,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val ^ right_val),
(BinaryOperator::LSh, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val << right_val)
}
(BinaryOperator::LSh, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val << right_val)
}
(BinaryOperator::LSh, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val << right_val)
}
(BinaryOperator::LSh, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val << right_val)
}
(
BinaryOperator::LSh,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val << right_val),
(
BinaryOperator::LSh,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val << right_val),
(
BinaryOperator::LSh,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val << right_val),
(
BinaryOperator::LSh,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val << right_val),
(BinaryOperator::RSh, Self::Integer8(left_val), Self::Integer8(right_val)) => {
Self::Integer8(left_val >> right_val)
}
(BinaryOperator::RSh, Self::Integer16(left_val), Self::Integer16(right_val)) => {
Self::Integer16(left_val >> right_val)
}
(BinaryOperator::RSh, Self::Integer32(left_val), Self::Integer32(right_val)) => {
Self::Integer32(left_val >> right_val)
}
(BinaryOperator::RSh, Self::Integer64(left_val), Self::Integer64(right_val)) => {
Self::Integer64(left_val >> right_val)
}
(
BinaryOperator::RSh,
Self::UnsignedInteger8(left_val),
Self::UnsignedInteger8(right_val),
) => Self::UnsignedInteger8(left_val >> right_val),
(
BinaryOperator::RSh,
Self::UnsignedInteger16(left_val),
Self::UnsignedInteger16(right_val),
) => Self::UnsignedInteger16(left_val >> right_val),
(
BinaryOperator::RSh,
Self::UnsignedInteger32(left_val),
Self::UnsignedInteger32(right_val),
) => Self::UnsignedInteger32(left_val >> right_val),
(
BinaryOperator::RSh,
Self::UnsignedInteger64(left_val),
Self::UnsignedInteger64(right_val),
) => Self::UnsignedInteger64(left_val >> right_val),
_ => {
println!("{:?}, {:?}", left, right);
panic!("Unsupported combination of binary operation and constant values. Did typechecking succeed?")
}
}
}
pub fn unary_op(op: UnaryOperator, val: InterpreterVal) -> Self {
match (op, val) {
(UnaryOperator::Not, Self::Boolean(val)) => Self::Boolean(!val),
(UnaryOperator::Not, Self::Integer8(val)) => Self::Integer8(!val),
(UnaryOperator::Not, Self::Integer16(val)) => Self::Integer16(!val),
(UnaryOperator::Not, Self::Integer32(val)) => Self::Integer32(!val),
(UnaryOperator::Not, Self::Integer64(val)) => Self::Integer64(!val),
(UnaryOperator::Neg, Self::Integer8(val)) => Self::Integer8(-val),
(UnaryOperator::Neg, Self::Integer16(val)) => Self::Integer16(-val),
(UnaryOperator::Neg, Self::Integer32(val)) => Self::Integer32(-val),
(UnaryOperator::Neg, Self::Integer64(val)) => Self::Integer64(-val),
(UnaryOperator::Neg, Self::Float32(val)) => Self::Float32(-val),
(UnaryOperator::Neg, Self::Float64(val)) => Self::Float64(-val),
(UnaryOperator::Cast(_), _) => todo!("Write cast impl"),
_ => panic!("Unsupported combination of unary operation and constant value. Did typechecking succeed?")
}
}
pub fn as_usize(&self) -> usize {
match *self {
InterpreterVal::Boolean(v) => v.try_into().unwrap(),
InterpreterVal::Integer8(v) => v.try_into().unwrap(),
InterpreterVal::Integer16(v) => v.try_into().unwrap(),
InterpreterVal::Integer32(v) => v.try_into().unwrap(),
InterpreterVal::Integer64(v) => v.try_into().unwrap(),
InterpreterVal::UnsignedInteger8(v) => v.try_into().unwrap(),
InterpreterVal::UnsignedInteger16(v) => v.try_into().unwrap(),
InterpreterVal::UnsignedInteger32(v) => v.try_into().unwrap(),
InterpreterVal::UnsignedInteger64(v) => v.try_into().unwrap(),
InterpreterVal::DynamicConstant(v) => v,
InterpreterVal::ThreadID(v) => v,
_ => panic!("PANIC: Value not castable to usize"),
}
}
// Defines row major / how we layout our arrays
pub fn array_idx(extents: &[usize], indices: &[usize]) -> usize {
let a = extents
.into_iter()
.enumerate()
.map(|(i, n)| {
extents[i + 1..]
.into_iter()
.cloned()
.reduce(|a, b| a * b)
.unwrap_or(1)
* indices[i]
})
.sum();
a
}
pub fn array_size(extents: &[usize]) -> usize {
extents
.into_iter()
.cloned()
.reduce(|a, b| a * b)
.unwrap_or(1)
}
}
mod tests {
use super::*;
#[test]
fn test_array_idx() {
let extents = [10, 5];
let indices = [1, 1];
let idx = InterpreterVal::array_idx(&extents, &indices);
assert_eq!(idx, 6)
}
}