Skip to content

Commit

Permalink
Improve UndeclaredVar error.
Browse files Browse the repository at this point in the history
  • Loading branch information
Vlamonster committed Nov 8, 2023
1 parent 9d4360e commit f45a6c7
Show file tree
Hide file tree
Showing 8 changed files with 42 additions and 23 deletions.
19 changes: 9 additions & 10 deletions compiler/src/passes/parse/grammar.lalrpop
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use std::str::FromStr;
use crate::passes::parse::{Def, TypeDef, Expr, Lit, Op, Param};
use crate::passes::parse::PrgParsed;
use crate::passes::parse::Type;
Expand Down Expand Up @@ -158,14 +157,14 @@ ExprStmt: Expr<'input> = {
}

ExprInStmt: Expr<'input> = {
<sym:Ident> "=" <bnd:Spanned<ExprLogicalOr<Struct>>> => Expr::Assign {
<sym:Spanned<Ident>> "=" <bnd:Spanned<ExprLogicalOr<Struct>>> => Expr::Assign {
sym,
bnd: Box::new(bnd),
},
"if" <cnd:Spanned<ExprLogicalOr<Never>>> "{" <thn:Spanned<Expr>> "}" <l:@L> <els:("else" "{" <Spanned<Expr>> "}")?> <r:@R> => Expr::If {
cnd: Box::new(cnd),
thn: Box::new(thn),
els: Box::new(els.unwrap_or(Spanned { span: (l, r), expr: Expr::Lit { val: Lit::Unit }})),
els: Box::new(els.unwrap_or(Spanned { span: (l, r), inner: Expr::Lit { val: Lit::Unit }})),
},
"loop" "{" <bdy:Spanned<Expr>> "}" => Expr::Loop {
bdy: Box::new(bdy),
Expand All @@ -174,22 +173,22 @@ ExprInStmt: Expr<'input> = {
<l:@L> "while" <r:@R> <cnd:Spanned<ExprLogicalOr<Never>>> "{" <bdy:Spanned<Expr>> "}" => Expr::Loop {
bdy: Box::new(Spanned {
span: (l, r),
expr: Expr::If {
inner: Expr::If {
cnd: Box::new(cnd),
thn: Box::new(bdy),
els: Box::new(Spanned {
span: (l, r),
expr: Expr::Seq {
inner: Expr::Seq {
stmt: Box::new(Spanned {
span: (l, r),
expr: Expr::Break { bdy: Box::new(Spanned {
inner: Expr::Break { bdy: Box::new(Spanned {
span: (l, r),
expr: Expr::Lit { val: Lit::Unit },
inner: Expr::Lit { val: Lit::Unit },
})},
}),
cnt: Box::new(Spanned {
span: (l, r),
expr: Expr::Lit { val: Lit::Unit },
inner: Expr::Lit { val: Lit::Unit },
}),
},
}),
Expand Down Expand Up @@ -305,7 +304,7 @@ Struct: Expr<'input> = {

StructArg : (&'input str, Spanned<Expr<'input>>) = {
<Ident> ":" <Spanned<Expr>>,
<l:@L> <sym:Ident> <r:@R> => (sym, Spanned { span: (l, r), expr: Expr::Var { sym } })
<l:@L> <sym:Ident> <r:@R> => (sym, Spanned { span: (l, r), inner: Expr::Var { sym } })
}

Never: Expr<'input> = {};
Expand All @@ -330,5 +329,5 @@ Comma<T>: Vec<T> = {
}
}

Spanned<T>: Spanned<T> = <l:@L> <expr:T> <r:@R> => Spanned { span: (l, r), expr };
Spanned<T>: Spanned<T> = <l:@L> <inner:T> <r:@R> => Spanned { span: (l, r), inner };

4 changes: 2 additions & 2 deletions compiler/src/passes/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ pub enum Expr<'p> {
/// Only mutable or uninitialized immutable variables can be assigned a new value.
Assign {
/// Symbol representing the variable to which the assignment is made.
sym: &'p str,
sym: Spanned<&'p str>,
/// The expression whose result is assigned to the variable.
bnd: Box<Spanned<Expr<'p>>>,
},
Expand Down Expand Up @@ -225,7 +225,7 @@ pub enum Expr<'p> {
#[derive(Debug, PartialEq, Functor)]
pub struct Spanned<T> {
pub span: (usize, usize),
pub expr: T,
pub inner: T,
}

/// A primitive operation.
Expand Down
8 changes: 6 additions & 2 deletions compiler/src/passes/validate/type_check/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ use thiserror::Error;

#[derive(Debug, Error, Diagnostic)]
pub enum TypeError {
#[error("Variable '{sym}' was not declared yet.")]
UndeclaredVar { sym: String },
#[error("Encountered an undeclared variable.")]
UndeclaredVar {
sym: String,
#[label = "This variable `{sym}` was not declared yet"]
span: (usize, usize),
},
#[error("Types were mismatched. Expected '{expect}', but found '{got}'.")]
TypeMismatchExpect {
expect: Type<String>,
Expand Down
26 changes: 17 additions & 9 deletions compiler/src/passes/validate/type_check/validate_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,22 @@ use crate::passes::validate::type_check::{expect_type, expect_type_eq, Env, EnvE
use crate::passes::validate::{TExpr, TLit};
use crate::utils::expect::expect;

macro_rules! s {
($span:expr) => {
($span.0, $span.1 - $span.0)
};
}

pub fn validate_expr<'p>(
expr: Spanned<Expr<'p>>,
env: &mut Env<'_, 'p>,
) -> Result<TExpr<'p, &'p str>, TypeError> {
let span = (expr.span.0, expr.span.1 - expr.span.0);

Ok(match expr.expr {
Ok(match expr.inner {
Expr::Lit { val } => match val {
Lit::Int { val } => {
let val = val.parse().map_err(|_| IntegerOutOfBounds { span })?;
let val = val.parse().map_err(|_| IntegerOutOfBounds {
span: s!(expr.span),
})?;
TExpr::Lit {
val: TLit::Int { val },
typ: Type::Int,
Expand All @@ -35,6 +41,7 @@ pub fn validate_expr<'p>(
Expr::Var { sym, .. } => {
let entry = env.scope.get(&sym).ok_or(UndeclaredVar {
sym: (*sym).to_string(),
span: s!(expr.span),
})?;

if let EnvEntry::Type { typ, .. } = entry {
Expand Down Expand Up @@ -160,26 +167,27 @@ pub fn validate_expr<'p>(
}
}
Expr::Assign { sym, bnd, .. } => {
let entry = env.scope.get(&sym).ok_or(UndeclaredVar {
sym: (*sym).to_string(),
let entry = env.scope.get(&sym.inner).ok_or(UndeclaredVar {
sym: (*sym.inner).to_string(),
span: s!(sym.span),
})?;

let EnvEntry::Type { typ: _, mutable } = entry else {
return Err(VariableShouldBeExpr {
sym: (*sym).to_string(),
sym: (*sym.inner).to_string(),
});
};

expect(
*mutable,
ModifyImmutable {
sym: (*sym).to_string(),
sym: (*sym.inner).to_string(),
},
)?;

let bnd = validate_expr(*bnd, env)?;
TExpr::Assign {
sym,
sym: sym.inner,
bnd: Box::new(bnd),
typ: Type::Unit,
}
Expand Down
1 change: 1 addition & 0 deletions compiler/src/passes/validate/type_check/validate_struct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ pub fn validate_struct<'p>(
) -> Result<TExpr<'p, &'p str>, TypeError> {
let entry = env.scope.get(&sym).ok_or(UndeclaredVar {
sym: sym.to_string(),
span: (0, 0), // todo: not correct
})?;

#[rustfmt::skip]
Expand Down
1 change: 1 addition & 0 deletions compiler/src/passes/validate/type_check/validate_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub fn validate_type<'p>(
scope.contains(sym),
UndeclaredVar {
sym: sym.to_string(),
span: (0, 0), // todo: not correct
},
)?;
}
Expand Down
3 changes: 3 additions & 0 deletions programs/fail/type_check/undeclared_var.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
x
}
3 changes: 3 additions & 0 deletions programs/fail/type_check/undeclared_var_assign.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
x = 2
}

0 comments on commit f45a6c7

Please sign in to comment.