From ba351201bca9bb116c2216b3e3f031cb8000b144 Mon Sep 17 00:00:00 2001 From: Miquel Sabaté Solà Date: Mon, 18 Aug 2025 17:08:53 +0200 Subject: Don't get into all blocks when evaluating the context MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some control statements like .if/.ifdef/.ifndef this is only desired when the condition is true; otherwise getting into the inner block should be prevented. Signed-off-by: Miquel Sabaté Solà --- lib/xixanta/src/assembler.rs | 55 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 51 insertions(+), 4 deletions(-) (limited to 'lib/xixanta/src') diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs index 2b82008..c12773b 100644 --- a/lib/xixanta/src/assembler.rs +++ b/lib/xixanta/src/assembler.rs @@ -448,11 +448,33 @@ impl<'a> Assembler<'a> { }); } - // If this control statement actually has a body, go inside - // of it. + // If this control statement actually has a body, try to go + // inside of it. That is not possible, for example, on + // if/ifdef/ifndef conditions with a condition that + // evaluates to false. if control_type.has_body() { - let inner = &node.right.as_ref().unwrap().args.as_ref().unwrap(); - self.eval_context(inner)?; + match control_type { + ControlType::IfDef | ControlType::IfNDef => { + // NOTE: you cannot realistically evaluate a + // condition which might depend on macro + // arguments which have not been provided at + // this stage. Hence, don't go into the inner + // block if this is the case. + if self.macros_seen == 0 { + self.evaluate_ifdef_block(node)? + } + } + ControlType::If => { + // NOTE: see IfDef | IfNDef. + if self.macros_seen == 0 { + self.evaluate_if_block(node)?; + } + } + _ => { + let inner = &node.right.as_ref().unwrap().args.as_ref().unwrap(); + self.eval_context(inner)?; + } + }; } } _ => {} @@ -1649,6 +1671,8 @@ impl<'a> Assembler<'a> { source: self.source_for(node), global: false, }); + } else if self.stage == Stage::Context { + self.eval_context(inner)?; } else { self.bundle(inner)?; } @@ -3631,6 +3655,29 @@ JAL procedure } } + #[test] + fn dont_redefine_variables_inside_false_ifdefs() { + let res = just_bundles( + r#"Var = 1 +.ifndef Var + Var = 0 +.endif + +.if !.defined(Var) + Var = 0 +.endif + +lda #Var +"#, + ); + + assert_eq!(res.len(), 1); + + assert_eq!(res[0].size, 2); + assert_eq!(res[0].bytes[0], 0xA9); + assert_eq!(res[0].bytes[1], 0x01); + } + // Macros #[test] -- cgit v1.2.3