flat assembler
Message board for the users of flat assembler.

Index > Macroinstructions > [fasmg] How to obtain the current namespace?

Author
Thread Post new topic Reply to topic
Jessé



Joined: 03 May 2025
Posts: 143
Location: Brazil
Jessé 18 Jul 2026, 16:02
Is there a native way where one can obtain - for conventional macro or CALM usage - the current namespace's full name as text (or something that maybe can be turned into text)?

I kind of got it working with the example below, but it clearly has its limitations, and also (I suppose) it has to grow too big (and probably slow at a medium scale project) to do something completely reliable:

Code:
define __NAMESPACE__

calminstruction ? line&
        local symbol, any
        match .symbol: any?, line
        jyes store_sub
        match symbol: any?, line
        jyes store_namespace
        match =namespace? symbol, line
        jyes store_namespace
    unchanged:
        assemble line
        exit
    store_sub:
        arrange symbol, __NAMESPACE__.symbol
    store_namespace:
        local nvar
        arrange nvar, =__NAMESPACE__
        publish nvar, symbol
        assemble line
end calminstruction

macro show_namespace
    match a, __NAMESPACE__
        display "Namespace: ", 27, "[32m", `a, 27, "[0m", 10
    else
        display 27, "[33mNo namespace currently defined.", 27, "[0m", 10
    end match
end macro

show_namespace

Start:  show_namespace

namespace ENCLOSED
    show_namespace
end namespace

Next:
    .subordinate:   show_namespace
    


Quote:

artix-avlt:[jesse6]:~/ASM64/fasm2_latest/tests$ fasmg.x64 namespace_name.asm
flat assembler version g.l7xm
No namespace currently defined.
Namespace: Start
Namespace: ENCLOSED
Namespace: Next.subordinate

1 pass, 0 bytes.


Thanks in advance,

_________________
jesse6
Post 18 Jul 2026, 16:02
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8550
Location: Kraków, Poland
Tomasz Grysztar 18 Jul 2026, 16:28
There is no general way, as generally the namespace may not have a name at all (the root namespace is the simplest example, the namespaces used by regular macro's LOCAL are another, and they are not even attached to the root).

The "show_symbol_name" function in console.inc is the only place where the engine even attempts to recover the symbol name in some form, and you can see in that code that it has many exotic cases to consider (and they cannot have a form that could be used in the source text to access them).

Whatever the problem you're trying to solve this way, it probably needs a revised assumptions to not fight against the design of fasmg's architecture.

Note that I intentionally designed fasmg in such way, that it is not possible to refer to the root and escape the namespace that you get enclosed with. You can only have relative references, no absolute ones. This allows things like assembling multiple project enclosed in separate boxes in a single controlling source, which can then take the output of each one and encode it into a .ZIP package with all generated files, etc. And every such project in turn can also be enclosed in a namespace controlled by another layer, and it is always possible to do it in such way, that the inner projects are not aware of the outer controllers.
Post 18 Jul 2026, 16:28
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8550
Location: Kraków, Poland
Tomasz Grysztar 18 Jul 2026, 16:41
A few notes concerning your example: to catch labels it's much better to use the label interceptor, like:
Code:
calminstruction (name) ? &line&    
Then it's not needlessly called for every line and does not impact the performance so much. The NAMESPACE can be intercepted with a direct macro. And also, "Next.subordinate" in your example does not become a base for any other symbols, not unless you use it in NAMESPACE statement. And entering the namespace in NAMESPACE is different from having the base label for symbols starting with dot, these are two separate attributes of the context. After "Start:" definition "Start" becomes base for the dot-prefixed names, but current namespace is still root.
Post 18 Jul 2026, 16:41
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 143
Location: Brazil
Jessé 18 Jul 2026, 17:43
Quote:

Whatever the problem you're trying to solve this way, it probably needs a revised assumptions to not fight against the design of fasmg's architecture.


Yes, there is a single situation I got here where being able to catch the current namespace's name will be useful. But, it can easily be redesigned for sure.
Then, since this situation had intrigued me (since it was something I hadn't thought about or needed before), I decided to push the main develop aside, and try to find a way to got working what I've posted here.


Quote:

A few notes concerning your example: to catch labels it's much better to use the label interceptor, like:
Code:
Code:
calminstruction (name) ? &line&    
    


I must mention that I misunderstood how to use this: I thought that it was only used to return value to whatever '(enclosed)' contains; But, according to your explanation, it behaves the same as 'struc (name) ? &line&', but at CALM, right?

The example above points how I think it should be used (and results expected):

Code:
; CALM label interceptor

calminstruction (name) ? &line&
    local cmd
    arrange cmd, name line
    assemble cmd
    local text, command
    arrange text, name
    arrange command, line
    stringify text
    stringify command
    display "Catching:  " bappend 27 bappend "[1;32m" bappend text bappend 27 bappend "[0;33m " \
        bappend command bappend 27 bappend "[0m" bappend 10
end calminstruction

macro show_msg msg&
    display 27, "[1m", `msg, 27, "[0m", 10
end macro

; All labels below should be catched
Start:

EQUATE equ 1999 + Start
NUMBER = 100

Next:
    .subordinate:
    .sub_data db ?

show_msg This should not be catched, because it isn't and it doesn't contain a label.

            dd ?    ; This also shouldn't

            mov     eax, eax    ; Neither these
            ret                 ;

.end.next:  cli                 ; This should be catched.
            hlt                 ; but this shouldn't

; Compile with fasm2!
    


And its behavior:
Quote:

