Ast: traits for basetype
All checks were successful
ci/woodpecker/push/build_rust Pipeline was successful

This commit is contained in:
Akemi Izuko 2023-11-17 14:36:34 -07:00
parent a875a78f4b
commit 16a9632f9d
Signed by: akemi
GPG key ID: 8DE0764E1809E9FC
2 changed files with 133 additions and 25 deletions

View file

@ -70,7 +70,6 @@ impl GazType for Literal {
}
}
#[derive(Clone, Default, Builder)]
#[builder(setter(into))]
pub struct Variable {
@ -102,41 +101,129 @@ impl GazType for Variable {
}
#[derive(Clone)]
pub enum BinaryOperator {
enum BinaryOp {
Add(Expr, Expr),
Subtract(Expr, Expr),
Multiply(Expr, Expr),
Divide(Expr, Expr),
}
#[derive(Clone)]
pub struct BinaryOperator {
basetype: BaseType,
op: BinaryOp,
}
impl BinaryOperator {
pub fn add(left: Expr, right: Expr) -> Self {
let is_both_same = left.get_base() == right.get_base();
let is_one_real = left.get_base() == BaseType::Real || right.get_base() == BaseType::Real;
let is_one_int = left.get_base() == BaseType::Int || right.get_base() == BaseType::Int;
let basetype = if is_both_same {
left.get_base()
} else if is_one_real && is_one_int {
BaseType::Real
} else {
panic!("Unsupported types being added: {:?} and {:?}",
left.get_base(), right.get_base());
};
BinaryOperator {
basetype,
op: BinaryOp::Add(left, right),
}
}
pub fn sub(left: Expr, right: Expr) -> Self {
let is_both_same = left.get_base() == right.get_base();
let is_one_real = left.get_base() == BaseType::Real || right.get_base() == BaseType::Real;
let is_one_int = left.get_base() == BaseType::Int || right.get_base() == BaseType::Int;
let basetype = if is_both_same {
left.get_base()
} else if is_one_real && is_one_int {
BaseType::Real
} else {
panic!("Unsupported types being subtracted: {:?} and {:?}",
left.get_base(), right.get_base());
};
BinaryOperator {
basetype,
op: BinaryOp::Subtract(left, right),
}
}
pub fn multiply(left: Expr, right: Expr) -> Self {
let is_both_same = left.get_base() == right.get_base();
let is_one_real = left.get_base() == BaseType::Real || right.get_base() == BaseType::Real;
let is_one_int = left.get_base() == BaseType::Int || right.get_base() == BaseType::Int;
let basetype = if is_both_same {
left.get_base()
} else if is_one_real && is_one_int {
BaseType::Real
} else {
panic!("Unsupported types being multiplied: {:?} and {:?}",
left.get_base(), right.get_base());
};
BinaryOperator {
basetype,
op: BinaryOp::Multiply(left, right),
}
}
pub fn divide(left: Expr, right: Expr) -> Self {
let is_both_same = left.get_base() == right.get_base();
let is_one_real = left.get_base() == BaseType::Real || right.get_base() == BaseType::Real;
let is_one_int = left.get_base() == BaseType::Int || right.get_base() == BaseType::Int;
let basetype = if is_both_same {
left.get_base()
} else if is_one_real && is_one_int {
BaseType::Real
} else {
panic!("Unsupported types being divided: {:?} and {:?}",
left.get_base(), right.get_base());
};
BinaryOperator {
basetype,
op: BinaryOp::Divide(left, right),
}
}
}
impl ToString for BinaryOperator {
fn to_string(&self) -> String {
let mut s = String::new();
s.push('(');
match self {
BinaryOperator::Add(l, _) => s.push_str(&l.to_string()),
BinaryOperator::Subtract(l, _) => s.push_str(&l.to_string()),
BinaryOperator::Multiply(l, _) => s.push_str(&l.to_string()),
BinaryOperator::Divide(l, _) => s.push_str(&l.to_string()),
match &self.op {
BinaryOp::Add(l, _) => s.push_str(&l.to_string()),
BinaryOp::Subtract(l, _) => s.push_str(&l.to_string()),
BinaryOp::Multiply(l, _) => s.push_str(&l.to_string()),
BinaryOp::Divide(l, _) => s.push_str(&l.to_string()),
}
s.push(')');
s.push(
match self {
&BinaryOperator::Add(_, _) => '+',
&BinaryOperator::Subtract(_, _) => '-',
&BinaryOperator::Multiply(_, _) => '*',
&BinaryOperator::Divide(_, _) => '/',
match &self.op {
BinaryOp::Add(_, _) => '+',
BinaryOp::Subtract(_, _) => '-',
BinaryOp::Multiply(_, _) => '*',
BinaryOp::Divide(_, _) => '/',
}
);
s.push('(');
match self {
BinaryOperator::Add(_, r) => s.push_str(&r.to_string()),
BinaryOperator::Subtract(_, r) => s.push_str(&r.to_string()),
BinaryOperator::Multiply(_, r) => s.push_str(&r.to_string()),
BinaryOperator::Divide(_, r) => s.push_str(&r.to_string()),
match &self.op {
BinaryOp::Add(_, r) => s.push_str(&r.to_string()),
BinaryOp::Subtract(_, r) => s.push_str(&r.to_string()),
BinaryOp::Multiply(_, r) => s.push_str(&r.to_string()),
BinaryOp::Divide(_, r) => s.push_str(&r.to_string()),
}
s.push(')');
@ -146,12 +233,6 @@ impl ToString for BinaryOperator {
impl GazType for BinaryOperator {
fn get_base(&self) -> BaseType {
// TODO: This get_base is clearly wrong
match self {
BinaryOperator::Add(l, _) => l.get_base(),
BinaryOperator::Subtract(l, _) => l.get_base(),
BinaryOperator::Multiply(l, _) => l.get_base(),
BinaryOperator::Divide(l, _) => l.get_base(),
}
self.basetype
}
}

View file

@ -1,6 +1,8 @@
mod expr;
mod statement;
use std::fmt;
use expr::{
Expr,
Literal,
@ -39,7 +41,7 @@ impl ToString for Quantifier {
}
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Eq)]
pub enum BaseType {
Int,
Real,
@ -64,3 +66,28 @@ impl ToString for BaseType {
}.to_string()
}
}
impl fmt::Debug for BaseType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let name = match self {
BaseType::Int => "integer",
BaseType::Real => "real",
BaseType::Never => "never",
BaseType::Unset => "unset",
};
write!(f, "{}", name)
}
}
impl PartialEq for BaseType {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(&BaseType::Int, &BaseType::Int) => true,
(&BaseType::Real, &BaseType::Real) => true,
(&BaseType::Never, &BaseType::Never) => true,
(&BaseType::Unset, &BaseType::Unset) => false,
_ => false,
}
}
}