flat assembler
Message board for the users of flat assembler.

flat assembler > Macroinstructions > forward and reverse with zero arguments

Author
Thread Post new topic Reply to topic
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16225
Location: The West Pole
I'm often finding myself coding workarounds to detect an empty argument list to avoid assembly errors.
Code:
; zero_arg_test.asm
macro tst [arg] {
        common
        display 'args: '
        forward
        display `arg,' '
        common
        display 13,10
}
tst 3,2,1
tst 2,1
tst 1
tst    
Code:
flat assembler  version 1.73.02  (2359008 kilobytes memory)
args: 3 2 1 
args: 2 1 
args: 1 
args: ,
zero_arg_test.asm [13]:
tst
zero_arg_test.asm [6] tst [4]:
        display `arg,' '
processed: display ',' ' '
error: extra characters on line.    
When the argument list is empty the forward and reverse directives will still iterate through the macro block with an empty argument.

Is there something that I missed where still producing code for an empty set is useful? I haven't yet found a situation where it helps me. But I have come across many situations where it hinders me.


Last edited by revolution on 28 Dec 2018, 12:09; edited 1 time in total
Post 28 Dec 2018, 02:57
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7061
Location: Kraków, Poland
It is mainly a matter of consistency across syntax where empty value is still a value. The symmetry becomes especially apparent when you specify a default value for an argument, but also when you have a similar macro that does not use argument grouping.

When macro uses no COMMON/FORWARD/REVERSE keywords, by default its whole body is treated as a FORWARD block. Processing an empty argument the same way as in the case of similar macro without square brackets around argument name was also a consistency point.

It was also preferable for a macro to signal an error because of broken expression or missing a value instead of just silently skipping entire body when an argument was missing (likely by mistake). Thus error detection was another use case of this feature in original design.
Post 28 Dec 2018, 11:05
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7061
Location: Kraków, Poland
For an actual example, old-style macros that utilized this might have looked like:
Code:
macro tag16 [value]
{
  db 1Fh,2
  dw value+0
}    
Note how you could simply extend a macro written for a single element by adding square brackets around the argument name and still have it behave the same in all the cases that worked with base macro.

Of course nowadays you'd be more likely to use (relatively recent) syntax for default value instead:
Code:
macro tag16 [value:0]
{
  db 1Fh,2
  dw value
}    

The other variant was where the base macro (for a single argument) would not work with an empty argument (broken expression, etc.) and where group variant would be also be expected to do the same. But nowadays you'd probably just use * to mark the argument as required to be non-empty there.
Post 28 Dec 2018, 11:32
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: 16225
Location: The West Pole
For my usage I often make simple call macros that have optional arguments.
Code:
macro mycall function,[argument] {
reverse ;or forward
 push argument
common
 call function
}    
Of course that fails when the argument set is empty, it generate a "push" opcode with no value. So I have to extend the macro to skip the forward/reverse block if the argument set is empty. It can be done, but it makes it quite a bit uglier, and it feels a bit of a surprise to have it generate code for no input.
Post 28 Dec 2018, 12:04
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 231
Location: Russian Federation, Sochi
revolution, syntax of call macro could be so as thou described. Thou just needed to override push to not causing error on empty value.
Post 28 Dec 2018, 12:48
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16225
Location: The West Pole
ProMiNick wrote:
revolution, syntax of call macro could be so as thou described. Thou just needed to override push to not causing error on empty value.
To solve it I don't override push, I use a match block to skip the forward/push/common lines.
Code:
macro mycall function,[argument] {
 common
 match anything,argument \{
 reverse ;or forward
   push argument
 common
 \}
 call function
}    
Post 28 Dec 2018, 12:55
View user's profile Send private message Visit poster's website Reply with quote
ProMiNick



Joined: 24 Mar 2012
Posts: 231
Location: Russian Federation, Sochi
not so match code needed to override push. The main thing is to avoid recursion.
push override for avoiding error on empty value is fast because is one line macro.
macro push value { match any,value \{ push value \} }

and usualy push most overrideble instruction by macros. so code could be added to existing macros.
Post 28 Dec 2018, 13:10
View user's profile Send private message Send e-mail Reply with quote
revolution
When all else fails, read the source


Joined: 24 Aug 2004
Posts: 16225
Location: The West Pole
Sure. That is another way. But it assumes the code always uses push. Sometimes I have more complex code in there, so for me it is easier to skip the unwanted blocks.

But my point was about the need for solutions, not the solutions themselves. I haven't found any situation where the blank argument behaviour was helpful to me.


Last edited by revolution on 28 Dec 2018, 13:50; edited 1 time in total
Post 28 Dec 2018, 13:46
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar
Assembly Artist


Joined: 16 Jun 2003
Posts: 7061
Location: Kraków, Poland
BTW, the new syntax back-ported from fasmg allows for perhaps a little better structured approach:
Code:
macro mycall function,arguments& {
  match any,arguments \{ irp argument,any \\{
    reverse push argument
  \\} \}
  call function
}    
Post 28 Dec 2018, 13:47
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-2019, Tomasz Grysztar.

Powered by rwasa.