flat assembler
Message board for the users of flat assembler.

flat assembler > Macroinstructions > Different macro behavior for different argument counts

Author
Thread Post new topic Reply to topic
VileR



Joined: 29 Nov 2018
Posts: 5
Location: B800:0000
Wondering if there is a way to define a single macro name to have a different behavior depending on the number of arguments.

For instance, to have one definition for a macro with two arguments
Code:
foo arg1, arg2    


...and another definition to specify that the same macro can optionally take three arguments
Code:
foo arg1, arg2, arg3    

(this definition can optionally, but not necessarily, call the first definition with two arguments.)

Some other assemblers support this kind of declaration. I had a look at the manual and there is a lot of flexibility in declaring macroinstructions, but I cannot see a way to do it quite like this. Advice appreciated. Smile

Thanks![/code]
Post 29 Nov 2018, 13:10
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16125
Location: Hyperborea
There are a few different approaches. One would be to define each macro separately and then call back through the chain. Example:
Code:
macro foo arg1 {
 ... ;do stuff for one argument foo
}
macro foo arg1,agr2 {
 local baz
 baz equ
 match =x,arg2 x \{
  foo arg1 ;call previous foo if arg2 is empty
  baz equ 1
 \}
 match =x,baz x \{
  ... ;do stuff for two argument foo
 \}
}    
Post 29 Nov 2018, 13:23
View user's profile Send private message Visit poster's website Reply with quote
VileR



Joined: 29 Nov 2018
Posts: 5
Location: B800:0000
Appreciated - was hoping it could be done more intuitively but this helped put me on the right direction. Thanks!
Post 30 Nov 2018, 07:27
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16125
Location: Hyperborea
You might be better off not using the layered macroinstructions. Instead you can use a single macro and then either 1) use the preprocessor to select the code path, or 2) use the assembler to select the code path. My personal preference is to use the assembler stage. I find the code easier to write and understand with the more intuitive if/else/end construct.
Post 30 Nov 2018, 08:03
View user's profile Send private message Visit poster's website Reply with quote
VileR



Joined: 29 Nov 2018
Posts: 5
Location: B800:0000
Yes; I ended up doing something more like this (one example):
Code:
macro adsto acc, val, [delta] {
  common
    if acc in <ax,al,ah> & val eqtype 0
    mov   acc, val
    end if
  forward
    if delta<>0
    add   di, (delta*2)
    end if
    stosw
}    

...in this case the first two arguments are optional, and one or more 'delta' arguments are mandatory.
But in that case, the first two arguments can't be entirely missing - to select the 'delta-only' code path I do have to ensure that the first condition evaluates to false, e.g.
Code:
    adsto ah, 0Ch, -5456,852,423,3780,788     ;acc, val, deltas
    adsto '', '',  0,879,320,864,331,3614     ;deltas only
    
Post 01 Dec 2018, 23:05
View user's profile Send private message Visit poster's website Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16125
Location: Hyperborea
You can also pass blanks parameters:
Code:
adsto ,,1,2,3,4    
Post 01 Dec 2018, 23:18
View user's profile Send private message Visit poster's website Reply with quote
VileR



Joined: 29 Nov 2018
Posts: 5
Location: B800:0000
Yep - that works as expected and makes things more readable. Thanks!

That's already close enough to what I was after. But just out of curiosity: using conditional assembly, is there a more direct method of differentiating between blank and non-blank arguments?
That would be a bit more intuitive than having to negate a condition like "x eqtype 0", when the intent is simply to check that the argument isn't blank. For instance, I've tried:
Code:
if acc in <ax,al,ah> & val ~ eq       ;attempt 1
if acc in <ax,al,ah> & val ~ eqtype   ;attempt 2
if acc in <ax,al,ah> & val <>         ;attempt 3    

The first two do not work as expected, and the last naturally produces an error.
Post 02 Dec 2018, 07:42
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 6994
Location: Kraków, Poland
The negation operator should precede the sub-expression:
Code:
if acc in <ax,al,ah> & ~ val eq    


Alternatively, you can specify default values for macro argument, then when argument is provided blank, default value is used instead:
Code:
macro adsto acc, val:0, [delta:0] {
  common
    if acc in <ax,al,ah> & val eqtype 0
    mov   acc, val
    end if
  forward
    if delta<>0
    add   di, (delta*2)
    end if
}

adsto ax        ; mov ax,0
adsto ax,1      ; mov ax,1
adsto ax,1,2    ; mov ax,1 / add di,2*2    
Post 02 Dec 2018, 12:54
View user's profile Send private message Visit poster's website Reply with quote
VileR



Joined: 29 Nov 2018
Posts: 5
Location: B800:0000
Oh, good - both of these alternatives seem to work nicely enough. Appreciated!
Post 02 Dec 2018, 19:16
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >
Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Copyright © 1999-2018, Tomasz Grysztar.

Powered by rwasa.