flat assembler
Message board for the users of flat assembler.

Index > Compiler Internals > [fasmg] possible bug with redifined macro and "." struc sym

Author
Thread Post new topic Reply to topic
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 05 Dec 2019, 09:19
Hello!! I don't know why but with nested unconditional redefined macro the use of the "." symbol seem to be an error. The symbol is undefined.
Code:
struc ABC?
  macro DEF?! ; or purge DEF?
  end macro
  macro DEF?!
    display .+"0", $0A
  end macro
  redefine . $06
  DEF
end struc
    

Maybe I'm wrong and if it's the case i'm sorry Sad. But this is a bit weird.
Often in struc, I declare nested macro and at the end I purge them.
This idiom lead me to frequent bug. I hope there is some solution Smile.
Post 05 Dec 2019, 09:19
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 05 Dec 2019, 10:18
This is a complex interaction and a risky usage pattern. Unconditional macros can be really tricky to use, I would recommend avoiding them unless you really need them for some specific reason (but then you should make sure that you know how they interact with everything).

By using PURGE, or defining macro multiple times, you make it so it cannot be forward-referenced. Therefore the ABC macro does not have the DEF macro expanded in its text, because at the time ABC macro is defined, DEF is not yet defined. And then when ABC macro is called, it in turn calls DEF macro, which refers to "." symbol that is interpreted in its own context (not in the context of ABC macro).

On the other hand, when you define DEF macro just once and do not PURGE it, it can be forward-referenced and it is recognized and expanded at the time when ABC macro is defined. The DISPLAY line then becomes a part of the text of the ABC macro and therefore "." is interpreted in that context (as you probably expected).

In general, if you'd like unconditional macro to be reliably expanded in the text of another macro, define it outside.
Post 05 Dec 2019, 10:18
View user's profile Send private message Visit poster's website Reply with quote
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 05 Dec 2019, 20:38
Yes thx Tomasz. I forget here to use the ?! macro to debug.
Code:
struc ABC?
  macro DEF?!
    display .+"0", $0A
  end macro
  redefine . $06
  DEF
end struc
    

Apparently the above code is fine but if the struc ABC is called several time the DEF is not constant and cannot be forward-referenced.
A possible "solution" is to declare it recursive. Such decl prevent the second call to ABC.
With nested macro in my first example, I like the idea of restricting the scope (like private).
Fortunately there is the "local" keyword. An idea, is maybe an instruction "static" that behave like local but each invocation can access the same symbol (expr,instr).
Post 05 Dec 2019, 20:38
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 06 Dec 2019, 15:55
Keep in mind that this relies on DEF being forward-referenced (because it is defined when the macro is called for the first time, but it is being used (expanded) when the macro is being defined. Therefore this needs a second pass to even start working properly (though if you need it just for debugging, then that's perhaps not an issue).

This is also why LOCAL would not help you here. Because you need the macro to be expanded when the outer STRUC is being defined, not when it is called. Also, BTW, you cannot make an unconditional macro recursive, an unconditional recursion would be infinite, for this reason this combination is not really allowed.

Therefore, if you really need to keep the definition inside your STRUC, you'd need to do something like:
Code:
struc ABC?
  if ~ definite ABCDEF
    ABCDEF := 1
    macro DEF?!
      display .+"0", $0A
    end macro
  end if
  redefine . $06
  DEF
end struc    

MaoKo wrote:
An idea, is maybe an instruction "static" that behave like local but each invocation can access the same symbol (expr,instr).
You could use a dedicated namespace for this purpose, perhaps one with the same name as macro. Since macro must have a name somewhere in the namespace tree, you can anchor your associated namespace at the same point.
Post 06 Dec 2019, 15:55
View user's profile Send private message Visit poster's website Reply with quote
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 14 Dec 2019, 07:41
Thank you, Tomasz. I have just another question in mind.
Why in this code, the context associated with the "." symbol seem to be dropped?
Code:
struc insert_database?
        __database equ .
        redefine . $02
end struc
distinct? := $00
macro store_wrapper?! object?*
        namespace distinct?
                object insert_database
        end namespace
end macro
struc main_loop?
        redefine . $01
        store_wrapper .
        display .+"0", $A ; display 1
end struc
^ main_loop
display distinct..+"0", $0A ; error
display .+"0", $0A ; display 2
    

I have difficulties to understand why after the macroinstruction "store_wrapper .", the "." still has the value $01.
And why, it's create the global "." symbol? If I remplace the "." with a different local symbol, everything works fine.
Thank you in advance Smile.
Post 14 Dec 2019, 07:41
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 14 Dec 2019, 09:15
This is yet another demonstration of why unconditional macros are tricky and should not be used without a good reason. Because your "store_wrapper" macro is unconditional, is it expanded during the definition of STRUC main_loop. And at the time the context is still global, so the value of "object" parameter has the global context associated with it and such text with context becomes part of the "main_loop" macro.
Post 14 Dec 2019, 09:15
View user's profile Send private message Visit poster's website Reply with quote
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 14 Dec 2019, 09:33
Ok I think that I understand. And if you do:
Code:
struc main_loop?
        local local_object?
        redefine local_object $01
        store_wrapper local_object
        display local_object+"0", $A
end struc
    

The store_wrapper expand and after that the local keyword "take the control".
Ps: I think that you should, maybe, introduce the subtle behavior with "." in the man.
Post 14 Dec 2019, 09:33
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8356
Location: Kraków, Poland
Tomasz Grysztar 14 Dec 2019, 10:15
This behavior is not unique to ".", any identifier would keep its original context when used like this. The reason that it behaves differently with LOCAL is because LOCAL defines parameters for preprocessing, which take precedence over everything else. Consider this example:
Code:
macro wrapper! object*
        namespace distinct
                object = 1
                a = 2
                repeat 1, a: 3
                        display 'parameter: ','0'+object,10
                end repeat
        end namespace
end macro

macro main
        wrapper a
end macro

main

display 'local: ','0'+distinct.a,10
display 'global: ','0'+a,10    
It defines "main" macro that looks like this:
Code:
macro main
        namespace distinct
                a = 1   ; "a" here marked with global context
                a = 2
                repeat 1, a: 3
                        display 'parameter: ','0'+a,10  ; "a" here also marked with global context, but preprocessing takes precedence
                end repeat
        end namespace
end macro    
Here REPEAT makes a parameter for preprocessing which is replaced with the value "3" before any actual assembly takes place and it replaces the token "a" with a plain number (this is also another demonstration why unconditional macro can bring chaos to your definitions).

And LOCAL directive also defines parameters, so they take precedence over anything else.
Post 14 Dec 2019, 10:15
View user's profile Send private message Visit poster's website Reply with quote
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 14 Dec 2019, 11:19
thx Smile.
Post 14 Dec 2019, 11:19
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.