flat assembler
Message board for the users of flat assembler.

Index > Main > [fasmg] Troubles with defined/definite

Goto page 1, 2  Next
Author
Thread Post new topic Reply to topic
Calanor



Joined: 19 Jul 2015
Posts: 45
Location: Sweden
Calanor 13 Jan 2021, 16:33
I'd like to use a variable as the argument to be sent to "format", e.g. "define var PE64 GUI". First I need to check if "var" has been defined at all. However, as the name of the variable is replaced with its value, defined/definite gets cranky about the extra "GUI" at the end of the line. Is there any way to solve this without resorting to match etc?

[Edit] Guess I am rusty, I forgot about "match =var, var". However, I still need to send the contents of "var" to format. As of now, I am using CALM to arrange and assemble the line, but I feel that I might be missing/forgetting something here.
Post 13 Jan 2021, 16:33
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 13 Jan 2021, 17:05
You cannot use DEFINED/DEFINITE operators to check the status of symbolic variables, because they are preprocessed before the text of the condition is evaluated. So if you "define var PE GUI", then "if definite var" becomes "if definite PE GUI" before the condition is evaluated, and you end up actually checking whether symbol named "PE" has been defined, with "GUI" appended at the end of condition and causing a syntax error. This actually ends up working quite similarly as it was in fasm 1 with regard to symbolic variables and expression evaluation.

However if you are using CALM, there is a simple trick that allows to check whether a symbol has a value assigned, even a symbolic one. See what the manual says about the TAKE command:
fasmg manual, section 15 wrote:
If the destination symbol is the same as source, the result flag can be used to check whether there is an available value without affecting it.
Post 13 Jan 2021, 17:05
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 13 Jan 2021, 17:13
A simple demonstration:
Code:
define var ; this is to make CALM code see "var" as global symbol

calminstruction Format
        take var,var
        jyes use_var
        ; here handle a case when var is not defined
        exit
    use_var:
        local cmd
        arrange cmd, =format var
        assemble cmd  
end calminstruction

restore var ; remove temporary definition

; now test it:
define var PE GUI
Format    
Post 13 Jan 2021, 17:13
View user's profile Send private message Visit poster's website Reply with quote
Calanor



Joined: 19 Jul 2015
Posts: 45
Location: Sweden
Calanor 13 Jan 2021, 17:22
I resorted to using "match =var, var", followed by the "default" format if no specific one was defined. If the match is false, some CALM-code kicks in order to properly send the argument to format. However, your solution is definitely prettier than mine Smile Thanks!
Post 13 Jan 2021, 17:22
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 13 Jan 2021, 17:23
There is also another method, which you would use if the identifier of the symbol to check for was provided at run-time to the instruction, for example as an argument to macro. Then you can use TRANSFORM and see whether any replacement has been made:
Code:
calminstruction Format symbol
        transform symbol
        jyes use_var
        ; here handle a case when symbol is not defined
        exit
    use_var:
        local cmd
        arrange cmd, =format symbol
        assemble cmd  
end calminstruction

; now test it:
define var PE GUI
Format var    
Post 13 Jan 2021, 17:23
View user's profile Send private message Visit poster's website Reply with quote
Calanor



Joined: 19 Jul 2015
Posts: 45
Location: Sweden
Calanor 13 Jan 2021, 17:27
I did use transform, but it never occurred to me to actually check the flag. Interesting approach!
Post 13 Jan 2021, 17:27
View user's profile Send private message Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 30 Mar 2023, 14:06
i do this
Code:
calminstruction initsymndef? name*, def&
        take name, name
        jyes _err
        publish name, def       
        exit    
_err:
        err "!! symbol already defined"
end calminstruction

initsymndef foo, FOOBAR

    


and get :
Custom error: !! symbol already defined.


... not what I expected !

intent : check if some symbol already has some value (foo in sample above),
and only if not, then define it
... I also tried replacing 'take name, name' with 'transform name'
but result is the same...

tx 4 help

Tomasz, wud u pls clarify why ? I thought above discussion was pointing to this...
... but getting confused....
Post 30 Mar 2023, 14:06
View user's profile Send private message Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 30 Mar 2023, 14:17
... also, to show msg in calm using display command, how wud i go about adding CRLF at the end ??
Code:
display "!! symbol already defined",13,10 
    


