Author Topic: %$ vs %$$  (Read 33005 times)

Klod

  • Guest
%$ vs %$$
« on: August 08, 2010, 02:40:40 AM »
Quote
%push __CONTEXT__0
      %define %$ctxname  __CONTEXT__0
   %push __CONTEXT__1
      %warning %$ctxname %$$ctxname       ??
      %define %$ctxname  __CONTEXT__1
      %warning %$ctxname %$$ctxname
   %pop
      %warning %$ctxname %$$ctxname


Output:
C:\Define.asm:3: warning: __CONTEXT__0 __CONTEXT__0
C:\Define.asm:5: warning: __CONTEXT__1 __CONTEXT__0
C:\Define.asm:7: error: `ctxname': context stack is only 1 level deep

Is this something I missed reading about in the docs? or is this a bug?

regards Klod

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: %$ vs %$$
« Reply #1 on: August 08, 2010, 04:54:35 AM »
Think of each $ as an individual stack pointer with each additional $ reaching higher up into the context stack. It is an error to attempt to reach non-existant context stacks

%push contextA
%define %$name Moe

%push contextB
%define %$name Larry

%push contextC
%define %$name Curly

%warning %$name
%warning %$$name
%warning %$$$name

%pop
%pop
%pop

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: %$ vs %$$
« Reply #2 on: August 08, 2010, 07:30:54 AM »
Funny you should mention it. That issue is under discussion as we speak!

http://sourceforge.net/mailarchive/message.php?msg_name=4C5DA5E6.3080105%40kanios.net

As I understand the current plan...

Quote
   %warning %$ctxname %$$ctxname       ??
...
C:\Define.asm:3: warning: __CONTEXT__0 __CONTEXT__0

is about to become an error. IOW, if a context-local variable is not found in the current context, Nasm is no longer going to search the "upper" context for it. If this change is going to break your code, either fix your code or complain really soon!

Best,
Frank



Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: %$ vs %$$
« Reply #3 on: August 08, 2010, 06:24:48 PM »
IOW, if a context-local variable is not found in the current context, Nasm is no longer going to search the "upper" context for it.

Yep, that's the plan.

To be more explicit, if a context-local variable is not found in the referenced context, with the number of $ signs determining how many context levels up to reference starting from zero (%$), then NASM will no longer attempt to "search until I find something that may or may not be intended/relevant" across all contexts.

So this...
Code: [Select]
main.asm:14: warning: __CONTEXT__0 __CONTEXT__0
main.asm:16: warning: __CONTEXT__1 __CONTEXT__0
main.asm:18: error: `ctxname': context stack is only 1 level deep
main.asm:18: warning: __CONTEXT__0 %$$ctxname

