flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > Why does FORWARD/REVERSE always get processed?

Author
Thread Post new topic Reply to topic
bitRAKE



Joined: 21 Jul 2003
Posts: 4022
Location: vpcmpistri
bitRAKE 01 Sep 2010, 03:14
Code:
macro abc [y] {
  forward
    display '-'
  common
    display 13,10
}

abc
abc a
abc a,b
abc a,b,c
abc a,b,c,d    
Outputs:
Code:
-
-
--
---
----    
Logically, it seems the forward section of the macro shouldn't get processed if there are no parameters to iterate through. This was obviously an early design decision - just curious.

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 01 Sep 2010, 03:14
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: 20300
Location: In your JS exploiting you and your system
revolution 01 Sep 2010, 03:35
It is easier to exclude expressions than having to duplicate them.
Code:
;...
   common
 if ~ y eq
   forward
     display '-' 
   common
 end if
;...    
Post 01 Sep 2010, 03:35
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4022
Location: vpcmpistri
bitRAKE 01 Sep 2010, 03:57
Code:
abc
abc ,
abc ,,
abc ,,,    
Output:
Code:
-
--
---
----    
Very Happy (No such thing as a macro without parameters if defined to take parameters.)
Post 01 Sep 2010, 03:57
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: 20300
Location: In your JS exploiting you and your system
revolution 01 Sep 2010, 05:38
bitRAKE wrote:
(No such thing as a macro without parameters if defined to take parameters.)
ORLY? Even the humble stdcall must allow for zero to infinity parameters.
Post 01 Sep 2010, 05:38
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 01 Sep 2010, 06:55
bitRAKE wrote:
[Logically, it seems the forward section of the macro shouldn't get processed if there are no parameters to iterate through.
But there is a parameter to iterate through... even though it has an empty value. The "y" symbol was defined in macro header, it HAS to have some value, even if empty.
Post 01 Sep 2010, 06:55
View user's profile Send private message Visit poster's website Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4022
Location: vpcmpistri
bitRAKE 02 Sep 2010, 01:30
Empty is good, but having no value could be a 'feature' (i.e. added confusion). "*" is used if a macro must have a value, and it's possible to pass an empty value differently than no value. It is only the present interpretation of the macro definition which limits the use - "y" is a placeholder which the present definition says defaults to empty - not undefined.
Code:
macro xyz {
  forward
             display "-"
       reverse
             display "|"
       common
              display 13,10
}    
Here forward/reverse have no meaning and are processed anyhow - there is no parameter to iterate through. The whole macro is common in the absence of a parameter definition.
Code:
macro abc [y] {
  common
    if ~ y eq
      forward display '-' 
              display `y 
      common
    end if
    display 13,10 
} 

t equ
abc t
abc a
abc a,b     
Here we have an actual empty value in "t" passed as a parameter. Yet, how is this different from "a" or "b" - which have no definition? The default definition of "a" appears to be "a".
Code:
macro abc [y*] {
}
t equ
abc   ; invalid macro argument - empty not valid
abc t ; empty seems okay
abc a ; not having a definition is okay    
Hm...?

_________________
¯\(°_o)/¯ “languages are not safe - uses can be” Bjarne Stroustrup
Post 02 Sep 2010, 01:30
View user's profile Send private message Visit poster's website Reply with quote
baldr



Joined: 19 Mar 2008
Posts: 1651
baldr 02 Sep 2010, 05:03
bitRAKE wrote:
Here we have an actual empty value in "t" passed as a parameter.
Not exactly. Actual parameter passed is «t» token; later is gets replaced with its value, thus conditional control directive becomes if ~eq, yet display `y is expanded as display 't'.

Preprocessed listing is priceless.
Post 02 Sep 2010, 05:03
View user's profile Send private message Reply with quote
bitRAKE



Joined: 21 Jul 2003
Posts: 4022
Location: vpcmpistri
bitRAKE 02 Sep 2010, 06:14
I'm trying to address the preprocessor language and not a specific programming problem.

Sorry, for being so vague.
Post 02 Sep 2010, 06:14
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 02 Sep 2010, 06:55
bitRAKE wrote:
I'm trying to address the preprocessor language and not a specific programming problem.
But the substitution of symbolic variables with their values is something that you by definition (that is: by part of the language specification) get after the preprocessing, not before. Thus "t" is just what it is and is in no way empty. And if you remove the "if" in the first macro, you are going to notice that "display `y" really gets the non-empty value of "t" and thus would display "t" character.

It is related to how the language is defined, not the particular implementation.
To define such fine details of language I once wrote the Order of processing section of manual (and I plan to expand the topic in Understanding fasm). It is important that those rules really are (and have to be) a part of the language, and may still be implemented in a various ways.


Last edited by Tomasz Grysztar on 02 Sep 2010, 21:16; edited 1 time in total
Post 02 Sep 2010, 06:55
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 02 Sep 2010, 08:03
Back to the original question - there is one more interesting detail.

If you had this simple macro:
Code:
macro data x
{
 db x
}    
you could "upgrade" it to work for multiple parameters just by putting square brackets around the "x":
Code:
macro data [x]
{
 db x
}    
The "forward" behavior was originally (before there were "common", "forward" and "reverse" directives introduced) the only one, and it stayed as the default one since then.
This macro works exactly the same as the first one, unless more than one parameter is provided. This includes, that it works exactly the same as the first one when empty value for this one parameter is provided.
Post 02 Sep 2010, 08:03
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8351
Location: Kraków, Poland
Tomasz Grysztar 02 Sep 2010, 08:13
bitRAKE wrote:
"y" is a placeholder which the present definition says defaults to empty - not undefined.

No, there is no "default" in present definition. You get the empty value because you provide the empty value when you use the macro. Like:
Code:
abc ; one empty parameter
abc , ; two empty parameters
abc ,, ; three empty parameters, etc.    
As macro is defined to take at least one parameter, it always looks for one and takes its value - even if it is empty.
This could be changed in the future to "when parameter has an empty value, the default value is taken instead", and only this way the concept of "default" could get introduced here.
And the fact that single empty parameter is in text indistinguishable from no parameters at all (which is interpretation accepted when macro is defined to take no parameters) is merely a conincidence.

bitRAKE wrote:
Here forward/reverse have no meaning and are processed anyhow - there is no parameter to iterate through.
They are processed as in the case of "rept 1" - you always have this one standard iteration with "macro". As opposed to "rept 0", which is not processed at all (even "common" over zero iterations is considered to be non-existing - it also requires at least one iteration to become "alive").
Note that "forward" and "common" will work this way even in case of "match" directive - when there is also an option of one iteration or zero iterations, depending on whether there is a match, or none.
This relates to the fact that those directives are universal for all macro-builders, like "macro", "rept", "irp", "irps" and "match" and they are connected to the amount of iterations specified for that macro. Even if you do "rept" without any counter, you can still create symbols to iterate through - with the "local" directive:
Code:
rept 4
{ 
  local a 
  a: dd a
  common db a ; aggregates "a" values from four iterations
}    
And there are only two ways to create zero-iterations macro - either "rept 0" or "match" with no match. Smile

This all should get covered in "Understanding fasm", of course.
Post 02 Sep 2010, 08:13
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-2024, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.