artix-avlt:[jesse6]:~/ASM64/fasm2_latest/tests/CALM$ fasm2 label_intercept.asm
flat assembler version g.l7xm
Catching: Start :
Catching: CONST equ 1999 + Start
Catching: NUMBER = 100
Catching: Next :
Catching: .subordinate :
Catching: .sub_data db ?
This should not be catched, because it isn't and it doesn't contain a label.
Catching: .end.next : cli

1 pass, 11 bytes.



By knowing that, I think I'm good to even try to get this futher, or try something new.

Many thanks for the explanations...
Post 18 Jul 2026, 17:43
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8550
Location: Kraków, Poland
Tomasz Grysztar 18 Jul 2026, 17:58
Jessé wrote:
I must mention that I misunderstood how to use this: I thought that it was only used to return value to whatever '(enclosed)' contains; But, according to your explanation, it behaves the same as 'struc (name) ? &line&', but at CALM, right?
Yes, it's exactly that. It's called "labeled instruction" in the manual, and is a separate symbol class (distinct from regular instructions).
And to only catch plain labels you may need something like "match : any?, line" in there.
Post 18 Jul 2026, 17:58
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 143
Location: Brazil
Jessé 18 Jul 2026, 23:35
Sounds good. I've modified my test code to suit those aforementioned changes, and it is working fine, and, even better, intercepting only what it's needed!

And, a variant of the following are already in my 'test pipeline' with very good results:

Code:
        ; These interceptors should stay at the main include file!
        calminstruction (name) ? &line&
                        local cmd
                        match :== value, line
                        jyes append
                        match ==: value, line
                        jyes append
                        match == value, line
                        jyes append
                        match =equ? statement, line
                        jyes append
                        arrange cmd, name line
                        assemble cmd
                        exit
                append:
                        local property, empty
                        arrange empty,
                        arrange property, =default.=type.=direct.name
                        arrange cmd, name line
                        publish property, empty
                        assemble cmd
        end calminstruction

        calminstruction define? statement*&
                        local line, verify, property, empty
                        match .sym any?, statement
                        jno root
                        arrange sym, .sym
                        jump next
                root:
                        match sym any?, statement
                next:
                        arrange line, =define statement
                        arrange verify, =assert =defined sym
                        arrange empty,
                        assemble line
                        assemble verify
                        arrange property, =default.=type.=direct.sym
                        publish property, empty
        end calminstruction
    


To share with you my main idea, I've brought back that very old quest I had about distinguishing types of labels, and, now, I've got a lot of successful attempts (yes, more than one approach, and all of them achieving what is desired) that gives me almost 100% of what I need. But now, I have an even better idea (from that of my past attempt), that will be also distinguishing adressable labels from data labels, which referes to 'label:' as addressable, and 'label struc data' or 'label db data' as data labels.
This is the easiest to differ, because data labels have size > 0, and then, size may be used to distinguish them. What I need something to be able to separate, is the group that I informally call "constant labels" (yes, I know that only one of them is really a constant) from the "addressable" group, because both have size 0. So, I append a "property" in the form of a definition to any of those 5 types of statements that not define a label as 'label:' does, to distinguish them.
It is already working, and a function that uses the (incredible and versatile) advanced CALM match features, can strip other types to remain a 'match n:name, dest, :' (or similar) statement to be able make the distinction followed by a 'check defined' statement.
During this explanation, I'm thinking of an even (maybe?) better approach, but I need to test it first.
Regarding adding a property to "label:" instead.

Yes, I remember that I can use some kind of 'elementary 'org' directive approach', but that way always messes up with something else that I need to exempt/alter further, in a kind of a chain reaction, and including damaging standard fasm2 stuff, which I really don't like to touch to suit my personal customizations. So, the above are not the cleanest, but a most stable (and compliant) approach.
Post 18 Jul 2026, 23:35
View user's profile Send private message Visit poster's website Reply with quote
Jessé



Joined: 03 May 2025
Posts: 143
Location: Brazil
Jessé 19 Jul 2026, 03:23
This "final" (or not) second approach gave me the exact control I need (so far):

Code:
        define __ROOT_LABEL_NAMESPACE__
        calminstruction (name) ? line&
                        local cmd, instructions
                        match := instructions?, line
                        arrange cmd, name line
                        assemble cmd
                        jyes append
                        match :, line
                        jyes append
                        exit
                append:
                        local property, empty, symbol
                        arrange empty,
                        match .symbol, name
                        jno ns_switch
                        arrange property, =default.=type.=address.__ROOT_LABEL_NAMESPACE__.symbol
                        publish property, empty
                        exit
                ns_switch:
                        arrange property, =default.=type.=address.name
                        publish property, empty
                        arrange __ROOT_LABEL_NAMESPACE__, name
                        local text
                        arrange text, name
                        stringify text
                        display "Switched label namespace to: " bappend text bappend 10
        end calminstruction
    


I also acknowledge that 'namespace' tracking can be done with:

Code:

calminstruction unwind.from.namespace
        local text
        take , __ROOT_LABEL_NAMESPACE__
        arrange text, __ROOT_LABEL_NAMESPACE__
        stringify text
        display "Switched namespace to: " bappend text bappend 10
end calminstruction

macro namespace? name*
        define __ROOT_LABEL_NAMESPACE__ name
        display "Switched namespace to: ", `name, 10
        esc namespace name
end macro

macro end?.namespace?
        esc end namespace
        unwind.from.namespace
end macro
    


But I have figured out that there's a difference on how things behave inside a 'namespace' block, as stated by Tomasz.
Well, so far, the current achievement (regarding common labels only) is enough for me to follow up with what I intended.
(Maybe should I mark this post as 'solved'?)

Thanks again for the very helpful clarification!
Very Happy
Post 19 Jul 2026, 03:23
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-2026, Tomasz Grysztar. Also on GitHub, YouTube.

Website powered by rwasa.