diff --git a/src/protocol/parser/mod.rs b/src/protocol/parser/mod.rs index 3dca61f0109c63bbe526e10dfd69e8e9cbf6feeb..acd963e0feb294e292cbf95b758b73d0c18a421c 100644 --- a/src/protocol/parser/mod.rs +++ b/src/protocol/parser/mod.rs @@ -10,6 +10,7 @@ pub(crate) mod pass_definitions_types; pub(crate) mod pass_validation_linking; pub(crate) mod pass_rewriting; pub(crate) mod pass_typing; +pub(crate) mod pass_stack_size; mod visitor; use tokens::*; @@ -21,6 +22,8 @@ use pass_imports::PassImport; use pass_definitions::PassDefinitions; use pass_validation_linking::PassValidationLinking; use pass_typing::{PassTyping, ResolveQueue}; +use pass_rewriting::PassRewriting; +use pass_stack_size::PassStackSize; use symbol_table::*; use type_table::TypeTable; @@ -37,9 +40,10 @@ pub enum ModuleCompilationPhase { DefinitionsParsed, // produced the AST for the entire module TypesAddedToTable, // added all definitions to the type table ValidatedAndLinked, // AST is traversed and has linked the required AST nodes + Typed, // Type inference and checking has been performed Rewritten, // Special AST nodes are rewritten into regular AST nodes // When we continue with the compiler: - // Typed, // Type inference and checking has been performed + // StackSize } pub struct Module { @@ -87,6 +91,8 @@ pub struct Parser { pass_definitions: PassDefinitions, pass_validation: PassValidationLinking, pass_typing: PassTyping, + pass_rewriting: PassRewriting, + pass_stack_size: PassStackSize, // Compiler options pub write_ast_to: Option, pub(crate) arch: TargetArch, @@ -106,6 +112,8 @@ impl Parser { pass_definitions: PassDefinitions::new(), pass_validation: PassValidationLinking::new(), pass_typing: PassTyping::new(), + pass_rewriting: PassRewriting::new(), + pass_stack_size: PassStackSize::new(), write_ast_to: None, arch: TargetArch { array_size_alignment: (3*8, 8), // pointer, length, capacity @@ -254,6 +262,21 @@ impl Parser { self.pass_typing.handle_module_definition(&mut ctx, &mut queue, top)?; } + // Rewrite nodes in tree, then prepare for execution of code + for module_idx in 0..self.modules.len() { + self.modules[module_idx].phase = ModuleCompilationPhase::Typed; + let mut ctx = visitor::Ctx{ + heap: &mut self.heap, + modules: &mut self.modules, + module_idx, + symbols: &mut self.symbol_table, + types: &mut self.type_table, + arch: &self.arch, + }; + self.pass_rewriting.visit_module(&mut ctx); + self.pass_stack_size.visit_module(&mut ctx); + } + // Write out desired information if let Some(filename) = &self.write_ast_to { let mut writer = ASTWriter::new(); diff --git a/src/protocol/parser/pass_rewriting.rs b/src/protocol/parser/pass_rewriting.rs index 2b8b2229277749989eba786a202138f38a24de83..54b7c3b8d91feaafe05f565a28351992e0fffe24 100644 --- a/src/protocol/parser/pass_rewriting.rs +++ b/src/protocol/parser/pass_rewriting.rs @@ -5,6 +5,7 @@ use super::visitor::*; pub(crate) struct PassRewriting { current_scope: ScopeId, + definition_buffer: ScopedBuffer, statement_buffer: ScopedBuffer, call_expr_buffer: ScopedBuffer, expression_buffer: ScopedBuffer, @@ -15,6 +16,7 @@ impl PassRewriting { pub(crate) fn new() -> Self { Self{ current_scope: ScopeId::new_invalid(), + definition_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_LARGE), statement_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_SMALL), call_expr_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_SMALL), expression_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_SMALL), @@ -24,6 +26,23 @@ impl PassRewriting { } impl Visitor for PassRewriting { + fn visit_module(&mut self, ctx: &mut Ctx) -> VisitorResult { + let module = ctx.module(); + debug_assert_eq!(module.phase, ModuleCompilationPhase::Typed); + + let root_id = module.root_id; + let root = &ctx.heap[root_id]; + let definition_section = self.definition_buffer.start_section_initialized(&root.definitions); + for definition_index in 0..definition_section.len() { + let definition_id = definition_section[definition_index]; + self.visit_definition(ctx, definition_id)?; + } + + definition_section.forget(); + ctx.module_mut().phase = ModuleCompilationPhase::Rewritten; + return Ok(()) + } + // --- Visiting procedures fn visit_component_definition(&mut self, ctx: &mut Ctx, id: ComponentDefinitionId) -> VisitorResult { @@ -135,7 +154,7 @@ impl Visitor for PassRewriting { outer_end_block_stmt.next = end_select_stmt_id.upcast(); // --- for the scopes - link_existing_child_to_new_parent_scope(ctx, &mut self.scope_buffer, self.current_scope, outer_scope_id, select_stmt_relative_pos); + link_new_child_to_existing_parent_scope(ctx, &mut self.scope_buffer, self.current_scope, outer_scope_id, select_stmt_relative_pos); // Create statements that will create temporary variables for all of the // ports passed to the "get" calls in the select case guards. @@ -144,7 +163,6 @@ impl Visitor for PassRewriting { let mut total_num_ports = 0; let end_select_stmt_id = select_stmt.end_select; let end_select = &ctx.heap[end_select_stmt_id]; - let stmt_id_after_select_stmt = end_select.next; // Put heap IDs into temporary buffers to handle borrowing rules let mut call_id_section = self.call_expr_buffer.start_section(); diff --git a/src/protocol/parser/pass_stack_size.rs b/src/protocol/parser/pass_stack_size.rs new file mode 100644 index 0000000000000000000000000000000000000000..1d1dce19b00791ebf8c290caf5287088ab7f1870 --- /dev/null +++ b/src/protocol/parser/pass_stack_size.rs @@ -0,0 +1,39 @@ +use crate::collections::*; +use crate::protocol::*; + +use super::visitor::*; + +// Will get a rename. Will probably become bytecode emitter or something. For +// now it just scans the scopes and assigns a unique number for each variable +// such that, at any point in the program's execution, all accessible in-scope +// variables will have a unique position "on the stack". +pub(crate) struct PassStackSize { + definition_buffer: ScopedBuffer, +} + +impl PassStackSize { + pub(crate) fn new() -> Self { + return Self{ + definition_buffer: ScopedBuffer::with_capacity(BUFFER_INIT_CAP_LARGE), + } + } +} + +impl Visitor for PassStackSize { + fn visit_module(&mut self, ctx: &mut Ctx) -> VisitorResult { + let module = ctx.module(); + debug_assert_eq!(module.phase, ModuleCompilationPhase::Rewritten); + + let root_id = module.root_id; + let root = &ctx.heap[root_id]; + let definition_section = self.definition_buffer.start_section_initialized(&root.definitions); + for definition_index in 0..definition_section.len() { + let definition_id = definition_section[definition_index]; + self.visit_definition(ctx, definition_id)? + } + + definition_section.forget(); + // ctx.module_mut().phase = ModuleCompilationPhase::StackSizeStuffAndStuff; + return Ok(()) + } +} \ No newline at end of file