does not work...
Post 30 Mar 2023, 14:17
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 Mar 2023, 14:25
Your TAKE command applies to symbol "name". The name "foo" is the text of the value that has been assigned to "name" symbol - the TAKE does not check the existence of value of "foo", it looks for the presence of value of "name".

As for TRANSFORM, it is only going to do something when the name has been assigned a symbolic value - but this is what you're doing, so it's not an issue in your case. I think what has thrown you off is that the symbols can be forward-referenced - it is the classic case of "if symbol is not defined, then it's defined" paradox - note that you likely get an error message about exceeding the allowed number of passes. If you do anything to prevent forward-references (for example execute your PUBLISH line twice), the "oscillation problem" should go away. See my articles about multi-pass assembly for other methods of dealing with this kind of issues. Going even further back, the manual for fasm 1 has a section that discusses the "if ~ defined" issue in its most basic form.
Post 30 Mar 2023, 14:25
View user's profile Send private message Visit poster's website Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 Mar 2023, 14:27
fabbel wrote:
... also, to show msg in calm using display command, how wud i go about adding CRLF at the end ??
Code:
display "!! symbol already defined",13,10 
    


does not work...
Either:
Code:
display "!! symbol already defined"
display 13
display 10 
    
or:
Code:
display "!! symbol already defined" bappend 13 bappend 10 
    
You could also customize the DISPLAY command to allow the verbose syntax:
Code:
calminstruction calminstruction?.display? list&
    loop:
        match item=,list, list
        jno final
        arrange item, =display item
        assemble item
        jump loop
    final:
        arrange item, =display list
        assemble item
end calminstruction    
Post 30 Mar 2023, 14:27
View user's profile Send private message Visit poster's website Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 30 Mar 2023, 14:44
tx vm
..i resorted to using 2x publish command then ...
Code:
calminstruction initsymndef? name*, def&
        transform name
        jyes _err
        publish name, def       
        publish name, def       
        exit    
_err:
        display "symbol already defined" bappend 13 bappend 10
end calminstruction

initsymndef foo, FOOBAR

    



... which now works as expected .... i get the fwd ref issue, but must admit that the above syntax (having 2xpublish) looks kinda weird to me though...
Post 30 Mar 2023, 14:44
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 30 Mar 2023, 14:52
fabbel wrote:
... which now works as expected .... i get the fwd ref issue, but must admit that the above syntax (having 2xpublish) looks kinda weird to me though...
Another way to prevent forward references is to execute a RESTORE command for a given symbol before defining it. But yes, it looks weird, because it is just a workaround.

For numeric symbols the issue is solved through use of DEFINITE operator instead of DEFINED, but there is no analogous facilities for symbolic values - which is exactly the problem mentioned by the OP. I've been in fact working on some additional operators for inspection of symbolic definitions, but it's an experimental branch that I'm still unsure about.
Post 30 Mar 2023, 14:52
View user's profile Send private message Visit poster's website Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 31 Mar 2023, 07:14
To generalize definite operator (which is for numeric variable only),
and check if some symbol - either symbolic or numeric - already has some value,
the below seems to be working (trying to circumvent fwd-referencing) :


Code:
struc (name) isdef? var*
        name = 0
        irpv v, var
                indx %%
                name = 1
                break
        end irpv        
end struc

; un-comment below symbolic / numeric to test
;foo equ FOOBAR
;foo = 1

chk_foo isdef foo


; un-comment below symbolic / numeric to test with/without fwd-ref
;foo equ FOOBAR
;foo = 1

