flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [SOLVED] Pascal-like begin…end syntax

Author
Thread Post new topic Reply to topic
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 30 Jul 2015, 22:32
Finally having a little spare time to do something useless, I decided to dive into FASM macros again and try to make macros that would allow Pascal-like syntax. For example:

Code:
procedure MyProc
begin
; Some ASM code here
end    


The task seemed to be pretty simple:
1) save some information within procedure macro;
2) inside the procedure macro create 2 other macros: begin and end;
3) make begin and end macros put prologue and epilogue;
4) remove begin and end macros’ definitions from within end macro.

The first problem (and the fatal one) is that one can’t purge a macro from within the macro itself. I tried something like this:

Code:
macro procedure Header&
{
common

  ; blah-blah some irrelevant code here

  macro procedure_initialize
  \{
    macro begin
    \\{
      display 'Custom begin macro', 13, 10
    \\}
    macro end
    \\{
      display 'Custom end macro', 13, 10
      procedure_finalize
      purge procedure_initialize, procedure_finalize
    \\}
  \}
  macro procedure_finalize
  \{
    purge begin, end
  \}
  procedure_initialize
}    


… which is a stupid attempt to use a commonly used pattern for recursive macro definitions plus some code trying to remove all the internal junk when the end macro is reached.

So, my goal is:
1) have a macro which represents header of a block (e.g. procedure);
2) have two macros, begin and end, which are available only after the block header and only once (until the next header is reached);
3) remove all the internal definitions those 3 macros created after the end macro is reached (so that the macro definitions’ stack doesn’t grow too large).

Is it actually possible with FASM, and what’s the right direction here?


Last edited by DimonSoft on 13 Aug 2015, 14:24; edited 1 time in total
Post 30 Jul 2015, 22:32
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 31 Jul 2015, 00:11
DimonSoft
There's a simple way to create a single-shot macro:
Code:
macro single_shot {}
macro single_shot
{
    single_shot
    purge single_shot
}    

Though it's not quite nesting friendly, which is what you're gonna need. Anyway I'd recommend you to restrain from that.

Following is an architecture you'd be good with:
Code:
match ,
{
    local begin_ctx,  end_ctx,\
          begin_stub, end_stub,\
          begin_proc, end_proc
    
    macro begin_stub
    \{
        display 'Error: begin context not defined',13,10
        err
    \}
    
    macro end_stub
    \{
        display 'Error: end context not defined',13,10
        err
    \}
    
    define begin_ctx begin_stub
    define end_ctx   end_stub

    macro begin \{ match b,begin_ctx \\{ b \\} \}
    macro end args&
    \{
        match ,args
        \\{
            match e,end_ctx \\\{ e \\\}
            restore begin_ctx,end_ctx
            rept 0 \\\{
        \\}
        match,\\{ end args \\}
    \}
    
    ;here you can start defining contexts such as procedure
    macro procedure
    \{
        define begin_ctx begin_proc
    \}
    
    macro begin_proc
    \{
        define end_ctx end_proc
        display 'Prologue',13,10
    \}
    
    macro end_proc
    \{
        display 'Epilogue',13,10
    \}
}    

Here you have shared identifiers begin_ctx and end_ctx to hold the context of the begin-end pair. If there's no context, the stub macros are invoked.

An important part here is that you can define data shared between paired macros inside the local identifiers and still the data is not available from outside. Additionally you avoid large macro definition-purging-redefinition overhead otherwise induced for each begin-end pair. Moreover nesting-friendliness is by design.

P.S. And note that you need to preserve the original functionality of the end directive (end if, end while, etc.) as shown in the code above.

_________________
Faith is a superposition of knowledge and fallacy
Post 31 Jul 2015, 00:11
View user's profile Send private message Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 01 Aug 2015, 17:20
l_inc

Thanks, this match trick reminds me of the Javascript anonymous functions and looks amazing. Thanks for the idea.

But I’m afraid, even with prepsrc tool, I don’t get how it solves the problem of using standard end if- and end while-like structures. And I can’t see where does the rept 0 statement end. Could you explain this in more detail, please?

I tried this code:
Code:
if eax eq
procedure
begin
end
end if    


and got this output from prepsrc:
Code:
if eax eq
;procedure
;define begin_ctx?TE begin_proc?TI
;begin
;match b,begin_proc?TI{b}
;begin_proc?TI
;define end_ctx?TF end_proc?TJ
display 'Prologue',13,10
;end
;match,
;{
; match e,end_ctx?TF \{ e \}
; restore begin_ctx?TE,end_ctx?TF
; rept 0 \{
;}
;match e,end_proc?TJ{e}
;end_proc?TJ
display 'Epilogue',13,10
;restore begin_ctx?TE,end_ctx?TF
;rept 0{
; match,{end}
;end if
;match,if
;{
; match e,end_ctx?TF \{ e \}
; restore begin_ctx?TE,end_ctx?TF
; rept 0 \{
;}
;match,{end if}
end if
    
Post 01 Aug 2015, 17:20
View user's profile Send private message Visit poster's website Reply with quote
DimonSoft



Joined: 03 Mar 2010
Posts: 1228
Location: Belarus
DimonSoft 01 Aug 2015, 17:38
UPD. Oops, found the description of the preprocessor bug/feature which makes such rept 0 work as “ignore everything until the next closing curly bracket”, in this case—ignore the next match.

So, am I right if I say that the pattern you’ve suggested makes work the end macro this way (as currently implemented)?
1) makes it a part of begin-end pair, if no arguments are given;
2) leaves any end anything statements the way they are taking advantage of the “less-nested” end anything implementation.
Post 01 Aug 2015, 17:38
View user's profile Send private message Visit poster's website Reply with quote
l_inc



Joined: 23 Oct 2009
Posts: 881
l_inc 02 Aug 2015, 00:58
DimonSoft
Quote:
Oops, found the description of the preprocessor bug/feature

Well, it's definitely not a bug, cause the behavior is documented and expected. I'd say it's a side effect of the preprocessor design, though this kind of use cases could very well be one of the author's intentions.

Quote:
So, am I right if I say that the pattern you’ve suggested makes work the end macro this way (as currently implemented)?

Yes, you are perfectly right.

_________________
Faith is a superposition of knowledge and fallacy
Post 02 Aug 2015, 00:58
View user's profile Send private message 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-2025, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.