mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-27 02:24:15 +03:00
Implement check for nested import
This commit is contained in:
parent
41a8bc5a73
commit
7e70da2326
@ -71,10 +71,11 @@ impl ParserContext<'_> {
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: remove import resolution from parser.
|
||||
/// Parses an import statement `import foo.leo;`.
|
||||
pub(super) fn parse_import(&mut self) -> Result<(Identifier, Program)> {
|
||||
pub(super) fn parse_import(&mut self) -> Result<(Identifier, (Program, Span))> {
|
||||
// Parse `import`.
|
||||
let _start = self.expect(&Token::Import)?;
|
||||
let start = self.expect(&Token::Import)?;
|
||||
|
||||
// Parse `foo`.
|
||||
let import_name = self.expect_identifier()?;
|
||||
@ -86,7 +87,7 @@ impl ParserContext<'_> {
|
||||
return Err(ParserError::leo_imports_only(self.token.span).into());
|
||||
}
|
||||
|
||||
let _end = self.expect(&Token::Semicolon)?;
|
||||
let end = self.expect(&Token::Semicolon)?;
|
||||
|
||||
// Tokenize and parse import file.
|
||||
// Todo: move this to a different module.
|
||||
@ -114,7 +115,7 @@ impl ParserContext<'_> {
|
||||
// Use the parser to construct the imported abstract syntax tree (ast).
|
||||
let program_ast = parse_ast(self.handler, &prg_sf.src, prg_sf.start_pos)?;
|
||||
|
||||
Ok((import_name, program_ast.into_repr()))
|
||||
Ok((import_name, (program_ast.into_repr(), start + end)))
|
||||
}
|
||||
|
||||
/// Parsers a program scope `program foo.aleo { ... }`.
|
||||
|
@ -34,7 +34,7 @@ impl<'a> CodeGenerator<'a> {
|
||||
&input
|
||||
.imports
|
||||
.iter()
|
||||
.map(|(identifier, imported_program)| self.visit_import(identifier, imported_program))
|
||||
.map(|(identifier, (imported_program, _))| self.visit_import(identifier, imported_program))
|
||||
.join("\n"),
|
||||
);
|
||||
|
||||
|
@ -152,7 +152,7 @@ impl ProgramConsumer for StaticSingleAssigner<'_> {
|
||||
imports: input
|
||||
.imports
|
||||
.into_iter()
|
||||
.map(|(name, import)| (name, self.consume_program(import)))
|
||||
.map(|(name, (import, span))| (name, (self.consume_program(import), span)))
|
||||
.collect(),
|
||||
program_scopes: input
|
||||
.program_scopes
|
||||
|
@ -287,4 +287,32 @@ 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));
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,8 @@ pub struct TypeChecker<'a> {
|
||||
pub(crate) is_transition_function: bool,
|
||||
/// Whether or not we are currently traversing a finalize block.
|
||||
pub(crate) is_finalize: bool,
|
||||
/// Whether or not we are currently traversing an imported program.
|
||||
pub(crate) is_imported: bool,
|
||||
}
|
||||
|
||||
const BOOLEAN_TYPE: Type = Type::Boolean;
|
||||
@ -95,6 +97,7 @@ impl<'a> TypeChecker<'a> {
|
||||
has_return: false,
|
||||
has_finalize: false,
|
||||
is_finalize: false,
|
||||
is_imported: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,4 +430,11 @@ create_messages!(
|
||||
msg: format!("Loop bound must be a literal."),
|
||||
help: None,
|
||||
}
|
||||
|
||||
@formatted
|
||||
imported_program_cannot_import_program {
|
||||
args: (),
|
||||
msg: format!("An imported program cannot import another program."),
|
||||
help: None,
|
||||
}
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user