mirror of
https://github.com/ProvableHQ/leo.git
synced 2024-11-23 23:23:50 +03:00
constant time lookups
This commit is contained in:
parent
909289c83c
commit
c37eeaae03
@ -147,7 +147,7 @@ impl ParserContext<'_> {
|
||||
match &self.token.token {
|
||||
Token::Const => {
|
||||
let declaration = self.parse_const_declaration_statement()?;
|
||||
consts.push((Symbol::intern(&declaration.place.to_string()), definition));
|
||||
consts.push((Symbol::intern(&declaration.place.to_string()), declaration));
|
||||
}
|
||||
Token::Struct | Token::Record => {
|
||||
let (id, struct_) = self.parse_struct()?;
|
||||
|
@ -59,14 +59,22 @@ impl<'a> CodeGenerator<'a> {
|
||||
// Note that the unwrap is safe since type checking guarantees that the struct dependency graph is acyclic.
|
||||
let order = self.struct_graph.post_order().unwrap();
|
||||
|
||||
// Create a mapping of symbols to references of structs so can perform constant-time lookups.
|
||||
let structs_map: IndexMap<Symbol, &Struct> = program_scope.structs.iter().map(|(name, struct_)| {
|
||||
(
|
||||
*name,
|
||||
struct_
|
||||
)
|
||||
}).collect();
|
||||
|
||||
// Visit each `Struct` or `Record` in the post-ordering and produce an Aleo struct or record.
|
||||
program_string.push_str(
|
||||
&order
|
||||
.into_iter()
|
||||
.map(|name| {
|
||||
match program_scope.structs.iter().find(|(identifier, _)| *identifier == name) {
|
||||
match structs_map.get(&name) {
|
||||
// If the struct is found, it is a local struct.
|
||||
Some((_, struct_)) => self.visit_struct_or_record(struct_),
|
||||
Some(struct_) => self.visit_struct_or_record(*struct_),
|
||||
// If the struct is not found, it is an imported struct.
|
||||
None => String::new(),
|
||||
}
|
||||
|
@ -19,6 +19,8 @@ use crate::{Assigner, AssignmentRenamer, CallGraph};
|
||||
use leo_ast::{Function, NodeBuilder};
|
||||
use leo_span::Symbol;
|
||||
|
||||
use indexmap::IndexMap;
|
||||
|
||||
pub struct FunctionInliner<'a> {
|
||||
/// A counter used to create unique NodeIDs.
|
||||
pub(crate) node_builder: &'a NodeBuilder,
|
||||
|
@ -15,8 +15,10 @@
|
||||
// along with the Leo library. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
use crate::FunctionInliner;
|
||||
use indexmap::{IndexMap, IndexSet};
|
||||
|
||||
use leo_ast::{ProgramReconstructor, ProgramScope};
|
||||
use leo_ast::{Function, ProgramReconstructor, ProgramScope};
|
||||
use leo_span::Symbol;
|
||||
|
||||
impl ProgramReconstructor for FunctionInliner<'_> {
|
||||
fn reconstruct_program_scope(&mut self, mut input: ProgramScope) -> ProgramScope {
|
||||
@ -25,25 +27,30 @@ impl ProgramReconstructor for FunctionInliner<'_> {
|
||||
// Note that the unwrap is safe since type checking guarantees that the call graph is acyclic.
|
||||
let order = self.call_graph.post_order().unwrap();
|
||||
|
||||
// Construct map to provide faster lookup of functions
|
||||
let function_map: IndexMap<Symbol, Function> = input.functions.clone().into_iter().collect();
|
||||
|
||||
// Construct set to keep track of the remaining functions that still need to be processed.
|
||||
let mut function_set: IndexSet<Symbol> = function_map.keys().cloned().collect();
|
||||
|
||||
// Reconstruct and accumulate each of the functions in post-order.
|
||||
for function_name in order.into_iter() {
|
||||
// None: If `function_name` is not in `input.functions`, then it must be an external function.
|
||||
// TODO: Check that this is indeed an external function. Requires a redesign of the symbol table.
|
||||
|
||||
if let Some(pos) = input.functions.iter().position(|(symbol, _)| *symbol == function_name) {
|
||||
let (_, function) = input.functions.remove(pos);
|
||||
if let Some(function) = function_map.get(&function_name) {
|
||||
function_set.remove(&function_name);
|
||||
// Reconstruct the function.
|
||||
let reconstructed_function = self.reconstruct_function(function);
|
||||
let reconstructed_function = self.reconstruct_function(function.clone());
|
||||
// Add the reconstructed function to the mapping.
|
||||
self.reconstructed_functions.insert(function_name, reconstructed_function);
|
||||
}
|
||||
}
|
||||
// Check that `input.functions` is empty.
|
||||
// This is a sanity check to ensure that functions in the program scope have been processed.
|
||||
assert!(input.functions.is_empty(), "All functions in the program scope should have been processed.");
|
||||
assert!(function_set.is_empty(), "All functions in the program scope should have been processed.");
|
||||
input.functions.clear();
|
||||
|
||||
// Note that this intentionally clears `self.reconstructed_functions` for the next program scope.
|
||||
let functions = core::mem::take(&mut self.reconstructed_functions).into_iter().map(|(symbol, function)| (*symbol, function.clone())).collect();
|
||||
let functions = core::mem::take(&mut self.reconstructed_functions).into_iter().collect();
|
||||
|
||||
ProgramScope {
|
||||
program_id: input.program_id,
|
||||
|
@ -2,4 +2,4 @@
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372082]: Expected a tuple with 2 elements, found one with 3 elements\n --> compiler-test:5:13\n |\n 5 | let (a,b,c): (u8,u8) = (2u8,3u8);\n | ^^^^^^^\nError [ETYC0372082]: Expected a tuple with 3 elements, found one with 2 elements\n --> compiler-test:6:13\n |\n 6 | let (d,e): (u8,u8,u8) = (1u8,2u8,3u8);\n | ^^^^^\n"
|
||||
- "Error [ETYC0372082]: Expected a tuple with 2 elements, found one with 3 elements\n --> compiler-test:5:13\n |\n 5 | let (a,b,c): (u8,u8) = (2u8,3u8);\n | ^^^^^^^\nError [ETYC0372082]: Expected a tuple with 3 elements, found one with 2 elements\n --> compiler-test:6:13\n |\n 6 | let (d,e): (u8,u8,u8) = (1u8,2u8,3u8);\n | ^^^^^\nError [ETYC0372003]: Expected type `(u8,u8,u8)` but type `u8` was found\n --> compiler-test:7:36\n |\n 7 | let (g,h,i): (u8,u8,u8) = (1u8);\n | ^^^\n"
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
namespace: Compile
|
||||
expectation: Fail
|
||||
outputs:
|
||||
- "Error [ETYC0372061]: Tuples on the left-hand side of a `DefinitionStatement` can only contain identifiers.\n --> compiler-test:5:14\n |\n 5 | let (1u8+1u8,1u8+1u8): (u8,u8) = (1u8,2u8);\n | ^^^^^^^\nError [ETYC0372061]: Tuples on the left-hand side of a `DefinitionStatement` can only contain identifiers.\n --> compiler-test:5:22\n |\n 5 | let (1u8+1u8,1u8+1u8): (u8,u8) = (1u8,2u8);\n | ^^^^^^^\n"
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
namespace: Compile
|
||||
expectation: Pass
|
||||
expectation: Fail
|
||||
*/
|
||||
|
||||
program test.aleo {
|
||||
|
Loading…
Reference in New Issue
Block a user