mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-12-24 10:41:57 +03:00
Tyc checks that types are defined
This commit is contained in:
parent
a69954b64a
commit
974e93cadf
@ -146,7 +146,7 @@ impl<'a> ExpressionVisitor<'a> for TypeChecker<'a> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
self.emit_err(TypeCheckerError::invalid_circuit(&access.inner, access.inner.span()));
|
||||
self.emit_err(TypeCheckerError::undefined_type(&access.inner, access.inner.span()));
|
||||
}
|
||||
}
|
||||
Some(type_) => {
|
||||
|
@ -43,6 +43,8 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
self.has_return = false;
|
||||
self.parent = Some(input.name());
|
||||
input.input.iter().for_each(|input_var| {
|
||||
// Check that the type of input parameter is valid.
|
||||
self.assert_type_is_valid(input_var.span, &input_var.type_);
|
||||
self.assert_not_tuple(input_var.span, &input_var.type_);
|
||||
|
||||
// If the function is not a program function, then check that the parameters do not have an associated mode.
|
||||
@ -68,6 +70,10 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
|
||||
if !self.has_return {
|
||||
self.emit_err(TypeCheckerError::function_has_no_return(input.name(), input.span()));
|
||||
} else {
|
||||
// Check that the return type is valid.
|
||||
// TODO: Span should be just for the return type.
|
||||
self.assert_type_is_valid(input.span, &input.output);
|
||||
}
|
||||
|
||||
// Ensure there are no nested tuples in the return type.
|
||||
@ -88,7 +94,16 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
|
||||
fn visit_circuit(&mut self, input: &'a Circuit) {
|
||||
// Check for conflicting circuit/record member names.
|
||||
let mut used = HashSet::new();
|
||||
if !input.members.iter().all(|member| used.insert(member.name())) {
|
||||
if !input
|
||||
.members
|
||||
.iter()
|
||||
.all(|CircuitMember::CircuitVariable(ident, type_)| {
|
||||
// TODO: Better spans.
|
||||
// Check that the member types are valid.
|
||||
self.assert_type_is_valid(input.span, type_);
|
||||
used.insert(ident.name)
|
||||
})
|
||||
{
|
||||
self.emit_err(if input.is_record {
|
||||
TypeCheckerError::duplicate_record_variable(input.name(), input.span())
|
||||
} else {
|
||||
|
@ -61,6 +61,9 @@ impl<'a> StatementVisitor<'a> for TypeChecker<'a> {
|
||||
VariableType::Mut
|
||||
};
|
||||
|
||||
// Check that the type of the definition is valid.
|
||||
self.assert_type_is_valid(input.span, &input.type_);
|
||||
|
||||
self.visit_expression(&input.value, &Some(input.type_.clone()));
|
||||
|
||||
if let Err(err) = self.symbol_table.borrow_mut().insert_variable(
|
||||
|
@ -317,6 +317,25 @@ impl<'a> TypeChecker<'a> {
|
||||
self.emit_err(TypeCheckerError::tuple_not_allowed(span))
|
||||
}
|
||||
}
|
||||
|
||||
/// Emits an error if the type is not valid.
|
||||
pub(crate) fn assert_type_is_valid(&self, span: Span, type_: &Type) {
|
||||
match type_ {
|
||||
// Check that the named composite type has been defined.
|
||||
Type::Identifier(identifier) => {
|
||||
if self.symbol_table.borrow().lookup_circuit(identifier.name).is_none() {
|
||||
self.emit_err(TypeCheckerError::undefined_type(identifier.name, span));
|
||||
}
|
||||
}
|
||||
// Check that the constituent types are valid.
|
||||
Type::Tuple(tuple_type) => {
|
||||
for type_ in tuple_type.iter() {
|
||||
self.assert_type_is_valid(span, type_)
|
||||
}
|
||||
}
|
||||
_ => {} // Do nothing.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn types_to_string(types: &[Type]) -> String {
|
||||
|
@ -193,10 +193,10 @@ create_messages!(
|
||||
|
||||
/// Attempted to access an invalid circuit.
|
||||
@formatted
|
||||
invalid_circuit {
|
||||
args: (circuit: impl Display),
|
||||
undefined_type {
|
||||
args: (type_: impl Display),
|
||||
msg: format!(
|
||||
"Circuit {circuit} is not found in the current scope."
|
||||
"The type `{type_}` is not found in the current scope."
|
||||
),
|
||||
help: None,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user