1
0
This commit is contained in:
2024-11-01 05:16:51 +03:00
parent 552dec9401
commit f83c37287a
15 changed files with 684 additions and 207 deletions

View File

@@ -1,4 +1,16 @@
pub mod typed;
pub mod untyped;
use core::fmt;
use std::str::FromStr;
use typed::{Type, TypedExpr};
pub use untyped::UntypedExpr;
use crate::{
error::{self, SemanticError, SemanticErrorKind},
symbols::SymbolsTable,
};
#[derive(Debug, Copy, Clone)]
pub struct Span {
@@ -12,39 +24,6 @@ impl Span {
}
}
#[derive(Debug)]
pub enum Expr {
Int {
span: Span,
value: i64,
},
Float {
span: Span,
value: f64,
},
Var {
span: Span,
id: usize,
},
BinOp {
span: Span,
lhs: Box<Expr>,
op: BinOp,
rhs: Box<Expr>,
},
}
impl Expr {
pub fn span(&self) -> Span {
match self {
Expr::Float { span, .. } => *span,
Expr::Int { span, .. } => *span,
Expr::Var { span, .. } => *span,
Expr::BinOp { span, .. } => *span,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum BinOp {
Add,
@@ -74,3 +53,78 @@ impl fmt::Display for BinOp {
}
}
}
pub fn to_typed_expr(expr: UntypedExpr, symbols: &SymbolsTable) -> error::Result<TypedExpr> {
let expr = match expr {
UntypedExpr::Int { span, value } => TypedExpr::Int { span, value },
UntypedExpr::Float { span, value } => TypedExpr::Float { span, value },
UntypedExpr::Var {
span,
name,
typename,
} => {
let ty = typename
.and_then(|t| symbols.resolve(t))
.map(Type::from_str)
.transpose()
.map_err(|e| SemanticError::new(span, e))?
.unwrap_or(Type::Int);
TypedExpr::Var { span, name, ty }
}
UntypedExpr::BinOp { span, lhs, op, rhs } => {
let rhs = *rhs;
let lhs = *lhs;
match op {
BinOp::Div
if matches!(rhs, UntypedExpr::Int { .. } | UntypedExpr::Float { .. }) =>
{
match &rhs {
UntypedExpr::Int { span, value } if *value == 0 => {
return Err(SemanticError::new(
*span,
SemanticErrorKind::DivisionByZero,
)
.into())
}
UntypedExpr::Float { span, value } if *value == 0.0 => {
return Err(SemanticError::new(
*span,
SemanticErrorKind::DivisionByZero,
)
.into())
}
_ => {}
}
}
_ => {}
}
let lhs = to_typed_expr(lhs, symbols)?;
let rhs = to_typed_expr(rhs, symbols)?;
let (lhs, rhs) = match (lhs.ty(), rhs.ty()) {
(Type::Int, Type::Int) => (lhs, rhs),
(Type::Float, Type::Float) => (lhs, rhs),
(Type::Int, Type::Float) => {
let lhs = TypedExpr::cast_to_float(lhs);
(lhs, rhs)
}
(Type::Float, Type::Int) => {
let rhs = TypedExpr::cast_to_float(rhs);
(lhs, rhs)
}
};
TypedExpr::BinOp {
span,
lhs: Box::new(lhs),
op,
rhs: Box::new(rhs),
}
}
};
Ok(expr)
}