Ast: wrap expressions in enum
Some checks failed
ci/woodpecker/push/build_rust Pipeline failed

This commit is contained in:
Akemi Izuko 2023-11-17 14:09:02 -07:00
parent 096aa39b05
commit 2abb04f4bb
Signed by: akemi
GPG key ID: 8DE0764E1809E9FC

147
src/ast/expr.rs Normal file
View file

@ -0,0 +1,147 @@
use std::string::ToString;
use super::BaseType;
use super::Quantifier;
use super::GazType;
/// Thin wrapper around all expression types, to avoid trait objects
#[derive(Clone)]
pub enum Expr {
Literal(Box<Literal>),
Variable(Box<Variable>),
BinaryOperator(Box<BinaryOperator>),
}
impl Expr {
pub fn new_literal(x: Literal) -> Self {
Self::Literal(Box::new(x))
}
pub fn new_variable(x: Variable) -> Self {
Self::Variable(Box::new(x))
}
pub fn new_binary_op(x: BinaryOperator) -> Self {
Self::BinaryOperator(Box::new(x))
}
}
impl GazType for Expr {
fn get_base(&self) -> BaseType {
match self {
Expr::Literal(x) => x.get_base(),
Expr::Variable(x) => x.get_base(),
Expr::BinaryOperator(x) => x.get_base(),
}
}
}
impl ToString for Expr {
fn to_string(&self) -> String {
match self {
Expr::Literal(x) => x.to_string(),
Expr::Variable(x) => x.to_string(),
Expr::BinaryOperator(x) => x.to_string(),
}
}
}
#[derive(Debug, Clone)]
pub enum Literal {
Int(i32),
Real(f32),
}
impl ToString for Literal {
fn to_string(&self) -> String {
match *self {
Literal::Int(x) => x.to_string(),
Literal::Real(x) => x.to_string(),
}
}
}
impl GazType for Literal {
fn get_base(&self) -> BaseType {
match *self {
Literal::Int(_) => BaseType::Int,
Literal::Real(_) => BaseType::Real,
}
}
}
#[derive(Clone, Default, Builder)]
#[builder(setter(into))]
pub struct Variable {
type_: BaseType,
quantifer: Quantifier,
name: String,
}
impl ToString for Variable {
fn to_string(&self) -> String {
self.name.clone()
}
}
impl GazType for Variable {
fn get_base(&self) -> BaseType {
self.type_
}
}
#[derive(Clone)]
pub enum BinaryOperator {
Add(Expr, Expr),
Subtract(Expr, Expr),
Multiply(Expr, Expr),
Divide(Expr, Expr),
}
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()),
}
s.push(')');
s.push(
match self {
&BinaryOperator::Add(_, _) => '+',
&BinaryOperator::Subtract(_, _) => '-',
&BinaryOperator::Multiply(_, _) => '*',
&BinaryOperator::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()),
}
s.push(')');
s
}
}
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(),
}
}
}