further changes to the visitor pattern to clean up code

This commit is contained in:
gluax 2022-05-30 10:53:06 -07:00
parent 044b2a10a4
commit 2db204b81e
7 changed files with 142 additions and 168 deletions

View File

@ -29,68 +29,77 @@ pub trait VisitorDirector<'a> {
}
pub trait ExpressionVisitorDirector<'a>: VisitorDirector<'a> {
type AdditionalInput: Default;
type Output;
fn visit_expression(&mut self, input: &'a Expression) -> Option<Self::Output> {
fn visit_expression(&mut self, input: &'a Expression, additional: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor_ref().visit_expression(input) {
match input {
Expression::Identifier(expr) => self.visit_identifier(expr),
Expression::Value(expr) => self.visit_value(expr),
Expression::Binary(expr) => self.visit_binary(expr),
Expression::Unary(expr) => self.visit_unary(expr),
Expression::Ternary(expr) => self.visit_ternary(expr),
Expression::Call(expr) => self.visit_call(expr),
Expression::Err(expr) => self.visit_err(expr),
Expression::Identifier(expr) => self.visit_identifier(expr, additional),
Expression::Value(expr) => self.visit_value(expr, additional),
Expression::Binary(expr) => self.visit_binary(expr, additional),
Expression::Unary(expr) => self.visit_unary(expr, additional),
Expression::Ternary(expr) => self.visit_ternary(expr, additional),
Expression::Call(expr) => self.visit_call(expr, additional),
Expression::Err(expr) => self.visit_err(expr, additional),
};
}
None
}
fn visit_identifier(&mut self, input: &'a Identifier) -> Option<Self::Output> {
fn visit_identifier(&mut self, input: &'a Identifier, _additional: &Self::AdditionalInput) -> Option<Self::Output> {
self.visitor_ref().visit_identifier(input);
None
}
fn visit_value(&mut self, input: &'a ValueExpression) -> Option<Self::Output> {
fn visit_value(&mut self, input: &'a ValueExpression, _additional: &Self::AdditionalInput) -> Option<Self::Output> {
self.visitor_ref().visit_value(input);
None
}
fn visit_binary(&mut self, input: &'a BinaryExpression) -> Option<Self::Output> {
fn visit_binary(
&mut self,
input: &'a BinaryExpression,
additional: &Self::AdditionalInput,
) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor_ref().visit_binary(input) {
self.visit_expression(&input.left);
self.visit_expression(&input.right);
self.visit_expression(&input.left, additional);
self.visit_expression(&input.right, additional);
}
None
}
fn visit_unary(&mut self, input: &'a UnaryExpression) -> Option<Self::Output> {
fn visit_unary(&mut self, input: &'a UnaryExpression, additional: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor_ref().visit_unary(input) {
self.visit_expression(&input.inner);
self.visit_expression(&input.inner, additional);
}
None
}
fn visit_ternary(&mut self, input: &'a TernaryExpression) -> Option<Self::Output> {
fn visit_ternary(
&mut self,
input: &'a TernaryExpression,
additional: &Self::AdditionalInput,
) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor_ref().visit_ternary(input) {
self.visit_expression(&input.condition);
self.visit_expression(&input.if_true);
self.visit_expression(&input.if_false);
self.visit_expression(&input.condition, additional);
self.visit_expression(&input.if_true, additional);
self.visit_expression(&input.if_false, additional);
}
None
}
fn visit_call(&mut self, input: &'a CallExpression) -> Option<Self::Output> {
fn visit_call(&mut self, input: &'a CallExpression, additional: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor_ref().visit_call(input) {
input.arguments.iter().for_each(|expr| {
self.visit_expression(expr);
self.visit_expression(expr, additional);
});
}
None
}
fn visit_err(&mut self, input: &'a ErrExpression) -> Option<Self::Output> {
fn visit_err(&mut self, input: &'a ErrExpression, _additional: &Self::AdditionalInput) -> Option<Self::Output> {
self.visitor_ref().visit_err(input);
None
}
@ -113,25 +122,25 @@ pub trait StatementVisitorDirector<'a>: VisitorDirector<'a> + ExpressionVisitorD
fn visit_return(&mut self, input: &'a ReturnStatement) {
if let VisitResult::VisitChildren = self.visitor_ref().visit_return(input) {
self.visit_expression(&input.expression);
self.visit_expression(&input.expression, &Default::default());
}
}
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
if let VisitResult::VisitChildren = self.visitor_ref().visit_definition(input) {
self.visit_expression(&input.value);
self.visit_expression(&input.value, &Default::default());
}
}
fn visit_assign(&mut self, input: &'a AssignStatement) {
if let VisitResult::VisitChildren = self.visitor_ref().visit_assign(input) {
self.visit_expression(&input.value);
self.visit_expression(&input.value, &Default::default());
}
}
fn visit_conditional(&mut self, input: &'a ConditionalStatement) {
if let VisitResult::VisitChildren = self.visitor_ref().visit_conditional(input) {
self.visit_expression(&input.condition);
self.visit_expression(&input.condition, &Default::default());
self.visit_block(&input.block);
if let Some(stmt) = input.next.as_ref() {
self.visit_statement(stmt);
@ -141,8 +150,8 @@ pub trait StatementVisitorDirector<'a>: VisitorDirector<'a> + ExpressionVisitorD
fn visit_iteration(&mut self, input: &'a IterationStatement) {
if let VisitResult::VisitChildren = self.visitor_ref().visit_iteration(input) {
self.visit_expression(&input.start);
self.visit_expression(&input.stop);
self.visit_expression(&input.start, &Default::default());
self.visit_expression(&input.stop, &Default::default());
self.visit_block(&input.block);
}
}
@ -150,10 +159,10 @@ pub trait StatementVisitorDirector<'a>: VisitorDirector<'a> + ExpressionVisitorD
fn visit_console(&mut self, input: &'a ConsoleStatement) {
if let VisitResult::VisitChildren = self.visitor_ref().visit_console(input) {
match &input.function {
ConsoleFunction::Assert(expr) => self.visit_expression(expr),
ConsoleFunction::Assert(expr) => self.visit_expression(expr, &Default::default()),
ConsoleFunction::Error(fmt) | ConsoleFunction::Log(fmt) => {
fmt.parameters.iter().for_each(|expr| {
self.visit_expression(expr);
self.visit_expression(expr, &Default::default());
});
None
}

View File

@ -44,6 +44,7 @@ impl<'a> VisitorDirector<'a> for Director<'a> {
}
impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
type AdditionalInput = ();
type Output = ();
}

View File

@ -23,12 +23,12 @@ use super::director::Director;
impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {}
fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: Option<Type>) -> Option<Type> {
fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: &Option<Type>) -> Option<Type> {
match (t1, t2) {
(Some(t1), Some(t2)) if t1 == t2 => Some(t1),
(Some(t1), Some(t2)) => {
if let Some(expected) = expected {
if t1 != expected {
if &t1 != expected {
Some(t1)
} else {
Some(t2)
@ -42,28 +42,29 @@ fn return_incorrect_type(t1: Option<Type>, t2: Option<Type>, expected: Option<Ty
}
impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
type AdditionalInput = Option<Type>;
type Output = Type;
fn visit_expression(&mut self, input: &'a Expression) -> Option<Self::Output> {
fn visit_expression(&mut self, input: &'a Expression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor.visit_expression(input) {
return match input {
Expression::Identifier(expr) => self.visit_identifier(expr),
Expression::Value(expr) => self.visit_value(expr),
Expression::Binary(expr) => self.visit_binary(expr),
Expression::Unary(expr) => self.visit_unary(expr),
Expression::Ternary(expr) => self.visit_ternary(expr),
Expression::Call(expr) => self.visit_call(expr),
Expression::Err(expr) => self.visit_err(expr),
Expression::Identifier(expr) => self.visit_identifier(expr, expected),
Expression::Value(expr) => self.visit_value(expr, expected),
Expression::Binary(expr) => self.visit_binary(expr, expected),
Expression::Unary(expr) => self.visit_unary(expr, expected),
Expression::Ternary(expr) => self.visit_ternary(expr, expected),
Expression::Call(expr) => self.visit_call(expr, expected),
Expression::Err(expr) => self.visit_err(expr, expected),
};
}
None
}
fn visit_identifier(&mut self, input: &'a Identifier) -> Option<Self::Output> {
fn visit_identifier(&mut self, input: &'a Identifier, expected: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor.visit_identifier(input) {
return if let Some(var) = self.visitor.symbol_table.clone().lookup_variable(&input.name) {
Some(self.visitor.assert_type(*var.type_, self.visitor.expected_type))
Some(self.visitor.assert_type(*var.type_, expected, var.span))
} else {
self.visitor
.handler
@ -75,12 +76,12 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
None
}
fn visit_value(&mut self, input: &'a ValueExpression) -> Option<Self::Output> {
fn visit_value(&mut self, input: &'a ValueExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor.visit_value(input) {
return Some(match input {
ValueExpression::Address(_, _) => self.visitor.assert_type(Type::Address, self.visitor.expected_type),
ValueExpression::Boolean(_, _) => self.visitor.assert_type(Type::Boolean, self.visitor.expected_type),
ValueExpression::Field(_, _) => self.visitor.assert_type(Type::Field, self.visitor.expected_type),
ValueExpression::Address(_, _) => self.visitor.assert_type(Type::Address, expected, input.span()),
ValueExpression::Boolean(_, _) => self.visitor.assert_type(Type::Boolean, expected, input.span()),
ValueExpression::Field(_, _) => self.visitor.assert_type(Type::Field, expected, input.span()),
ValueExpression::Integer(type_, str_content, _) => {
match type_ {
IntegerType::I8 => {
@ -171,10 +172,10 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
_ => {}
}
self.visitor
.assert_type(Type::IntegerType(*type_), self.visitor.expected_type)
.assert_type(Type::IntegerType(*type_), expected, input.span())
}
ValueExpression::Group(_) => self.visitor.assert_type(Type::Group, self.visitor.expected_type),
ValueExpression::Scalar(_, _) => self.visitor.assert_type(Type::Scalar, self.visitor.expected_type),
ValueExpression::Group(_) => self.visitor.assert_type(Type::Group, expected, input.span()),
ValueExpression::Scalar(_, _) => self.visitor.assert_type(Type::Scalar, expected, input.span()),
ValueExpression::String(_, _) => unreachable!("String types are not reachable"),
});
}
@ -182,80 +183,73 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
None
}
fn visit_binary(&mut self, input: &'a BinaryExpression) -> Option<Self::Output> {
fn visit_binary(&mut self, input: &'a BinaryExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor.visit_binary(input) {
return match input.op {
BinaryOperation::And | BinaryOperation::Or => {
self.visitor.assert_type(Type::Boolean, self.visitor.expected_type);
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
self.visitor.assert_type(Type::Boolean, expected, input.span());
let t1 = self.visit_expression(&input.left, expected);
let t2 = self.visit_expression(&input.right, expected);
return_incorrect_type(t1, t2, self.visitor.expected_type)
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Add => {
self.visitor
.assert_field_group_scalar_int_type(self.visitor.expected_type, input.span());
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
self.visitor.assert_field_group_scalar_int_type(expected, input.span());
let t1 = self.visit_expression(&input.left, expected);
let t2 = self.visit_expression(&input.right, expected);
return_incorrect_type(t1, t2, self.visitor.expected_type)
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Sub => {
self.visitor
.assert_field_group_int_type(self.visitor.expected_type, input.span());
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
self.visitor.assert_field_group_int_type(expected, input.span());
let t1 = self.visit_expression(&input.left, expected);
let t2 = self.visit_expression(&input.right, expected);
return_incorrect_type(t1, t2, self.visitor.expected_type)
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Mul => {
self.visitor
.assert_field_group_int_type(self.visitor.expected_type, input.span());
self.visitor.assert_field_group_int_type(expected, input.span());
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = None;
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
self.visitor.expected_type = prev_expected_type;
let t1 = self.visit_expression(&input.left, &None);
let t2 = self.visit_expression(&input.right, &None);
// Allow `group` * `scalar` multiplication.
match (t1.as_ref(), t2.as_ref()) {
(Some(Type::Group), Some(other))
| (Some(other), Some(Type::Group)) => {
self.visitor.assert_type(Type::Group, self.visitor.expected_type);
self.visitor.assert_type(*other, Some(Type::Scalar));
(Some(Type::Group), Some(other)) => {
self.visitor.assert_type(Type::Group, expected, input.left.span());
self.visitor
.assert_type(*other, &Some(Type::Scalar), input.right.span());
Some(Type::Group)
}
(Some(other), Some(Type::Group)) => {
self.visitor.assert_type(*other, &Some(Type::Scalar), input.left.span());
self.visitor.assert_type(Type::Group, expected, input.right.span());
Some(Type::Group)
}
_ => {
self.visitor.assert_type(t1.unwrap(), self.visitor.expected_type);
self.visitor.assert_type(t2.unwrap(), self.visitor.expected_type);
return_incorrect_type(t1, t2, self.visitor.expected_type)
self.visitor.assert_type(t1.unwrap(), expected, input.left.span());
self.visitor.assert_type(t2.unwrap(), expected, input.right.span());
return_incorrect_type(t1, t2, expected)
}
}
}
BinaryOperation::Div => {
self.visitor
.assert_field_int_type(self.visitor.expected_type, input.span());
self.visitor.assert_field_int_type(expected, input.span());
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
let t1 = self.visit_expression(&input.left, expected);
let t2 = self.visit_expression(&input.right, expected);
return_incorrect_type(t1, t2, self.visitor.expected_type)
return_incorrect_type(t1, t2, expected)
}
BinaryOperation::Pow => {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = None;
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
self.visitor.expected_type = prev_expected_type;
let t1 = self.visit_expression(&input.left, &None);
let t2 = self.visit_expression(&input.right, &None);
match (t1.as_ref(), t2.as_ref()) {
// Type A must be an int.
// Type B must be a unsigned int.
(Some(Type::IntegerType(_)), Some(Type::IntegerType(itype))) if !itype.is_signed() => {
self.visitor.assert_type(t1.unwrap(), self.visitor.expected_type);
self.visitor.assert_type(t1.unwrap(), expected, input.left.span());
}
// Type A was an int.
// But Type B was not a unsigned int.
@ -268,7 +262,7 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
// Type A must be a field.
// Type B must be an int.
(Some(Type::Field), Some(Type::IntegerType(_))) => {
self.visitor.assert_type(Type::Field, self.visitor.expected_type);
self.visitor.assert_type(Type::Field, expected, input.left.span());
}
// Type A was a field.
// But Type B was not an int.
@ -289,28 +283,20 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
t1
}
BinaryOperation::Eq | BinaryOperation::Ne => {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = None;
let t1 = self.visit_expression(&input.left, &None);
let t2 = self.visit_expression(&input.right, &None);
let t1 = self.visit_expression(&input.left);
let t2 = self.visit_expression(&input.right);
self.visitor.expected_type = prev_expected_type;
self.visitor.assert_eq_types(t1, t2, input.span());
Some(Type::Boolean)
}
BinaryOperation::Lt | BinaryOperation::Gt | BinaryOperation::Le | BinaryOperation::Ge => {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = None;
let t1 = self.visit_expression(&input.left, &None);
self.visitor.assert_field_scalar_int_type(&t1, input.left.span());
let t1 = self.visit_expression(&input.left);
self.visitor.assert_field_scalar_int_type(t1, input.left.span());
let t2 = self.visit_expression(&input.right, &None);
self.visitor.assert_field_scalar_int_type(&t2, input.right.span());
let t2 = self.visit_expression(&input.right);
self.visitor.assert_field_scalar_int_type(t2, input.right.span());
self.visitor.expected_type = prev_expected_type;
self.visitor.assert_eq_types(t1, t2, input.span());
Some(Type::Boolean)
@ -321,17 +307,17 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
None
}
fn visit_unary(&mut self, input: &'a UnaryExpression) -> Option<Self::Output> {
fn visit_unary(&mut self, input: &'a UnaryExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
match input.op {
UnaryOperation::Not => {
self.visitor.assert_type(Type::Boolean, self.visitor.expected_type);
self.visit_expression(&input.inner)
self.visitor.assert_type(Type::Boolean, expected, input.span());
self.visit_expression(&input.inner, expected)
}
UnaryOperation::Negate => {
let prior_negate_state = self.visitor.negate;
self.visitor.negate = true;
let type_ = self.visit_expression(&input.inner);
let type_ = self.visit_expression(&input.inner, expected);
self.visitor.negate = prior_negate_state;
match type_.as_ref() {
Some(
@ -356,27 +342,28 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
}
}
fn visit_ternary(&mut self, input: &'a TernaryExpression) -> Option<Self::Output> {
fn visit_ternary(
&mut self,
input: &'a TernaryExpression,
expected: &Self::AdditionalInput,
) -> Option<Self::Output> {
if let VisitResult::VisitChildren = self.visitor.visit_ternary(input) {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = Some(Type::Boolean);
self.visit_expression(&input.condition);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(&input.condition, &Some(Type::Boolean));
let t1 = self.visit_expression(&input.if_true);
let t2 = self.visit_expression(&input.if_false);
let t1 = self.visit_expression(&input.if_true, expected);
let t2 = self.visit_expression(&input.if_false, expected);
return return_incorrect_type(t1, t2, self.visitor.expected_type);
return return_incorrect_type(t1, t2, expected);
}
None
}
fn visit_call(&mut self, input: &'a CallExpression) -> Option<Self::Output> {
fn visit_call(&mut self, input: &'a CallExpression, expected: &Self::AdditionalInput) -> Option<Self::Output> {
match &*input.function {
Expression::Identifier(ident) => {
if let Some(func) = self.visitor.symbol_table.clone().lookup_fn(&ident.name) {
let ret = self.visitor.assert_type(func.output, self.visitor.expected_type);
let ret = self.visitor.assert_type(func.output, expected, func.span());
if func.input.len() != input.arguments.len() {
self.visitor.handler.emit_err(
@ -393,10 +380,7 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
.iter()
.zip(input.arguments.iter())
.for_each(|(expected, argument)| {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = Some(expected.get_variable().type_);
self.visit_expression(argument);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(argument, &Some(expected.get_variable().type_));
});
Some(ret)
@ -407,7 +391,7 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
None
}
}
expr => self.visit_expression(expr),
expr => self.visit_expression(expr, expected),
}
}
}

View File

@ -29,10 +29,10 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
// statements should always have some parent block
let parent = self.visitor.parent.unwrap();
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = self.visitor.symbol_table.lookup_fn(&parent).map(|f| f.output);
self.visit_expression(&input.expression);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(
&input.expression,
&self.visitor.symbol_table.lookup_fn(&parent).map(|f| f.output),
);
}
fn visit_definition(&mut self, input: &'a DefinitionStatement) {
@ -54,10 +54,7 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
self.visitor.handler.emit_err(err);
}
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = Some(input.type_);
self.visit_expression(&input.value);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(&input.value, &Some(input.type_));
});
}
@ -86,18 +83,12 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
};
if var_type.is_some() {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = var_type;
self.visit_expression(&input.value);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(&input.value, &var_type);
}
}
fn visit_conditional(&mut self, input: &'a ConditionalStatement) {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = Some(Type::Boolean);
self.visit_expression(&input.condition);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(&input.condition, &Some(Type::Boolean));
}
fn visit_iteration(&mut self, input: &'a IterationStatement) {
@ -112,21 +103,14 @@ impl<'a> StatementVisitorDirector<'a> for Director<'a> {
self.visitor.handler.emit_err(err);
}
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = Some(input.type_);
self.visit_expression(&input.start);
self.visit_expression(&input.stop);
self.visitor.expected_type = prev_expected_type;
self.visit_expression(&input.start, &Some(input.type_));
self.visit_expression(&input.stop, &Some(input.type_));
}
fn visit_console(&mut self, input: &'a ConsoleStatement) {
match &input.function {
ConsoleFunction::Assert(expr) => {
let prev_expected_type = self.visitor.expected_type;
self.visitor.expected_type = Some(Type::Boolean);
self.visit_expression(expr);
self.visitor.expected_type = prev_expected_type;
// self.compare_expr_type(expr, Some(Type::Boolean), expr.span());
self.visit_expression(expr, &Some(Type::Boolean));
}
ConsoleFunction::Error(_) | ConsoleFunction::Log(_) => {
// TODO: undetermined

View File

@ -25,8 +25,6 @@ pub struct TypeChecker<'a> {
pub(crate) handler: &'a Handler,
pub(crate) parent: Option<Symbol>,
pub(crate) negate: bool,
pub(crate) expected_type: Option<Type>,
pub(crate) span: Span,
}
const INT_TYPES: [Type; 10] = [
@ -76,8 +74,6 @@ impl<'a> TypeChecker<'a> {
handler,
parent: None,
negate: false,
expected_type: None,
span: Default::default(),
}
}
@ -95,11 +91,11 @@ impl<'a> TypeChecker<'a> {
}
/// Returns the given type if it equals the expected type or the expected type is none.
pub(crate) fn assert_type(&mut self, type_: Type, expected: Option<Type>) -> Type {
pub(crate) fn assert_type(&mut self, type_: Type, expected: &Option<Type>, span: Span) -> Type {
if let Some(expected) = expected {
if type_ != expected {
if &type_ != expected {
self.handler
.emit_err(TypeCheckerError::type_should_be(type_, expected, self.span).into());
.emit_err(TypeCheckerError::type_should_be(type_, expected, span).into());
}
}
@ -107,9 +103,9 @@ impl<'a> TypeChecker<'a> {
}
/// Emits an error to the error handler if the given type is not equal to any of the expected types.
pub(crate) fn assert_one_of_types(&self, type_: Option<Type>, expected: &[Type], span: Span) {
pub(crate) fn assert_one_of_types(&self, type_: &Option<Type>, expected: &[Type], span: Span) {
if let Some(type_) = type_ {
if !expected.iter().any(|t: &Type| t == &type_) {
if !expected.iter().any(|t: &Type| t == type_) {
self.handler.emit_err(
TypeCheckerError::expected_one_type_of(
expected.iter().map(|t| t.to_string() + ",").collect::<String>(),
@ -123,22 +119,22 @@ impl<'a> TypeChecker<'a> {
}
/// Emits an error to the handler if the given type is not a field or integer.
pub(crate) fn assert_field_int_type(&self, type_: Option<Type>, span: Span) {
pub(crate) fn assert_field_int_type(&self, type_: &Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_INT_TYPES, span)
}
/// Emits an error to the handler if the given type is not a field, scalar, or integer.
pub(crate) fn assert_field_scalar_int_type(&self, type_: Option<Type>, span: Span) {
pub(crate) fn assert_field_scalar_int_type(&self, type_: &Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_SCALAR_INT_TYPES, span)
}
/// Emits an error to the handler if the given type is not a field, group, or integer.
pub(crate) fn assert_field_group_int_type(&self, type_: Option<Type>, span: Span) {
pub(crate) fn assert_field_group_int_type(&self, type_: &Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_GROUP_INT_TYPES, span)
}
/// Emits an error to the handler if the given type is not a field, group, scalar or integer.
pub(crate) fn assert_field_group_scalar_int_type(&self, type_: Option<Type>, span: Span) {
pub(crate) fn assert_field_group_scalar_int_type(&self, type_: &Option<Type>, span: Span) {
self.assert_one_of_types(type_, &FIELD_GROUP_SCALAR_INT_TYPES, span)
}
}

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:1:1\n |\n 1 | \n | \n"
- "Error [ETYC0372002]: Found type `group` but type `scalar` was expected\n --> compiler-test:4:26\n |\n 4 | return (_, _)group * a;\n | ^\n"

View File

@ -2,4 +2,4 @@
namespace: Compile
expectation: Fail
outputs:
- "Error [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:4:19\n |\n 4 | let b: bool = a == 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:5:19\n |\n 5 | let c: bool = a != 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:6:19\n |\n 6 | let d: bool = a > 1u8;\n | ^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:7:19\n |\n 7 | let e: bool = a < 1u8;\n | ^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:8:19\n |\n 8 | let f: bool = a >= 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:9:19\n |\n 9 | let g: bool = a <= 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u32` was expected\n --> compiler-test:1:1\n |\n 1 | \n | \nError [ETYC0372002]: Found type `u8` but type `u32` was expected\n --> compiler-test:1:1\n |\n 1 | \n | \n"
- "Error [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:4:19\n |\n 4 | let b: bool = a == 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:5:19\n |\n 5 | let c: bool = a != 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:6:19\n |\n 6 | let d: bool = a > 1u8;\n | ^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:7:19\n |\n 7 | let e: bool = a < 1u8;\n | ^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:8:19\n |\n 8 | let f: bool = a >= 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u8` was expected\n --> compiler-test:9:19\n |\n 9 | let g: bool = a <= 1u8;\n | ^^^^^^^^\nError [ETYC0372002]: Found type `i8` but type `u32` was expected\n --> compiler-test:10:18\n |\n 10 | let h: u32 = a * 1u8;\n | ^\nError [ETYC0372002]: Found type `u8` but type `u32` was expected\n --> compiler-test:10:22\n |\n 10 | let h: u32 = a * 1u8;\n | ^^^\n"