fix type checking bugs

This commit is contained in:
collin 2022-06-26 15:13:58 -10:00
parent 21c6a2167a
commit df8ee1a1f9
5 changed files with 22 additions and 40 deletions

View File

@ -60,7 +60,7 @@ impl Type {
| (Type::Scalar, Type::Scalar) | (Type::Scalar, Type::Scalar)
| (Type::String, Type::String) => true, | (Type::String, Type::String) => true,
(Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right), (Type::IntegerType(left), Type::IntegerType(right)) => left.eq(right),
(Type::Identifier(left), Type::Identifier(right)) => left.eq(right), (Type::Identifier(left), Type::Identifier(right)) => left.matches(right),
_ => false, _ => false,
} }
} }

View File

@ -64,20 +64,20 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
} }
fn visit_identifier(&mut self, var: &'a Identifier, expected: &Self::AdditionalInput) -> Option<Self::Output> { fn visit_identifier(&mut self, var: &'a Identifier, expected: &Self::AdditionalInput) -> Option<Self::Output> {
if let Some(circuit) = self.visitor.symbol_table.clone().lookup_circuit(&var.name) { if let VisitResult::VisitChildren = self.visitor.visit_identifier(var) {
return Some(self.visitor.assert_expected_option( if let Some(circuit) = self.visitor.symbol_table.clone().lookup_circuit(&var.name) {
Type::Identifier(circuit.identifier.clone()), return Some(self.visitor.assert_expected_option(
expected, Type::Identifier(circuit.identifier.clone()),
circuit.span(), expected,
)); circuit.span(),
} else if let Some(record) = self.visitor.symbol_table.clone().lookup_record(&var.name) { ));
return Some(self.visitor.assert_expected_option( } else if let Some(record) = self.visitor.symbol_table.clone().lookup_record(&var.name) {
Type::Identifier(record.identifier.clone()), return Some(self.visitor.assert_expected_option(
expected, Type::Identifier(record.identifier.clone()),
record.span(), expected,
)); record.span(),
} else if let VisitResult::VisitChildren = self.visitor.visit_identifier(var) { ));
if let Some(var) = self.visitor.symbol_table.clone().lookup_variable(&var.name) { } else if let Some(var) = self.visitor.symbol_table.clone().lookup_variable(&var.name) {
return Some(self.visitor.assert_expected_option(*var.type_, expected, var.span)); return Some(self.visitor.assert_expected_option(*var.type_, expected, var.span));
} else { } else {
self.visitor self.visitor
@ -651,26 +651,22 @@ impl<'a> ExpressionVisitorDirector<'a> for Director<'a> {
// Check record variable types. // Check record variable types.
input.members.iter().for_each(|actual| { input.members.iter().for_each(|actual| {
// Check record owner.
if actual.identifier.matches(&expected.owner.ident) { if actual.identifier.matches(&expected.owner.ident) {
// Check record owner.
if let Some(owner_expr) = &actual.expression { if let Some(owner_expr) = &actual.expression {
self.visit_expression(owner_expr, &Some(Type::Address)); self.visit_expression(owner_expr, &Some(Type::Address));
} }
} } else if actual.identifier.matches(&expected.balance.ident) {
// Check record balance.
// Check record balance.
if actual.identifier.matches(&expected.balance.ident) {
if let Some(balance_expr) = &actual.expression { if let Some(balance_expr) = &actual.expression {
self.visit_expression(balance_expr, &Some(Type::IntegerType(IntegerType::U64))); self.visit_expression(balance_expr, &Some(Type::IntegerType(IntegerType::U64)));
} }
} } else if let Some(expected_var) = expected
// Check record data variable.
if let Some(expected_var) = expected
.data .data
.iter() .iter()
.find(|member| member.ident.matches(&actual.identifier)) .find(|member| member.ident.matches(&actual.identifier))
{ {
// Check record data variable.
if let Some(var_expr) = &actual.expression { if let Some(var_expr) = &actual.expression {
self.visit_expression(var_expr, &Some(expected_var.type_)); self.visit_expression(var_expr, &Some(expected_var.type_));
} }

View File

@ -68,7 +68,6 @@ impl<'a> ProgramVisitorDirector<'a> for Director<'a> {
} }
fn visit_record(&mut self, input: &'a Record) { fn visit_record(&mut self, input: &'a Record) {
println!("visit record");
if let VisitResult::VisitChildren = self.visitor_ref().visit_record(input) { if let VisitResult::VisitChildren = self.visitor_ref().visit_record(input) {
// Check for conflicting record member names. // Check for conflicting record member names.
let mut used = HashSet::new(); let mut used = HashSet::new();

View File

@ -159,7 +159,7 @@ impl<'a> TypeChecker<'a> {
/// Returns the given `actual` type and emits an error if the `expected` type does not match. /// Returns the given `actual` type and emits an error if the `expected` type does not match.
pub(crate) fn assert_expected_option(&mut self, actual: Type, expected: &Option<Type>, span: Span) -> Type { pub(crate) fn assert_expected_option(&mut self, actual: Type, expected: &Option<Type>, span: Span) -> Type {
if let Some(expected) = expected { if let Some(expected) = expected {
if &actual != expected { if !actual.eq_flat(expected) {
self.handler self.handler
.emit_err(TypeCheckerError::type_should_be(actual, expected, span).into()); .emit_err(TypeCheckerError::type_should_be(actual, expected, span).into());
} }
@ -172,7 +172,7 @@ impl<'a> TypeChecker<'a> {
/// `span` should be the location of the expected type. /// `span` should be the location of the expected type.
pub(crate) fn assert_expected_type(&mut self, actual: &Option<Type>, expected: Type, span: Span) -> Type { pub(crate) fn assert_expected_type(&mut self, actual: &Option<Type>, expected: Type, span: Span) -> Type {
if let Some(actual) = actual { if let Some(actual) = actual {
if actual != &expected { if !actual.eq_flat(&expected) {
self.handler self.handler
.emit_err(TypeCheckerError::type_should_be(actual, expected, span).into()); .emit_err(TypeCheckerError::type_should_be(actual, expected, span).into());
} }

View File

@ -1,16 +1,3 @@
circuit Token {
// The token owner.
balance: u64,
data: u64
}
function mint() -> Token {
let tok: Token = Token { balance: 1u64, data: 1u64};
return tok;
}
function main(a: u8) -> group { function main(a: u8) -> group {
return Pedersen64::hash(a); return Pedersen64::hash(a);
} }