flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [fasmg] outscope persistent

Author
Thread Post new topic Reply to topic
MaoKo



Joined: 07 May 2019
Posts: 100
Location: Paris/French
MaoKo 27 Oct 2019, 16:21
Hello! Today I'm figure out that many of my macro work not very well in certain context. Especially those who have the '!' prepended to it for unconditional expansion. For instance:
Code:
macro _iterate_string?! parameter?*, text?*
  local char, start, iterator
  must_string (text)
  start = $00
  iterator equ parameter
  match it =: begin, parameter
    must_numeric (begin)
    start = begin
    iterator equ it
  end match
  repeat (lengthof (text) - start), i:start
    char =: string (((text) shr ($08 * i)) and $FF)
  end repeat
  match it, iterator
    macro invoker?!
      outscope irpv it, char
    end macro
  end match
  invoker
end macro

macro end?._iterator_string?
  end irpv
end macro
    

must_??? is kind of assert (eqtype). The problem is that I can only call these macro outside of any macro definition cuz of the invoker?"!" macro. If I want to be able to call these macro inside a macro definition I need the delete the "!" but I can't call them outside. I'ts like a big dilemma. In fact, if I'm sure that irpv body is entered at least one time, I don't need of "!" anymore. But _iterate_string accept empty string. Thereby I can't predict and I must add "!" to the end?._iterate_string?! and also to the _iterate_string?! macro cuz of the code:
Code:
if $00
  _iterate_string A, "..."
  end _iterate_string
end if
    

If you have solution, I would glad to hear it Smile. I have thought of two kind of outscope instruction. Maybe the standard outscope that get vanish after an unconditional expansion and a new outscope! that get persistent after uncond expansion.
Post 27 Oct 2019, 16:21
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 27 Oct 2019, 18:46
I believe that the interaction of OUTSCOPE with macro nesting was not implemented properly. Even the example from the manual was not behaving well.

I therefore tried correcting the implementation, please try this with the new "ipyd0" release:
Code:
macro _iterate_string?! parameter?*, text?*
  local char, start, iterator
  ;must_string (text)
  start = $00
  iterator equ parameter
  match it =: begin, parameter
    ;must_numeric (begin)
    start = begin
    iterator equ it
  end match
  repeat (lengthof (text) - start), i:start
    char =: string (((text) shr ($08 * i)) and $FF)
  end repeat
  match it, iterator
    macro invoker?!
      esc outscope irpv it, char
    end macro
  end match
  outscope invoker
end macro

macro end?._iterate_string?!
  end irpv
end macro    
Note that to make the OUTSCOPE apply to inner macro, ESC has to be used now (the correction I made causes the OUTSCOPE to be dropped when a text generated by a macro becomes a part of a new macro). Also the "invoker" needs another OUTSCOPE, to forward the context further.

Anyway, this still does not solve problems with using it inside an IF $00 block, because END IRPV is not paired correctly then. But I believe this can be easily corrected, and it even simplifies the macro a little:
Code:
macro _iterate_string?! parameter?*, text?*
  local char, start, iterator
  ;must_string (text)
  start = $00
  iterator equ parameter
  match it =: begin, parameter
    ;must_numeric (begin)
    start = begin
    iterator equ it
  end match
  repeat (lengthof (text) - start), i:start
    char =: string (((text) shr ($08 * i)) and $FF)
  end repeat
  match it, iterator
    outscope irpv it, char
end macro

macro end?._iterate_string?!
    end irpv
  end match
end macro     
Post 27 Oct 2019, 18:46
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 27 Oct 2019, 19:08
Ty very much Tomasz. It's help me a lot because I duplicate several macro to bypass this.
Post 27 Oct 2019, 19:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 27 Oct 2019, 19:21
Thank you for pointing this out! This was also affecting my IRPS macro, which I obviously have not been using enough myself. Smile
Post 27 Oct 2019, 19:21
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 29 Oct 2019, 21:41
Hi!. I just figure out that in my first example it's only need "esc" before macro defined with ! to get's work in macro def body. I'm sorry, I didn't known about this "esc" usage.
And also why the outscope get vanish in inner macro def ???

Have a good day Smile


Last edited by MaoKo on 29 Oct 2019, 22:17; edited 1 time in total
Post 29 Oct 2019, 21:41
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 29 Oct 2019, 22:08
MaoKo wrote:
Hi!. I just figure out that in my first example it's only need "esc" before macro defined with ! to get's work in macro def body. I'm sorry, I didn't about this "esc" usage.
And also why the outscope get vanish in inner macro def ???
This is in fact what I corrected in the implementation. Because OUTSCOPE is a modifier that only really affects a line generated by macro, it should also be removed at that point. When previously it was not removed, it could be passed to the text of some other macro (for example when you used an unconditional macro inside a definition of another macro), where it was causing incorrect behavior.

And ESC in general allows to ensure that something becomes part of the text of a macro. It also handles respects nesting, so as long you have an inner macro completely enclosed in an outer one, you do not need to use constructions like ESC ESC (unlike the backslashing in fasm 1, for example).

Some of the nuances may be not documented properly yet, this is because I keep experimenting with some corner cases and I only define them in the manual after I'm sure I arrived at a good design.
Post 29 Oct 2019, 22:08
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8353
Location: Kraków, Poland
Tomasz Grysztar 30 Oct 2019, 15:32
After giving this some more thought I found another solution.

This is a simple trick that allows to handle nesting properly without making the main macro unconditional. Because it is much safer to not have it unconditional and only unroll it when the arguments really require processing. Unconditional macros are tricky and may cause many kinds of unwanted interactions, so it is better to reduce them to minimum.

I updated my IRPS macro to use the new trick:
Code:
macro irps_as_irpv parameter*, text&
        local buffer,symbol  

        define buffer text   
        while 1   
                match car cdr, buffer   
                        define symbol car   
                        define buffer cdr   
                else   
                        match any, buffer   
                                define symbol any   
                        end match   
                        break   
                end match   
        end while   

        outscope irpv parameter, symbol
end macro 

macro irps?! arguments&
        macro irpv!
                purge irpv
        end macro
        irpv
        outscope irps_as_irpv arguments
end macro

macro end?.irps?! 
        end irpv 
end macro    
It uses a trick with self-purging macro to make IRPV be paired properly with END IRPV generated by END IRPS even when we are in a skipped area of source (like inside an IF 0 block).

When the directive is in skipped code, the IRPV line is seen and is counted for END IRPV pairing. When the directive is in processed code, the macro gets defined and subsequent IRPV line ends up calling that macro (which just purges itself), and then the main conditional macro parses the arguments and opens the actual IRPV block.

I recommend this method, it should be more reliable.
Post 30 Oct 2019, 15:32
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 30 Oct 2019, 16:48
Haha yeah, you are right. I find this pretty funny Smile. It's interesting to note that the argument doesn't matter for pairing.
Post 30 Oct 2019, 16:48
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.