aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/xixanta/src/assembler.rs47
1 files changed, 46 insertions, 1 deletions
diff --git a/lib/xixanta/src/assembler.rs b/lib/xixanta/src/assembler.rs
index 54ba4c3..a5937ba 100644
--- a/lib/xixanta/src/assembler.rs
+++ b/lib/xixanta/src/assembler.rs
@@ -1015,7 +1015,29 @@ impl<'a> Assembler<'a> {
// locally. These are basically arguments from a macro call.
if let Some(pd) = &pn.pending_defines {
for d in pd {
- let _ = self.context.set_variable(&d.id, &d.obj, true);
+ // Does this definition have a node attach to it? If so,
+ // then evaluate it again but with all the gained context we
+ // have at this stage. This way we will resolve the proper
+ // value for it even if it involved an arithmetical
+ // operation with an address we couldn't resolve before this
+ // stage.
+ let _ = match &d.obj.node {
+ Some(n) => {
+ // Yes! We have to evaluate this node again.
+ self.literal_mode = None;
+ let o = self.evaluate_node(n)?;
+
+ // Re-create the bundle to be passed from this
+ // object member, and set it as the variable's
+ // value.
+ let mut dobj = d.obj.clone();
+ dobj.bundle = o;
+ self.context.set_variable(&d.id, &dobj, true)
+ }
+ // No attached node, we can proceed by setting the
+ // variable as is.
+ None => self.context.set_variable(&d.id, &d.obj, true),
+ };
}
}
@@ -5179,6 +5201,29 @@ MACRO Var1
assert_eq!(res[3].bytes[1], 0xFC);
}
+ #[test]
+ fn arithmetic_on_macro_arg() {
+ let res = just_bundles(
+ r#"
+.macro MC ADDR
+ adc ADDR, y
+.endmacro
+
+MC things + 1
+
+things:
+ .byte $00, $01
+ "#,
+ );
+
+ assert_eq!(res.len(), 3);
+
+ assert_eq!(res[0].size, 3);
+ assert_eq!(res[0].bytes[0], 0x79);
+ assert_eq!(res[0].bytes[1], 0x04);
+ assert_eq!(res[0].bytes[2], 0x80);
+ }
+
// .repeat
#[test]