expressions so far, and clean up, need to appropiately handle binary exprs

This commit is contained in:
gluax 2022-05-04 09:27:00 -07:00
parent 5cb4a5d8c0
commit 9c8ac64871
30 changed files with 241 additions and 305 deletions

View File

@ -51,10 +51,6 @@ impl Node for Identifier {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}
impl Identifier {

View File

@ -14,8 +14,6 @@
// 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.
@ -158,23 +156,4 @@ impl Node for BinaryExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
match self.op.class() {
BinaryOperationClass::Boolean => Ok(Some(Type::Boolean)),
BinaryOperationClass::Numeric => {
let left = self.left.get_type()?;
let right = self.right.get_type()?;
match (left, right) {
(Some(t1), Some(t2)) if t1 == t2 => Ok(Some(t1)),
(None, None) => Ok(None),
(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

@ -49,8 +49,4 @@ impl Node for CallExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -37,8 +37,4 @@ impl Node for ErrExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -14,8 +14,7 @@
// 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::{GroupValue, Identifier, IntegerType, Node, Type};
use leo_errors::Result;
use crate::{GroupValue, Identifier, IntegerType, Node};
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -80,19 +79,6 @@ impl Node for Expression {
Err(n) => n.set_span(span),
}
}
fn get_type(&self) -> Result<Option<Type>> {
use Expression::*;
match self {
Identifier(n) => n.get_type(),
Value(n) => n.get_type(),
Binary(n) => n.get_type(),
Unary(n) => n.get_type(),
Ternary(n) => n.get_type(),
Call(n) => n.get_type(),
Err(n) => n.get_type(),
}
}
}
impl fmt::Display for Expression {

View File

@ -43,8 +43,4 @@ impl Node for TernaryExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -24,9 +24,6 @@ pub enum UnaryOperation {
Not,
/// The arithmetic negation operator, i.e., `-`.
Negate,
/// The bitwise negation operator, i.e., `~`.
/// For example, it transforms `1010` to `0101`.
BitNot,
}
impl AsRef<str> for UnaryOperation {
@ -34,7 +31,6 @@ impl AsRef<str> for UnaryOperation {
match self {
UnaryOperation::Not => "!",
UnaryOperation::Negate => "-",
UnaryOperation::BitNot => "~",
}
}
}
@ -64,8 +60,4 @@ impl Node for UnaryExpression {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.inner.get_type()
}
}

View File

@ -85,17 +85,4 @@ impl Node for ValueExpression {
},
}
}
fn get_type(&self) -> Result<Option<crate::Type>> {
use ValueExpression::*;
Ok(Some(match &self {
Address(_, _) => Type::Address,
Boolean(_, _) => Type::Boolean,
Char(_) => Type::Char,
Field(_, _) => Type::Field,
Integer(type_, _, _) => Type::IntegerType(*type_),
Group(_) => Type::Group,
String(_, _) => return Ok(None),
}))
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, FunctionInput, Identifier, Node, Type};
use leo_errors::Result;
use leo_span::{sym, Span, Symbol};
use serde::{Deserialize, Serialize};
@ -93,8 +92,4 @@ impl Node for Function {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.output.clone()))
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -96,8 +95,4 @@ impl Node for FunctionInputVariable {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.type_.clone()))
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{FunctionInputVariable, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -84,11 +83,4 @@ impl Node for FunctionInput {
Variable(variable) => variable.span = span,
}
}
fn get_type(&self) -> Result<Option<crate::Type>> {
use FunctionInput::*;
match self {
Variable(variable) => variable.get_type(),
}
}
}

View File

@ -14,11 +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::Result;
use leo_span::Span;
use crate::Type;
/// A node in the AST.
pub trait Node:
std::fmt::Debug + std::fmt::Display + Clone + PartialEq + Eq + serde::Serialize + serde::de::DeserializeOwned
@ -28,7 +25,4 @@ pub trait Node:
/// Sets the span of the node.
fn set_span(&mut self, span: Span);
/// Gets the type of the node if it exists.
fn get_type(&self) -> Result<Option<Type>>;
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -109,8 +108,4 @@ impl Node for AssignStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.value.get_type()
}
}

View File

