reid-llvm/reid/src/mir/types.rs

66 lines
1.7 KiB
Rust

use super::*;
#[derive(Debug, Clone)]
pub enum ReturnTypeOther {
Import(TokenRange),
Let(TokenRange),
EmptyBlock(TokenRange),
NoBlockReturn(TokenRange),
}
pub trait ReturnType {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther>;
}
impl ReturnType for Block {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
self.return_expression
.as_ref()
.ok_or(ReturnTypeOther::NoBlockReturn(self.meta.range))
.and_then(|(_, stmt)| stmt.return_type())
}
}
impl ReturnType for Statement {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
use StmtKind::*;
match &self.0 {
Expression(e) => e.return_type(),
Import(_) => Err(ReturnTypeOther::Import(self.1.range)),
Let(_, _) => Err(ReturnTypeOther::Let(self.1.range)),
}
}
}
impl ReturnType for Expression {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
use ExprKind::*;
match &self.0 {
Literal(lit) => Ok(lit.as_type()),
Variable(var) => var.return_type(),
BinOp(_, expr, _) => expr.return_type(),
Block(block) => block.return_type(),
FunctionCall(fcall) => fcall.return_type(),
If(expr) => expr.return_type(),
}
}
}
impl ReturnType for IfExpression {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
self.1.return_type()
}
}
impl ReturnType for VariableReference {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
Ok(self.0.clone())
}
}
impl ReturnType for FunctionCall {
fn return_type(&self) -> Result<TypeKind, ReturnTypeOther> {
Ok(self.return_type.clone())
}
}