From d492aa8271f9fb02351b1144733508194df67746 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Wed, 23 Oct 2024 12:54:14 +0200 Subject: Re-work the support on labels, variables and jumps MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As a way to firstly adapt on the latest changes from the parser since 184c39579227 ("Re-work the parser from scratch"), the assembler had to leave out some features on 16114b2ca358 ("Adapt the assembler to the changes on the parser"). This commit reintroduces support for settings labels, variables and referencing them, while also providing a more robust implementation at that. Signed-off-by: Miquel Sabaté Solà --- lib/xixanta/src/context.rs | 51 ++++++++++++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 17 deletions(-) (limited to 'lib/xixanta/src/context.rs') diff --git a/lib/xixanta/src/context.rs b/lib/xixanta/src/context.rs index 3fceab9..bccac12 100644 --- a/lib/xixanta/src/context.rs +++ b/lib/xixanta/src/context.rs @@ -59,28 +59,35 @@ impl Context { } } - /// Sets a value for a new variable defined in the assignment `node`. - pub fn set_variable(&mut self, id: &PString, bundle: &Bundle) -> Result<(), ContextError> { + /// Sets a value for a variable defined in the assignment `node`. If + /// `overwrite` is set to true, then this value will be set even if the + /// variable already existed, otherwise it will return a ContextError + pub fn set_variable( + &mut self, + id: &PString, + bundle: &Bundle, + overwrite: bool, + ) -> Result<(), ContextError> { let scope_name = self.name().to_string(); let scope = self.map.get_mut(&scope_name).unwrap(); match scope.get_mut(&id.value) { - Some(_) => { - return Err(ContextError { - message: format!( - "'{}' already defined in {}: you cannot re-assign variables", - id.value, - self.to_human() - ), - line: id.line, - reason: ContextErrorReason::Redefinition, - }) + Some(sc) => { + if !overwrite { + return Err(ContextError { + message: format!( + "'{}' already defined in {}: you cannot re-assign variables", + id.value, + self.to_human() + ), + line: id.line, + reason: ContextErrorReason::Redefinition, + }); + } + *sc = bundle.clone(); } None => { - self.map.insert( - scope_name, - HashMap::from([(id.value.clone(), bundle.to_owned())]), - ); + scope.insert(id.value.clone(), bundle.to_owned()); } } @@ -121,6 +128,16 @@ impl Context { } } + pub fn force_context_switch(&mut self, name: &String) { + self.stack.push(name.to_owned()); + } + + pub fn force_context_pop(&mut self) { + if !self.stack.is_empty() { + self.stack.truncate(self.stack.len() - 1); + } + } + // Pushes a new context given a `node`, which holds the identifier of the // new scope. fn context_push(&mut self, id: &PNode) { @@ -150,7 +167,7 @@ impl Context { } // Returns the name of the current context. - fn name(&self) -> &str { + pub fn name(&self) -> &str { match self.stack.last() { Some(name) => name, None => GLOBAL_CONTEXT, -- cgit v1.2.3