Implement fix

This commit is contained in:
d0cd 2022-11-05 14:17:33 -07:00
parent de6ac4eb9b
commit 9370c11a2b
2 changed files with 58 additions and 28 deletions

View File

@ -26,6 +26,57 @@ use std::collections::HashSet;
// TODO: Generally, cleanup tyc logic.
impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
fn visit_program(&mut self, input: &'a Program) {
match self.is_imported {
// If the program is imported, then it is not allowed to import any other programs.
true => {
input.imports.values().for_each(|(_, span)| {
self.emit_err(TypeCheckerError::imported_program_cannot_import_program(*span))
});
}
// Otherwise, typecheck the imported programs.
false => {
// Set `self.is_imported`.
let previous_is_imported = core::mem::replace(&mut self.is_imported, true);
// Typecheck the imported programs.
input.imports.values().for_each(|import| self.visit_import(&import.0));
// Set `self.is_imported` to its previous state.
self.is_imported = previous_is_imported;
}
}
// Typecheck the program scopes.
input
.program_scopes
.values()
.for_each(|scope| self.visit_program_scope(scope));
}
fn visit_program_scope(&mut self, input: &'a ProgramScope) {
// Typecheck the struct definitions.
input.structs.values().for_each(|function| self.visit_struct(function));
// Typecheck the mapping definitions.
input.mappings.values().for_each(|mapping| self.visit_mapping(mapping));
// Typecheck the function definitions.
let mut transition_count = 0;
for function in input.functions.values() {
self.visit_function(function);
if matches!(function.call_type, CallType::Transition) {
transition_count += 1;
}
}
// TODO: Use the snarkVM configurations to parameterize the check, need similar checks for structs (all in separate PR)
// Check that the number of transitions does not exceed the maximum.
if transition_count > 15 {
self.emit_err(TypeCheckerError::too_many_transitions(15, input.program_id.name.span + input.program_id.network.span));
}
}
fn visit_struct(&mut self, input: &'a Struct) {
// Check for conflicting struct/record member names.
let mut used = HashSet::new();
@ -287,32 +338,4 @@ impl<'a> ProgramVisitor<'a> for TypeChecker<'a> {
// Unset `is_transition_function` flag.
self.is_transition_function = false;
}
fn visit_program(&mut self, input: &'a Program) {
match self.is_imported {
// If the program is imported, then it is not allowed to import any other programs.
true => {
input.imports.values().for_each(|(_, span)| {
self.emit_err(TypeCheckerError::imported_program_cannot_import_program(*span))
});
}
// Otherwise, typecheck the imported programs.
false => {
// Set `self.is_imported`.
let previous_is_imported = core::mem::replace(&mut self.is_imported, true);
// Typecheck the imported programs.
input.imports.values().for_each(|import| self.visit_import(&import.0));
// Set `self.is_imported` to its previous state.
self.is_imported = previous_is_imported;
}
}
// Typecheck the program scopes.
input
.program_scopes
.values()
.for_each(|scope| self.visit_program_scope(scope));
}
}

View File

@ -444,4 +444,11 @@ create_messages!(
msg: format!("An imported program cannot import another program."),
help: None,
}
@formatted
too_many_transitions {
args: (max: impl Display),
msg: format!("The number of transitions exceeds the maximum. snarkVM allows up to {max} transitions within a single program."),
help: None,
}
);