... will become this...
Code: [Select]
main.asm:14: warning: %$ctxname __CONTEXT__0
main.asm:16: warning: __CONTEXT__1 __CONTEXT__0
main.asm:18: error: `ctxname': context stack is only 1 level deep
main.asm:18: warning: __CONTEXT__0 %$$ctxname

... and sanity will be restored.

As for the last %warning producing an error, Rob is correct, you are trying to reference a non-existent context via %$$ctxname, because you already %poped it prior to the last %warning.

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: %$ vs %$$
« Reply #4 on: August 08, 2010, 08:39:02 PM »
Code: [Select]
        %define %$arg1  [esp+4]
        test    eax,eax
        if      nz
                mov     eax,%$arg1
        endif

IMHO, a better fix to this bug would be to have a child context inherit the locals of the parent, then if need be we can modify the children and when we pop the child off the symbols return to the parent state. This would allow the code above, while also allowing %$$$$$blah direct access which is actually handy. For example:

Code: [Select]
%macro _F 1
%push
        %assign %$x %{1} ; Initialize %$x in the parent context.
        %push
                %assign %$x %{$x} * 4 ; Initialize %$x in the child context (%$x inherited parents value)
                %rep %{1}
                        ; %$x changes with each iteration but %{$$x} stays the same being of the parent context.
                        %assign %$x %{$x} + %{$$x}
                %endrep
                %warning %$x
        %pop
%pop
%endmacro
...
_F(  25 )
_F( 100 )

output would be something like..

Code: [Select]
test.asm:19: warning: (_F:8) 725
test.asm:20: warning: (_F:8) 10400

About Bryant Keller
bkeller@about.me

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: %$ vs %$$
« Reply #5 on: August 08, 2010, 08:54:59 PM »
IMHO, a better fix to this bug would be to have a child context inherit the locals of the parent, then if need be we can modify the children and when we pop the child off the symbols return to the parent state. This would allow the code above, while also allowing %$$$$$blah direct access which is actually handy.

It still doesn't change the fact that such implicit inheritance is outright unintuitive and error-prone :-\

Code: [Select]
%macro _F 1
%push
        %assign %$x %{1} ; Initialize %$x in the parent context.
        %push
                %assign %$x %{$$x} * 4 ; Initialize %$x in the child context (%$x inherited parents value)
                %rep %{1}
                        ; %$x changes with each iteration but %{$$x} stays the same being of the parent context.
                        %assign %$x %{$x} + %{$$x}
                %endrep
                %warning %$x
        %pop
%pop
%endmacro
...
_F(  25 )
_F( 100 )

The above [correct] form (%assign %$x %{$$x} * 4) works the same, is more intuitive and less prone to perpetuating bugs/errors.

Klod

  • Guest
Re: %$ vs %$$
« Reply #6 on: August 09, 2010, 02:55:14 AM »
Thanks all you guys for your answers,
Quote
Yep, that's the plan.

To be more explicit, if a context-local variable is not found in the referenced context, with the number of $ signs determining how many context levels up to reference starting from zero (%$), then NASM will no longer attempt to "search until I find something that may or may not be intended/relevant" across all contexts.

From a point of consistency and logic, this sort of thing should throw an error. As programmers we take great pains to define everything we have to and need. Imagine attempting to traverse multiple context stacks and you end up with a "default" value for the "current" context. This is when %$$$$ turns into %****

Regards
Klod

Klod

  • Guest
Re: %$ vs %$$
« Reply #7 on: August 09, 2010, 03:04:37 AM »
oops, missed this point in my earlier post.

Quote
As for the last %warning producing an error, Rob is correct, you are trying to reference a non-existent context via %$$ctxname, because you already %poped it prior to the last %warning.

I purposly put:
Quote
%pop
      %warning %$ctxname %$$ctxname

to show the different "behavior" when traversing "up" the context stacks vs. traversing down the stack. For political correctnes, it should trow an error both ways?

Regards
Klod

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: %$ vs %$$
« Reply #8 on: August 09, 2010, 03:36:37 AM »
For political correctnes, it should trow an error both ways?

IIRC, %warning/%fatal/%error are special in that they will dump something out as if it was a string, if it doesn't resolve to something else. If so, the above output that I posted is correct.

Klod

  • Guest
Re: %$ vs %$$
« Reply #9 on: August 09, 2010, 03:51:56 AM »
Hi Keith
Yes, that is how I thought it would work. I became aware of the above issue when a define in the child context failed and a value of the parent context was "assigned" to the failed define.

Regards
Klod

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: %$ vs %$$
« Reply #10 on: August 09, 2010, 04:27:32 AM »
It still doesn't change the fact that such implicit inheritance is outright unintuitive and error-prone :-\

Code: [Select]
%macro _F 1
%push
        %assign %$x %{1} ; Initialize %$x in the parent context.
        %push
                %assign %$x %{$$x} * 4 ; Initialize %$x in the child context (%$x inherited parents value)
                %rep %{1}
                        ; %$x changes with each iteration but %{$$x} stays the same being of the parent context.
                        %assign %$x %{$x} + %{$$x}
                %endrep
                %warning %$x
        %pop
%pop
%endmacro
...
_F(  25 )
_F( 100 )

The above [correct] form (%assign %$x %{$$x} * 4) works the same, is more intuitive and less prone to perpetuating bugs/errors.

Yes, less error prone... that is until you start writing macros in which the context spans multiple macros and you not only want to have macro local variables, but allow the users of your macros to have their own (like in your earlier if/endif example). ;)

About Bryant Keller
bkeller@about.me

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: %$ vs %$$
« Reply #11 on: August 09, 2010, 06:16:20 AM »
Yes, less error prone... that is until you start writing macros in which the context spans multiple macros and you not only want to have macro local variables, but allow the users of your macros to have their own (like in your earlier if/endif example). ;)

???

macro-local (%%) != context-local (%$)

Each macro invocation/call and context (%push) generates a unique prefix, one that is globally incremented in the preprocessor as to not conflict with each other.

Also, the fact that contexts can span across multiple macros makes more of a case against such a feature, as not everyone is a NASM preprocessor guru and can be (have been) easily tripped up by this unintuitive feature. This isn't a case of RTFM, this is a case of a poorly designed feature used to satisfy even poorer coding practices. It's syntactic sugar... laced with cyanide :P

Can you provide a detailed example of how this feature is exclusively beneficial?

Offline Bryant Keller

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 360
  • Country: us
    • About Bryant Keller
Re: %$ vs %$$
« Reply #12 on: August 10, 2010, 01:56:29 AM »
Not really, to be honest I've never even used the %$$...$ident forms before. Generally it's always been my practice not to use context variables outside of a macro other than in much more recently I've began using the %args/%local stuff from NASM itself which requires a context. I'm just saying that people have to become much more intimately familiar with your macros when you don't support inheritance. In the IF example, the user has to know that the context has changed.

About Bryant Keller
bkeller@about.me