@ -14,8 +14,7 @@
// 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::{Node, Statement, Type};
use leo_errors::Result;
use crate::{Node, Statement};
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -52,8 +51,4 @@ impl Node for Block {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(None)
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, Expression, Node, Statement};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -52,8 +51,4 @@ impl Node for ConditionalStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Char, Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -55,8 +54,4 @@ impl Node for ConsoleArgs {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ConsoleArgs, Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -59,8 +58,4 @@ impl Node for ConsoleFunction {
ConsoleFunction::Error(formatted) | ConsoleFunction::Log(formatted) => formatted.set_span(span),
}
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{ConsoleFunction, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -50,8 +49,4 @@ impl Node for ConsoleStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -73,8 +72,4 @@ impl Node for DefinitionStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.type_.clone()))
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Identifier, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -46,8 +45,4 @@ impl Node for VariableName {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
Ok(None)
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -44,8 +43,4 @@ impl Node for ExpressionStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.expression.get_type()
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Block, Expression, Identifier, Node, Type};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -60,8 +59,4 @@ impl Node for IterationStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<Type>> {
Ok(Some(self.type_.clone()))
}
}

View File

@ -15,7 +15,6 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use crate::{Expression, Node};
use leo_errors::Result;
use leo_span::Span;
use serde::{Deserialize, Serialize};
@ -44,8 +43,4 @@ impl Node for ReturnStatement {
fn set_span(&mut self, span: Span) {
self.span = span;
}
fn get_type(&self) -> Result<Option<crate::Type>> {
self.expression.get_type()
}
}

View File

@ -14,8 +14,7 @@
// 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::{ConditionalStatement, Node, Type};
use leo_errors::Result;
use crate::{ConditionalStatement, Node};
use leo_span::Span;
use super::*;
@ -87,18 +86,4 @@ impl Node for Statement {
Block(n) => n.set_span(span),
}
}
fn get_type(&self) -> Result<Option<Type>> {
use Statement::*;
match self {
Return(n) => n.get_type(),
Definition(n) => n.get_type(),
Assign(n) => n.get_type(),
Conditional(n) => n.get_type(),
Iteration(n) => n.get_type(),
Console(n) => n.get_type(),
Expression(n) => n.get_type(),
Block(n) => n.get_type(),
}
}
}

View File

@ -0,0 +1,129 @@
// 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 leo_ast::*;
use leo_errors::TypeCheckerError;
use leo_span::Span;
use crate::TypeChecker;
impl<'a> TypeChecker<'a> {
pub(crate) fn compare_expr_type(&self, expr: &Expression, expected: Type, span: &Span) {
match expr {
Expression::Identifier(ident) => {
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
self.assert_type(var.type_.clone(), expected, var.span);
} else {
self.handler
.emit_err(TypeCheckerError::unknown_sym("variable", ident.name, span).into());
}
}
Expression::Value(value) => match value {
ValueExpression::Address(_, _) => self.assert_type(Type::Address, expected, value.span()),
ValueExpression::Boolean(_, _) => self.assert_type(Type::Boolean, expected, value.span()),
ValueExpression::Char(_) => self.assert_type(Type::Char, expected, value.span()),
ValueExpression::Field(_, _) => self.assert_type(Type::Field, expected, value.span()),
ValueExpression::Integer(type_, _, _) => {
self.assert_type(Type::IntegerType(*type_), expected, value.span())
}
ValueExpression::Group(_) => self.assert_type(Type::Group, expected, value.span()),
ValueExpression::String(_, _) => {}
},
Expression::Binary(binary) => match binary.op.class() {
// some ops support more types than listed here
BinaryOperationClass::Boolean => {
self.assert_type(Type::Boolean, expected, span);
self.compare_expr_type(&binary.left, Type::Boolean, binary.span());
self.compare_expr_type(&binary.right, Type::Boolean, binary.span());
}
BinaryOperationClass::Numeric => {
// depending on operation could also be field or group
if !matches!(expected, Type::IntegerType(_)) {
self.handler
.emit_err(TypeCheckerError::type_should_be_integer(binary.op, expected.clone(), span).into());
}
self.compare_expr_type(&binary.left, expected.clone(), binary.span());
self.compare_expr_type(&binary.right, expected, binary.span());
}
},
Expression::Unary(unary) => match unary.op {
UnaryOperation::Not => {
self.assert_type(Type::Boolean, expected, unary.span());
self.compare_expr_type(&unary.inner, Type::Boolean, unary.inner.span());
}
UnaryOperation::Negate => {
match expected {
Type::IntegerType(
IntegerType::I8
| IntegerType::I16
| IntegerType::I32
| IntegerType::I64
| IntegerType::I128,
)
| Type::Field
| Type::Group => {}
_ => self.handler.emit_err(
TypeCheckerError::type_is_not_negatable(expected.clone(), unary.inner.span()).into(),
),
}
self.compare_expr_type(&unary.inner, expected, unary.inner.span());
}
},
Expression::Ternary(ternary) => {
self.compare_expr_type(&ternary.condition, Type::Boolean, ternary.condition.span());
self.compare_expr_type(&ternary.if_true, expected.clone(), ternary.if_true.span());
self.compare_expr_type(&ternary.if_false, expected, ternary.if_false.span());
}
Expression::Call(call) => match &*call.function {
Expression::Identifier(ident) => {
if let Some(func) = self.symbol_table.lookup_fn(&ident.name) {
self.assert_type(func.output.clone(), expected, ident.span());
if func.input.len() != call.arguments.len() {
self.handler.emit_err(
TypeCheckerError::incorrect_num_args_to_call(
func.input.len(),
call.arguments.len(),
call.span(),
)
.into(),
);
}
func.input
.iter()
.zip(call.arguments.iter())
.for_each(|(expected, argument)| {
self.compare_expr_type(
argument,
expected.get_variable().type_.clone(),
argument.span(),
);
});
} else {
self.handler
.emit_err(TypeCheckerError::unknown_sym("function", &ident.name, ident.span()).into());
}
}
expr => self.compare_expr_type(expr, expected, call.span()),
},
Expression::Err(_) => {}
}
}
}
impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {}

