From 09b190449d34574cc9ca7b9bf9477efe6c776e7e Mon Sep 17 00:00:00 2001 From: Aleksey Yakovlev Date: Tue, 28 May 2024 14:02:50 +0700 Subject: [PATCH] added partial local context --- src/compiler/rst/compilation_context.rs | 74 +++++++++++++++++++++---- src/compiler/rst/compiler.rs | 37 ++++++++----- src/compiler/util/id_generator.rs | 10 ++++ src/compiler/util/mod.rs | 2 + 4 files changed, 98 insertions(+), 25 deletions(-) create mode 100644 src/compiler/util/id_generator.rs diff --git a/src/compiler/rst/compilation_context.rs b/src/compiler/rst/compilation_context.rs index fd6f50d..46dc97e 100644 --- a/src/compiler/rst/compilation_context.rs +++ b/src/compiler/rst/compilation_context.rs @@ -12,8 +12,15 @@ pub(crate) struct ConstantBinding { #[derive(Clone)] pub(crate) struct FunctionBinding { + pub(crate) identifier: u64, pub(crate) name: String, - pub(crate) context: CompilationContext +} + +#[derive(Clone)] +pub(crate) struct LocalCompilationContext { + constant_table: HashMap, + function_table: HashMap, + parents: Vec, } #[derive(Clone)] @@ -22,6 +29,7 @@ pub(crate) struct CompilationContext { parent: Option>, constant_table: HashMap, function_table: HashMap, + local_contexts: HashMap, } impl CompilationContext { @@ -31,31 +39,77 @@ impl CompilationContext { parent: None, constant_table: HashMap::new(), function_table: HashMap::new(), + local_contexts: HashMap::new(), }; } - pub(crate) fn branch(parent: CompilationContext) -> CompilationContext { - return CompilationContext { - self_path: parent.self_path.clone(), - parent: Some(Box::new(parent)), + // region constant + pub(crate) fn bind_local_constant(&mut self, context_id: u64, constant: ConstantBinding) { + if !self.local_contexts.contains_key(&context_id) { + self.local_contexts.insert(context_id, LocalCompilationContext::new()); + } + + let mut local_context: &mut LocalCompilationContext = self.local_contexts.get_mut(&context_id) + .expect("prechecked but value is still missing"); + + local_context.bind_constant(constant); + } + pub(crate) fn get_local_constant(&self, context_id: u64, name: &String) -> Option<&ConstantBinding> { + let local_context = self.local_contexts.get(&context_id)?; + + let local_constant = local_context.get_constant(context_id, name); + + if local_constant.is_none() { + for parent in &local_context.parents { + let parent_constant = self.get_local_constant(*parent, name); + if parent_constant.is_some() { + return parent_constant + } + } + } else { + return local_constant + } + + return None; + } + + // endregion + + pub(crate) fn bind_function(&mut self, function: FunctionBinding) { + self.function_table.insert(function.name.clone(), function); + } + + pub(crate) fn get_function(&self, name: &String) -> Option<&FunctionBinding> { + return self.function_table.get(name); + } +} + +impl LocalCompilationContext { + fn new() -> LocalCompilationContext { + return LocalCompilationContext { constant_table: HashMap::new(), function_table: HashMap::new(), + parents: Vec::new(), }; } - pub(crate) fn bind_constant(&mut self, constant: ConstantBinding) { + fn bind_constant(&mut self, constant: ConstantBinding) { self.constant_table.insert(constant.name.clone(), constant); } - pub(crate) fn get_constant(&self, name: &String) -> Option<&ConstantBinding> { + fn get_constant(&self, context_id: u64, name: &String) -> Option<&ConstantBinding> { return self.constant_table.get(name); } - pub(crate) fn bind_function(&mut self, function: FunctionBinding) { + fn bind_function(&mut self, function: FunctionBinding) { self.function_table.insert(function.name.clone(), function); } - pub(crate) fn get_function(&self, name: &String) -> Option<&FunctionBinding> { + fn get_function(&self, name: &String) -> Option<&FunctionBinding> { return self.function_table.get(name); } -} + + fn attach_parent(&mut self, parent_id: u64) { + self.parents.push(parent_id); + } +} \ No newline at end of file diff --git a/src/compiler/rst/compiler.rs b/src/compiler/rst/compiler.rs index 68640de..80f2c11 100644 --- a/src/compiler/rst/compiler.rs +++ b/src/compiler/rst/compiler.rs @@ -3,7 +3,7 @@ use std::path::PathBuf; use crate::compiler::cst::{CstAtom, CstAtomVec, CstEmitStatement, CstFile, CstFunctionStatement}; use crate::compiler::rst::compilation_context::{CompilationContext, ConstantBinding, FunctionBinding}; use crate::compiler::rst::node::HexoFile; -use crate::compiler::util::ByteBuffer; +use crate::compiler::util::{ByteBuffer, next_identifier}; use crate::compiler::HexoCompiler; #[derive(Debug)] @@ -21,9 +21,10 @@ impl RstCompiler<'_> { } pub(crate) fn compile(&self, cst: &CstFile) -> Result { - let context = Self::build_context(&cst.path, &cst.main)?; + let context_id = next_identifier(); + let context = Self::build_context(context_id, &cst.path, &cst.main)?; - let bb = Self::build_bytes(&context, &cst.main.emits)?; + let bb = Self::build_bytes(context_id, &context, &cst.main.emits)?; return Ok(HexoFile { path: cst.path.clone(), @@ -33,19 +34,21 @@ impl RstCompiler<'_> { } fn build_bytes( + context_id: u64, context: &CompilationContext, emits: &Vec, ) -> Result { let mut byte_buffer = ByteBuffer::new(); for emit in emits { - Self::build_bytes_into(context, &emit.atoms, &mut byte_buffer)? + Self::build_bytes_into(context_id, context, &emit.atoms, &mut byte_buffer)? } return Ok(byte_buffer); } fn build_bytes_into( + context_id: u64, context: &CompilationContext, atoms: &CstAtomVec, buffer: &mut ByteBuffer, @@ -55,7 +58,7 @@ impl RstCompiler<'_> { CstAtom::Hex(byte) => buffer.push_byte(*byte), CstAtom::String(string) => buffer.push_string(string.clone()), CstAtom::Number(number) => buffer.push_u32_shrunk(*number), - CstAtom::Constant { name } => Self::build_constant_into(context, &name, buffer)?, + CstAtom::Constant { name } => Self::build_constant_into(context_id, context, &name, buffer)?, CstAtom::Function { .. } => {} } } @@ -64,12 +67,13 @@ impl RstCompiler<'_> { } fn build_constant_into( + context_id: u64, context: &CompilationContext, name: &String, buffer: &mut ByteBuffer, ) -> Result<(), RstCompilerError> { let constant_binding = context - .get_constant(name) + .get_local_constant(context_id, name) .ok_or(RstCompilerError::UnresolvedConstant { name: name.clone() })?; buffer.push_byte_buffer(&constant_binding.byte_buffer); @@ -78,30 +82,36 @@ impl RstCompiler<'_> { } fn build_context( + context_id: u64, file_path: &PathBuf, cst: &CstFunctionStatement, ) -> Result { let mut root_context = CompilationContext::new(file_path); - Self::build_context_into(&cst, &mut root_context)?; + Self::build_context_into(context_id, &cst, &mut root_context)?; return Ok(root_context); } - fn build_context_into(cst: &&CstFunctionStatement, mut root_context: &mut CompilationContext) -> Result<(), RstCompilerError> { - Self::build_context_constants_into(&cst, &mut root_context)?; + fn build_context_into( + context_id: u64, + cst: &&CstFunctionStatement, + mut root_context: &mut CompilationContext, + ) -> Result<(), RstCompilerError> { + Self::build_context_constants_into(context_id, &cst, &mut root_context)?; Self::build_context_functions_into(&cst, &mut root_context)?; Ok(()) } fn build_context_constants_into( + context_id: u64, cst: &&CstFunctionStatement, root_context: &mut CompilationContext, ) -> Result<(), RstCompilerError> { for constant in &cst.constants { let mut buff = ByteBuffer::new(); - Self::build_bytes_into(&root_context, &constant.atoms, &mut buff)?; - root_context.bind_constant(ConstantBinding { + Self::build_bytes_into(context_id, &root_context, &constant.atoms, &mut buff)?; + root_context.bind_local_constant(context_id, ConstantBinding { name: constant.name.clone(), byte_buffer: buff, }) @@ -115,13 +125,10 @@ impl RstCompiler<'_> { root_context: &mut CompilationContext, ) -> Result<(), RstCompilerError> { for function in &cst.functions { - let mut sub_context = CompilationContext::branch(root_context.clone()); - Self::build_context_into(&function, &mut sub_context)?; - root_context.bind_function( FunctionBinding { + identifier: next_identifier(), name: function.name.clone(), - context: sub_context, }) } diff --git a/src/compiler/util/id_generator.rs b/src/compiler/util/id_generator.rs new file mode 100644 index 0000000..b27ef05 --- /dev/null +++ b/src/compiler/util/id_generator.rs @@ -0,0 +1,10 @@ +use std::collections::HashMap; + +static mut COUNTER: u64 = 0; + +pub(crate) fn next_identifier() -> u64 { + unsafe { + COUNTER = COUNTER + 1; + COUNTER + } +} \ No newline at end of file diff --git a/src/compiler/util/mod.rs b/src/compiler/util/mod.rs index 93fc421..343986c 100644 --- a/src/compiler/util/mod.rs +++ b/src/compiler/util/mod.rs @@ -1,4 +1,6 @@ mod byte_buffer; pub(crate) mod encoding; +mod id_generator; pub(crate) use byte_buffer::ByteBuffer; +pub(crate) use id_generator::next_identifier; \ No newline at end of file