use ecow::EcoString; use num_bigint::BigInt; #[derive(Debug, Clone, PartialEq, Eq)] pub enum IncompleteType { Int, Float, Bool, String, Func { arguments: Vec, returns: Box, }, Struct { elements: Vec, }, List(Box), Generic { id: u64, }, } #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum CompleteType { Int, Float, Bool, String, Func { arguments: Vec, returns: Box, }, Struct { elements: Vec, }, List(Box), } #[derive(Debug, PartialEq, Eq, Default)] pub struct Module { pub name: EcoString, pub functions: Vec>, } #[derive(Debug, PartialEq, Eq, Clone)] pub struct Function { pub name: EcoString, pub return_type: T, pub parameters: Vec>, pub body: Expression, } #[derive(Debug, PartialEq, Eq, Clone)] pub struct FunctionParameter { pub type_: T, pub name: Option, } #[derive(Debug, PartialEq, Eq, Clone)] pub struct Var { pub name: EcoString, pub type_: T, } #[derive(Debug, PartialEq, Eq, Clone)] pub enum Expression { Block(Vec>), FunctionRef { module: EcoString, name: EcoString, arity: usize, type_: T, }, Var(Var), Int { value: BigInt, }, Float { value: EcoString, }, Bool { value: bool, }, String { value: EcoString, }, Equals { lhs: Box>, rhs: Box>, }, NotEquals { lhs: Box>, rhs: Box>, }, IntGt { lhs: Box>, rhs: Box>, }, IntGtEq { lhs: Box>, rhs: Box>, }, IntLt { lhs: Box>, rhs: Box>, }, IntLtEq { lhs: Box>, rhs: Box>, }, IntAdd { lhs: Box>, rhs: Box>, }, IntSub { lhs: Box>, rhs: Box>, }, IntMul { lhs: Box>, rhs: Box>, }, IntDiv { lhs: Box>, rhs: Box>, }, IntRem { lhs: Box>, rhs: Box>, }, FloatGt { lhs: Box>, rhs: Box>, }, FloatGtEq { lhs: Box>, rhs: Box>, }, FloatLt { lhs: Box>, rhs: Box>, }, FloatLtEq { lhs: Box>, rhs: Box>, }, FloatAdd { lhs: Box>, rhs: Box>, }, FloatSub { lhs: Box>, rhs: Box>, }, FloatMul { lhs: Box>, rhs: Box>, }, FloatDiv { lhs: Box>, rhs: Box>, }, StringConcat { lhs: Box>, rhs: Box>, }, List { items: Vec>, tail: Option>>, type_: T, }, Struct { tag: Option, items: Vec>, type_: T, }, StructTag { value: Box>, }, StructAccess { value: Box>, index: u64, type_: T, }, Set { name: Var, value: Box>, }, If { cond: Box>, then: Box>, else_: Box>, }, Call { target: Box>, args: Vec>, type_: T, }, } impl Expression { pub fn type_(&self) -> IncompleteType { match self { Expression::Block(expressions) => expressions .last() .expect("a block should not be empty") .type_(), Expression::FunctionRef { type_, .. } => type_.clone(), Expression::Var(var) => var.type_.clone(), Expression::Int { .. } => IncompleteType::Int, Expression::Float { .. } => IncompleteType::Float, Expression::Bool { .. } => IncompleteType::Bool, Expression::String { .. } => IncompleteType::String, Expression::Equals { .. } => IncompleteType::Bool, Expression::NotEquals { .. } => IncompleteType::Bool, Expression::IntGt { .. } => IncompleteType::Bool, Expression::IntGtEq { .. } => IncompleteType::Bool, Expression::IntLt { .. } => IncompleteType::Bool, Expression::IntLtEq { .. } => IncompleteType::Bool, Expression::IntAdd { .. } => IncompleteType::Int, Expression::IntSub { .. } => IncompleteType::Int, Expression::IntMul { .. } => IncompleteType::Int, Expression::IntDiv { .. } => IncompleteType::Int, Expression::IntRem { .. } => IncompleteType::Int, Expression::FloatGt { .. } => IncompleteType::Bool, Expression::FloatGtEq { .. } => IncompleteType::Bool, Expression::FloatLt { .. } => IncompleteType::Bool, Expression::FloatLtEq { .. } => IncompleteType::Bool, Expression::FloatAdd { .. } => IncompleteType::Bool, Expression::FloatSub { .. } => IncompleteType::Bool, Expression::FloatMul { .. } => IncompleteType::Bool, Expression::FloatDiv { .. } => IncompleteType::Bool, Expression::StringConcat { .. } => IncompleteType::Bool, Expression::List { type_, .. } => type_.clone(), Expression::Struct { type_, .. } => type_.clone(), Expression::StructTag { .. } => IncompleteType::Int, Expression::StructAccess { type_, .. } => type_.clone(), Expression::Set { value, .. } => value.type_(), Expression::If { then, .. } => then.type_(), Expression::Call { type_, .. } => type_.clone(), } } }