View File

@ -0,0 +1,42 @@
// 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 leo_ast::*;
use crate::{Declaration, TypeChecker, VariableSymbol};
impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_function(&mut self, input: &'a Function) -> VisitResult {
self.symbol_table.clear_variables();
self.parent = Some(input.name());
input.input.iter().for_each(|i| {
let input_var = i.get_variable();
if let Err(err) = self.symbol_table.insert_variable(
input_var.identifier.name,
VariableSymbol {
type_: &input_var.type_,
span: input_var.span(),
declaration: Declaration::Input(input_var.mode()),
},
) {
self.handler.emit_err(err);
}
});
VisitResult::VisitChildren
}
}

View File

@ -15,73 +15,10 @@
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
use leo_ast::*;
use leo_errors::{Result, TypeCheckerError};
use leo_span::Span;
use leo_errors::TypeCheckerError;
use crate::{Declaration, TypeChecker, VariableSymbol};
impl<'a> TypeChecker<'a> {
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(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);
self.handler.emit_err(err2);
}
// Types match
_ => {}
}
}
fn assert_type(&self, type_: Result<Option<Type>>, expected: Type, span: &Span) {
match type_ {
Ok(Some(type_)) if type_ != expected => self
.handler
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into()),
// Types match
_ => {}
}
}
fn compare_expr_type(&self, compare: Result<Option<Type>>, expr: &Expression, span: &Span) {
match expr {
Expression::Identifier(ident) => {
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
self.assert_type(compare, var.type_.clone(), span);
} else {
self.handler
.emit_err(TypeCheckerError::unknown_returnee(ident.name, span).into());
}
}
expr => self.compare_types(compare, expr.get_type(), span),
}
}
fn assert_expr_type(&self, expr: &Expression, expected: Type, span: &Span) {
match expr {
Expression::Identifier(ident) => {
if let Some(var) = self.symbol_table.lookup_variable(&ident.name) {
if var.type_ != &expected {
self.handler
.emit_err(TypeCheckerError::type_should_be(var.type_, expected, span).into());
}
} else {
self.handler
.emit_err(TypeCheckerError::unknown_returnee(ident.name, span).into());
}
}
expr => self.assert_type(expr.get_type(), expected, span),
}
}
}
impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {}
impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
fn visit_return(&mut self, input: &'a ReturnStatement) -> VisitResult {
@ -90,7 +27,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_expr_type(func.get_type(), &input.expression, input.span());
self.compare_expr_type(&input.expression, func.output.clone(), input.expression.span());
}
VisitResult::VisitChildren
@ -115,7 +52,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.handler.emit_err(err);
}
self.compare_types(input.get_type(), input.get_type(), input.span());
self.compare_expr_type(&input.value, input.type_.clone(), input.value.span());
});
VisitResult::VisitChildren
@ -134,17 +71,18 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
_ => {}
}
self.assert_expr_type(&input.value, var.type_.clone(), input.span())
self.compare_expr_type(&input.value, var.type_.clone(), input.value.span())
} else {
self.handler
.emit_err(TypeCheckerError::unknown_assignee(&input.assignee.identifier.name, input.span()).into())
self.handler.emit_err(
TypeCheckerError::unknown_sym("variable", &input.assignee.identifier.name, &input.assignee.span).into(),
)
}
VisitResult::VisitChildren
}
fn visit_conditional(&mut self, input: &'a ConditionalStatement) -> VisitResult {
self.assert_expr_type(&input.condition, Type::Boolean, input.span());
self.compare_expr_type(&input.condition, Type::Boolean, input.condition.span());
VisitResult::VisitChildren
}
@ -161,10 +99,8 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
self.handler.emit_err(err);
}
let iter_var_type = input.get_type();
self.compare_expr_type(iter_var_type.clone(), &input.start, input.span());
self.compare_expr_type(iter_var_type, &input.stop, input.span());
self.compare_expr_type(&input.start, input.type_.clone(), input.start.span());
self.compare_expr_type(&input.stop, input.type_.clone(), input.stop.span());
VisitResult::VisitChildren
}
@ -172,7 +108,7 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
fn visit_console(&mut self, input: &'a ConsoleStatement) -> VisitResult {
match &input.function {
ConsoleFunction::Assert(expr) => {
self.assert_expr_type(expr, Type::Boolean, expr.span());
self.compare_expr_type(expr, Type::Boolean, expr.span());
}
ConsoleFunction::Error(_) | ConsoleFunction::Log(_) => {
todo!("need to discuss this");
@ -182,6 +118,10 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
VisitResult::VisitChildren
}
fn visit_expression_statement(&mut self, _input: &'a ExpressionStatement) -> VisitResult {
VisitResult::SkipChildren
}
fn visit_block(&mut self, input: &'a Block) -> VisitResult {
self.symbol_table.push_variable_scope();
// have to redo the logic here so we have scoping
@ -202,26 +142,3 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
VisitResult::SkipChildren
}
}
impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_function(&mut self, input: &'a Function) -> VisitResult {
self.symbol_table.clear_variables();
self.parent = Some(input.name());
input.input.iter().for_each(|i| {
let input_var = i.get_variable();
if let Err(err) = self.symbol_table.insert_variable(
input_var.identifier.name,
VariableSymbol {
type_: &input_var.type_,
span: input_var.span(),
declaration: Declaration::Input(input_var.mode()),
},
) {
self.handler.emit_err(err);
}
});
VisitResult::VisitChildren
}
}

