use crate::ast::*; use crate::typing::Type; #[derive(Debug, PartialEq)] pub struct SExpr { pub expr: Expr, pub span: Span, } #[derive(Debug, PartialEq)] pub struct BinaryExpression { pub lhs: Box, pub op: BinaryOperator, pub op_span: Span, pub rhs: Box, pub typ: Type, } #[derive(Debug, PartialEq)] pub enum Expr { BinaryExpression(BinaryExpression), UnaryExpression { op: UnaryOperator, inner: Box, }, Identifier { name: String, typ: Type, }, Call(Box), Block(Box), /// Last field is either Expr::Block or Expr::IfExpr IfExpr { cond: Box, then_body: Box, else_body: Box, typ: Type, }, // Literals UnitLiteral, BooleanLiteral(bool), IntegerLiteral(i64), FloatLiteral(f64), StringLiteral(String), } impl Block { #[inline] pub fn ty(&self) -> Type { // XXX: Cloning may be expensive -> TypeId? self.typ.clone() } } impl Expr { pub fn ty(&self) -> Type { match self { Expr::BinaryExpression(BinaryExpression { typ, .. }) => typ.clone(), Expr::UnaryExpression { inner, .. } => inner.ty(), // XXX: problems will arise here Expr::Identifier { typ, .. } => typ.clone(), Expr::Call(call) => call.typ.clone(), Expr::Block(block) => block.typ.clone(), Expr::IfExpr { typ, .. } => typ.clone(), Expr::UnitLiteral => Type::Unit, Expr::BooleanLiteral(_) => Type::Bool, Expr::IntegerLiteral(_) => Type::Int, Expr::FloatLiteral(_) => Type::Float, Expr::StringLiteral(_) => Type::Str, } } } impl SExpr { #[inline] pub fn ty(&self) -> Type { self.expr.ty() } }