lab4
This commit is contained in:
120
src/ast/mod.rs
120
src/ast/mod.rs
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user