type checking errors so far

This commit is contained in:
gluax 2022-05-03 14:00:40 -07:00
parent 1a25db8e23
commit 4612602807
6 changed files with 146 additions and 11 deletions

View File

@ -14,6 +14,8 @@
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_errors::TypeCheckerError;
use super::*;
/// A binary operator.
@ -167,8 +169,10 @@ impl Node for BinaryExpression {
match (left, right) {
(Some(t1), Some(t2)) if t1 == t2 => Ok(Some(t1)),
(None, None) => Ok(None),
(Some(t1), Some(t2)) => todo!("throw err"),
(None, Some(t)) | (Some(t), None) => todo!("throw err"),
(Some(t1), Some(t2)) => Err(TypeCheckerError::types_do_not_match(t1, t2, self.span()).into()),
(None, Some(t)) | (Some(t), None) => {
Err(TypeCheckerError::type_expected_but_not_found(t, self.span()).into())
}
}
}
}

View File

@ -15,15 +15,20 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::*;
use leo_errors::Result;
use leo_errors::{Result, TypeCheckerError};
use leo_span::Span;
use crate::TypeChecker;
impl<'a> TypeChecker<'a> {
fn compare_types(&self, t1: Result<Option<Type>>, t2: Result<Option<Type>>) {
fn compare_types(&self, t1: Result<Option<Type>>, t2: Result<Option<Type>>, span: &Span) {
match (t1, t2) {
(Ok(Some(t1)), Ok(Some(t2))) if t1 != t2 => self.handler.emit_err(todo!()),
(Ok(Some(t)), Ok(None)) | (Ok(None), Ok(Some(t))) => self.handler.emit_err(todo!()),
(Ok(Some(t1)), Ok(Some(t2))) if t1 != t2 => self
.handler
.emit_err(TypeCheckerError::types_do_not_match(t1, t2, span).into()),
(Ok(Some(t)), Ok(None)) | (Ok(None), Ok(Some(t))) => self
.handler
.emit_err(TypeCheckerError::type_expected_but_not_found(t, span).into()),
(Err(err), Ok(None)) | (Ok(None), Err(err)) => self.handler.emit_err(err),
(Err(err1), Err(err2)) => {
self.handler.emit_err(err1);
@ -43,7 +48,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
let parent = self.parent.unwrap();
if let Some(func) = self.symbol_table.lookup_fn(&parent) {
self.compare_types(func.get_type(), input.get_type());
self.compare_types(func.get_type(), input.get_type(), input.span());
}
VisitResult::VisitChildren
@ -54,6 +59,8 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
if let Err(err) = self.symbol_table.insert_variable(v.identifier.name, input) {
self.handler.emit_err(err);
}
self.compare_types(input.get_type(), input.get_type(), input.span());
});
VisitResult::VisitChildren
@ -65,12 +72,33 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
match (input_var, var) {
(Some(var), None) => {
self.compare_types(var.get_type(), input.value.get_type());
let inner = var.get_variable();
if inner.mode() == ParamMode::Constant {
self.handler.emit_err(
TypeCheckerError::cannont_assign_to_const_input(&inner.identifier.name, var.span()).into(),
);
}
self.compare_types(var.get_type(), input.value.get_type(), input.span());
}
(None, Some(var)) => {
self.compare_types(var.get_type(), input.value.get_type());
if var.declaration_type == Declare::Const {
// there will always be one variable name
// as we don't allow tuples at the moment.
self.handler.emit_err(
TypeCheckerError::cannont_assign_to_const_input(
&var.variable_names[0].identifier.name,
var.span(),
)
.into(),
);
}
self.compare_types(var.get_type(), input.value.get_type(), input.span());
}
(None, None) => self.handler.emit_err(todo!()),
(None, None) => self
.handler
.emit_err(TypeCheckerError::unknown_assignee(&input.assignee.identifier.name, input.span()).into()),
// Don't have to error here as shadowing checks are done during insertions.
_ => {}
}

View File

@ -20,7 +20,7 @@ use std::fmt::{Debug, Display};
create_messages!(
/// InputError enum that represents all the errors for the inputs part of `leo-ast` crate.
InputError,
code_mask: 8000i32,
code_mask: 1000i32,
code_prefix: "INP",
/// For when declared variable type mismatches actual type.

View File

@ -41,6 +41,10 @@ pub use self::package::*;
pub mod parser;
pub use self::parser::*;
/// Contains the Type Checker error definitions.
pub mod type_checker;
pub use self::type_checker::*;
/// The LeoError type that contains all sub error types.
/// This allows a unified error type throughout the Leo crates.
#[derive(Clone, Debug, Error)]
@ -63,6 +67,9 @@ pub enum LeoError {
/// Represents an Parser Error in a Leo Error.
#[error(transparent)]
ParserError(#[from] ParserError),
/// Represents an Type Checker Error in a Leo Error.
#[error(transparent)]
TypeCheckerError(#[from] TypeCheckerError),
}
impl LeoError {
@ -77,6 +84,7 @@ impl LeoError {
InputError(error) => error.error_code(),
ParserError(error) => error.error_code(),
PackageError(error) => error.error_code(),
TypeCheckerError(error) => error.error_code(),
}
}
@ -91,6 +99,7 @@ impl LeoError {
InputError(error) => error.exit_code(),
ParserError(error) => error.exit_code(),
PackageError(error) => error.exit_code(),
TypeCheckerError(error) => error.exit_code(),
}
}
}

View File

@ -0,0 +1,19 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
/// This module contains the Input error definitions.
pub mod type_checker_error;
pub use self::type_checker_error::*;

View File

@ -0,0 +1,75 @@
// Copyright (C) 2019-2022 Aleo Systems Inc.
// This file is part of the Leo library.
// The Leo library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// The Leo library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::create_messages;
use std::fmt::{Debug, Display};
create_messages!(
/// InputError enum that represents all the errors for the inputs part of `leo-ast` crate.
TypeCheckerError,
code_mask: 2000i32,
code_prefix: "TYC",
/// For when types do not match.
@formatted
types_do_not_match {
args: (lhs: impl Display, rhs: impl Display),
msg: format!(
"unexpected type, lhs type is: '{lhs}', but rhs type is: '{rhs}'",
),
help: None,
}
/// For when types do not match.
@formatted
type_expected_but_not_found {
args: (known: impl Display),
msg: format!(
"One side has type: '{known}', but the other has no type",
),
help: None,
}
/// For when the user tries to assign to a unknown variable.
@formatted
unknown_assignee {
args: (var: impl Display),
msg: format!(
"Unknown assignee `{var}`",
),
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
cannont_assign_to_const_input {
args: (input: impl Display),
msg: format!(
"Cannot assign to const input `{input}`",
),
help: None,
}
/// For when the user tries to assign to a const input.
@formatted
cannont_assign_to_const_var {
args: (var: impl Display),
msg: format!(
"Cannot assign to const variable `{var}`",
),
help: None,
}
);