View File

@ -14,8 +14,9 @@
// 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::emitter::Handler;
use leo_span::Symbol;
use leo_ast::Type;
use leo_errors::{emitter::Handler, TypeCheckerError};
use leo_span::{Symbol, Span};
use crate::SymbolTable;
@ -33,4 +34,11 @@ impl<'a> TypeChecker<'a> {
parent: None,
}
}
pub(crate) fn assert_type(&self, type_: Type, expected: Type, span: &Span) {
if type_ != expected {
self.handler
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into());
}
}
}

View File

@ -14,8 +14,14 @@
// 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/>.
pub mod check;
pub use check::*;
pub mod check_expressions;
pub use check_expressions::*;
pub mod check_file;
pub use check_file::*;
pub mod check_statements;
pub use check_statements::*;
pub mod checker;
pub use checker::*;

View File

@ -23,36 +23,6 @@ create_messages!(
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 {
@ -85,10 +55,40 @@ create_messages!(
/// For when the user tries to return a unknown variable.
@formatted
unknown_returnee {
args: (var: impl Display),
unknown_sym {
args: (kind: impl Display, sym: impl Display),
msg: format!(
"Unknown returnee `{var}`",
"Unknown {kind} `{sym}`",
),
help: None,
}
/// For when the user tries to expect a non integer type .
@formatted
type_should_be_integer {
args: (op: impl Debug, type_: impl Display),
msg: format!(
"Binary statement has numeric operation `{op:?}` but has expected type `{type_}`",
),
help: None,
}
/// For when the user tries to negate a non negatable type.
@formatted
type_is_not_negatable {
args: (type_: impl Display),
msg: format!(
"The type `{type_}` is not negatable",
),
help: None,
}
/// For when the user tries calls a function with the incorrect number of args.
@formatted
incorrect_num_args_to_call {
args: (expected: impl Display, received: impl Display),
msg: format!(
"Call expected `{expected}` args, got `{received}`",
),
help: None,
}