repeat 1, d:chk_foo
        display 'chk_foo : ',`d,13,10
end repeat

    



Tomasz : can u pls comment ? Do u see any issue with the above ?

tx
Post 31 Mar 2023, 07:14
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 31 Mar 2023, 07:31
Looks great! Yes, IRPV is a very good solution, even if a bit tricky. It detects all kinds of values and never forward-references.
Post 31 Mar 2023, 07:31
View user's profile Send private message Visit poster's website Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 31 Mar 2023, 08:12
tx ! appreciated ( gratifying to see that am starting to understand a bit... but still... am about to post another question in another thread....)
Post 31 Mar 2023, 08:12
View user's profile Send private message Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 25 Jan 2024, 11:07
Hi Tomasz,

Any news regarding those 'experimental' operators that you previously referred to ?

I kinda feel those could be useful to address some topics/isues that have (re)surfaced in the forum on multiple occasions :

* check if variable hold symbolic value ?

* check if some text can be valid identifier ?
-> you already demontrated some macro / struc workaround in the form of 'struc isname' and 'struc isidentifier'
.. but wouldn't that be perfect case for such dedicted operator ?

* check if variable hold 'legal' computable text / value
-> not the same as defined / definite that will actually err (Error: invalid expression) if fed with non computable text
e.g. define var 1 2
-> aim here would be to check var contents and allow for some alternate handling if non computable
-> typ. in CALM, do 'compute var, var' if legally computable or alternate handling otherwise...
Post 25 Jan 2024, 11:07
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 25 Jan 2024, 12:05
Have you tried the experimental branch I linked previously? It needs to get all the latest fixed merged from the trunk, but otherwise it was already functional.
Post 25 Jan 2024, 12:05
View user's profile Send private message Visit poster's website Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 25 Jan 2024, 12:11
not yet tbh, was kinda waiting for the merge to signal that they were 'officialized' and here to stay ...
but will give it a try
.. to proceed could u pls give some more details
* list of new experimental operators introduced here
* quick use / syntax guide for each of those
tx
rgds
Post 25 Jan 2024, 12:11
View user's profile Send private message Reply with quote
fabbel



Joined: 30 Oct 2012
Posts: 84
fabbel 25 Jan 2024, 12:14
.... am especially interested in seeing how those can address the 3 points I mentionned above
Post 25 Jan 2024, 12:14
View user's profile Send private message Reply with quote
Tomasz Grysztar



Joined: 16 Jun 2003
Posts: 8359
Location: Kraków, Poland
Tomasz Grysztar 25 Jan 2024, 17:37
The operators implemented in the "calm3" branch are for testing values of symbolic variables, and for this reason they can only be used in CALM, because normally values of symbolic variables are replaced with corresponding text before the expression is evaluated. Only in CALM you have a chance to actually "catch" such variable, because there expressions are pre-parsed with hardcoded references to symbols.

__text checks whether the value of given variable is actually symbolic, that is: whether it's a tokenized text.
Code:
;fossil open https://flatassembler.net/fossil/repo/fasmg
;fossil checkout calm3

calminstruction show arg
        check   __text arg
        jno     error
        stringify arg
        display arg
        jump    done
        exit
    error:
        display 'non-symbolic value cannot be shown'
    done:
        display 10
        exit
end calminstruction

calminstruction demo
        arrange tmp, 3*7
        call    show, tmp
        compute tmp, tmp
        call    show, tmp
end calminstruction

demo    


__name additionally checks whether the text within a variable is a valid identifier of a symbol and without any additional tokens.
__nameofequ checks whether the text within a variable is an identifier of a defined symbol with symbolic value.
__nameofpriorequ checks whether the text within a variable is an identifier of a symbol with symbolic value defined earlier in the source.

Note that each of these consecutive operators performs the same check as the previous ones, with even more restrictions added. "__name x" cannot be true unless "__text x" is true, and so on.

Code:
;fossil open https://flatassembler.net/fossil/repo/fasmg
;fossil checkout calm3

__if_true equ if 1
__if_false equ if 0

calminstruction ifdef? name*
        check __name name & (__nameofequ name | defined name)
        jyes true
        assemble __if_false
        exit
    true:
        assemble __if_true
end calminstruction

calminstruction ifdefprior? name*
        check __name name & (__nameofpriorequ name | (~__nameofequ name & definite name))
        jyes true
        assemble __if_false
        exit
    true:
        assemble __if_true
end calminstruction


ifdef a
        display 'Yes'
else
        display 'No'
end if

ifdefprior a
        display 'Yes'
else
        display 'No'
end if

a equ 8    


__nameofmacro and __nameofpriormacro are analogous to __nameofequ and __nameofpriorequ, but they check for existence of an instruction symbol instead. Similarly __nameofstruc and __nameofpriorstruc check existence of labeled instructions.
Post 25 Jan 2024, 17:37
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:  
Goto page 1, 2  Next

< 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.