On Thu, 08 May 2008, frank van nuffel wrote:

Hi Frank,

[...]

> For whomever wonders what applicability pp evaluation precedence
> modification is useful for, here's a quick idea regarding how to define pp
> macro's that are suspendable and resumable at specific places in source
> code, and that avoid to also substitute a corresponding function definition,
> for the case where this macro was suspended, leading to the effect that the
> macro behaves just like a normal function call (for which the corresponding
> function needs to be defined somewhere)
> 
> --- system definitions ----- 
> 
> #xTRAN                   ppparam( , <f>, <b>, [<a,...>] ) => ;
> PPIIF( %% _SUSPEND_(), <f>(<a>,), <b> )
> 
> // removing %% in line above leads to wrong results
> 
> # TRAN   function   ppparam( , <f>, <b>,           ) => func <f>
> # TRAN   function   ppparam( , <f>, <b>,  <a,...>  ) => func <f> ; PARAM <a>
> 
> # TRAN  procedure   ppparam( , <f>, <b>,           ) => proc <f>
> # TRAN  procedure   ppparam( , <f>, <b>,  <a,...>  ) => proc <f> ; PARAM <a>
> 
> #xCOMM  MACRO SECTION BEGIN  => #undef  _EXPAND_
> #xCOMM  MACRO <f>( [ <a,...> ] ) <b> => #define <f>( <a> )  ;
>    ppparam( _EXPAND_(), <f>, <b>, <a> )
> #xCOMM  MACRO SECTION END       => #define _EXPAND_()
> 
> #xCOMM  MACRO SUSPEND  =>  #xTRAN  _SUSPEND_\\()   =>  .T.
> #xCOMM  MACRO RESUME    =>  #xTRAN  _SUSPEND_\\()   =>  .F.
> 
> #xTRAN  _SUSPEND_() =>  .F.
> 
> #xTRAN  %% =>
> 
> #xTRAN  PPIIF( <x>, <a>, <b> ) => <b>
> #xTRAN  PPIIF(  .T. , <a>, <b> ) => <a>

In this example using 1_ instead of %% also works anyhow it can be
written in simpler way. But first please note that in Clipper it's
not possible to use #undef <NAME> inside result pattern because if
<NAME> is defined then it is substituted. I can only guess that the
above is some type of mixed Clipper and old PP code. If you want to
use #undef in such way using Clipper's PP then you have to put it
in a separate file and use #include directive.
Now alternative version:

--- system definitions ----- 

#xCOMM  MACRO SECTION BEGIN   => #undef _EXPAND_
#xCOMM  MACRO <f>( [ <a,...> ] ) <b> => #define <f>( <a> )  ;
               ppparam( _EXPAND_ <f> | <b>, <a> )
#xCOMM  MACRO SECTION END     => #define _EXPAND_

#xCOMM  MACRO SUSPEND         => #undef _EXPAND_
#xCOMM  MACRO RESUME          => #define _EXPAND_

#xTRAN  ppparam( _EXPAND_ <f> | <b> [, <a,...>] ) => <b>
#xTRAN  ppparam(          <f> | <b> [, <a,...>] ) => <f>( <a>, )

# TRAN  function  ppparam( [_EXPAND_] <f> | <b> [, <a,...>] ) => ;
        func <f> ; PARAM <a>
# TRAN  procedure ppparam( [_EXPAND_] <f> | <b> [, <a,...>] ) => ;
        func <f> ; PARAM <a>

--- end of system definitions ----- 

It gives the same results is much faster and IMHO simpler.
It's for Harbour only. If you want to adopt it to Clipper then you have
to make the trick with #include I've written above: create file undef.ch
with one line:
   #undef  _EXPAND_
and in the above code change:
   #undef  _EXPAND_
to:
   #include "undef.ch"
Such tricks makes also class(y).ch
I intentionally haven't used TRANS rules because each time you call
MACRO SUSPEND / MACRO RESUME new rules are added and the PP table is
systematically growing up reducing the memory for compiler and slowing
the preprocessing. Clipper's PP does not have #untrans directive.
But if you change it to use TRANS then it will not be necessary to
make the trick with #include.

> since neither in ca-clipper/harbour it is possible to apply P.J. Plauger's
> suggestion to avoid macro defines to trigger upon corresponding function
> definitions as he does in his C implementations, the only viable alternative
> i've found so far, is sth like above; in C it is enough to do:
> 
> #define someMacro( a, b ) a+b
> 
> int (someMacro)( int a, int b ) // definition (guarded against substitution)
> { ...

In this code you make two different tricks to disable infinite translation.
1-st you added additional dummy parameter to function call so instead
     of fun2( 3, 5 ) we have fun2( 3, 5, ) and this is not recognized
     by #define declaration
2-nd for function declaration you moved parameters to PARAM statement.

Such tricks are possible if you have alternative syntax which is not
affected by your PP rules. Just like the above trick in C which is
also for one situation only and resolves the problem by alternative
code.
If you need general solution then we should introduce new PP token
which is significant for PP but neutral for compiler. F.e. <->
as result marker.

   #trans func( <a,...> ) => func( <-> 1, <a> )

The <-> in result pattern will block infinite translation and because
it will be invisible for compiler then it will not break compilation
process. I can add such marker in the future.

best regards,
Przemek
_______________________________________________
Harbour mailing list
Harbour@harbour-project.org
http://lists.harbour-project.org/mailman/listinfo/harbour

Reply via email to