1
1
Fork 0
mirror of https://github.com/azur1s/bobbylisp.git synced 2024-10-16 02:37:40 -05:00

simple typechecking

This commit is contained in:
Natapat Samutpong 2022-03-24 07:07:24 +07:00
parent 74adfe1f0f
commit ea90b7f90a
3 changed files with 104 additions and 7 deletions

View file

@ -63,14 +63,19 @@ fn main() {
// Typecheck the HIR
match check(&ir) {
Ok(_) => {},
Err(err) => {
diagnostics.add_typecheck_error(err);
Ok(_) => {
logif!(0, format!("Typechecking took {}ms", start.elapsed().as_millis()));
},
Err(errs) => {
for err in errs {
diagnostics.add_typecheck_error(err);
}
diagnostics.display(src);
logif!(0, "Typechecking failed");
logif!(2, "Typechecking failed");
std::process::exit(1);
}
}
dbg!(check(&ir));
// Report lowering errors if any
if diagnostics.has_error() {

View file

@ -1,4 +1,4 @@
use hir::{IR, IRKind};
use hir::{IR, IRKind, Value};
#[derive(Debug)]
pub enum TypecheckErrorKind {
@ -29,6 +29,95 @@ pub struct TypecheckError {
pub span: std::ops::Range<usize>,
}
pub fn check(ir: &Vec<IR>) -> Result<(), TypecheckError> {
todo!();
pub fn check(irs: &Vec<IR>) -> Result<(), Vec<TypecheckError>> {
let mut errors = Vec::new();
for ir in irs {
match &ir.kind {
ir @ IRKind::Define { .. } => {
match check_define(&ir) {
Ok(()) => (),
Err(e) => errors.push(e),
}
}
_ => {}
}
}
if errors.is_empty() { Ok(()) }
else { Err(errors) }
}
#[macro_export]
macro_rules! return_err {
($kind:expr, $span:expr) => {{
return Err(TypecheckError {
kind: $kind,
span: $span.clone()
});
}};
}
/// Check the types of the definitions.
/// This is done by checking the type of the value against the type hint.
///
/// # Examples
/// ```sml
/// let x: int = 1; -- Correct
///
/// let x: string = 1; -- Incorrect
/// ```
fn check_define(ir: &IRKind) -> Result<(), TypecheckError> {
match ir {
IRKind::Define {
type_hint,
value,
span,
..
} => {
match &**value {
IRKind::Value { value } => {
match value {
Value::Int(_) => {
if type_hint != "number" {
return_err!(
TypecheckErrorKind::DefinitionTypeMismatch {
type_specified: type_hint.to_string(),
type_found: "number".to_string(),
},
span.clone()
);
}
}
Value::String(_) => {
if type_hint != "string" {
return_err!(
TypecheckErrorKind::DefinitionTypeMismatch {
type_specified: type_hint.to_string(),
type_found: "string".to_string(),
},
span.clone()
);
}
}
Value::Boolean(_) => {
if type_hint != "boolean" {
return_err!(
TypecheckErrorKind::DefinitionTypeMismatch {
type_specified: type_hint.to_string(),
type_found: "boolean".to_string(),
},
span.clone()
);
}
}
// TODO: other types
_ => {}
}
}
// TODO: other (right-hand side) IRKinds
_ => {}
}
}
_ => unreachable!()
}
Ok(())
}

View file

@ -0,0 +1,3 @@
let foo: int = "123";
let bar: string = 69;
let baz: bool = "true";