From 2abb04f4bbf7a2682cedd64b473a40c5c2e3104d Mon Sep 17 00:00:00 2001 From: Akemi Izuko Date: Fri, 17 Nov 2023 14:09:02 -0700 Subject: [PATCH] Ast: wrap expressions in enum --- src/ast/expr.rs | 147 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/ast/expr.rs diff --git a/src/ast/expr.rs b/src/ast/expr.rs new file mode 100644 index 0000000..aca827f --- /dev/null +++ b/src/ast/expr.rs @@ -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), + Variable(Box), + BinaryOperator(Box), +} + +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(), + } + } +}