flat assembler
Message board for the users of flat assembler.
Index
> Compiler Internals > [fasmg/fasm2]Predicted calm |
| Author |
|
|
Tomasz Grysztar 19 Mar 2026, 05:53
The LOCAL command in CALM instruction initializes the variable with a new value. As the manual states it:
fasmg manual wrote: ... is initally assigned a defined but unusable value. This is why the effect disappears if you remove the LOCAL command (even though the variable may still be local, unless a global symbol with the same name is declared). m_stery wrote: Was it even intended to call macros before defining them using prediction? I could perhaps change it so that LOCAL would only make the unusable value when the symbol has no value to begin with. Let me try and test it, although I'm not sure if making the behavior even more complex is the right way. |
|||
|
|
m_stery 19 Mar 2026, 13:30
Tomasz Grysztar wrote:
Leave it as it is. I was just testing what can and cannot be done. Basically nothing like local, or init, initsym from 'xcalm.inc' is executed until the instruction is defined if the command 'local' did not delete the previous one ... Code: calminstruction test? local i init i,0 ;the 'i' has a value 0 ... local i ;after this the 'i' has an unusable value ... end calminstruction BTW Isn't the result always true, when using 'check defined/definite some_local_var', where some_local_var has the unusable value? |
|||
|
|
Tomasz Grysztar 19 Mar 2026, 13:54
m_stery wrote: Basically nothing like local, or init, initsym from 'xcalm.inc' is executed until the instruction is defined To be even more precise, something like TAKE or COMPUTE is an ALM instruction that emits a CALM binary opcode into the compiled code of CALM macro. LOCAL is an ALM instruction that does not emit any CALM opcode, it only does something at the time of definition. Macros that you define in CALMINSTRUCTION namespace, like INIT/INITSYM are ALM instructions, evaluated at the time of definition. Such macros may in turn emit some instructions that generate CALM binary code, but INIT/INITSYM do no such thing. I tried to describe this in detail in the auxiliary documentation, but maybe another reframing, like my attempt above, could be a good addition to the manual. m_stery wrote: Isn't the result always true, when using 'check defined/definite some_local_var', where some_local_var is the variable, defined by calminstruction's local? BTW, for an interesting example of something that is only possible thanks to a forward-referenced macro, see my fasmg-specific quine. |
|||
|
|
m_stery 20 Mar 2026, 01:08
It's written exactly in the documentation.
"A symbol made local is initally assigned a defined but unusable value. " BTW: This is in the flat assembler g User Manual (line 2153 perhaps?) "initally" -> "initially" But I assumed wrongly: *CALM command 'local' would not overwrite an already valid value, and it does *CALM command 'take' would remove 'unusable', when it is not used as the value of another symbol. If no value to remove so nothing removed This CALMINSTRUCTION does what I wanted Code: test 1 ;Output: 1:1 test 2 ;Output: 2:2 calminstruction test?! arg local i,tmp take ,i jyes ready compute i,0 take ,i take i,i jyes ready compute i,0 ready: compute i,i+1 arrange tmp,arg:i stringify tmp display tmp bappend 10 compute tmp,i take i,tmp end calminstruction test 3 ;Output: 3:3 test 4 ;Output: 4:4 So the question is, can I initialize the variables before definition and return the last value after definition That was the original (useless) idea |
|||
|
|
Tomasz Grysztar 20 Mar 2026, 07:23
As I mentioned before, you could remove LOCAL and rely on implicit localness (when no global symbol with such name exists, a local one is used anyway), although this is only practical when you use a rarer name.
However, you could also make use of a symbol in a dedicated namespace controlled by you, something like: Code: test 1 test 2 define LINK test namespace testing define i ; force i to be in the "testing" namespace match test, LINK ; define instruction with global name calminstruction test?! arg local tmp take i,i jyes ready compute i,0 ready: compute i,i+1 arrange tmp,i:arg stringify tmp display tmp bappend 10 end calminstruction end match restore i ; after the definition is completed, we can bring back previous value (if any) end namespace test 3 test 4 Code: test 1 test 2 namespace testing define LINK i end namespace match i, testing.LINK ; get "i" with context of the "testing" namespace define i ; force i to be in the "testing" namespace calminstruction test?! arg local tmp take i,i jyes ready compute i,0 ready: compute i,i+1 arrange tmp,i:arg stringify tmp display tmp bappend 10 end calminstruction restore i ; after the definition is completed, we can bring back previous value (if any) end match test 3 test 4 While experimenting with various solutions, I discovered that PUBLISH does not follow the standard "symbol is defined" code path (and because of that INIT does not enforce symbol localness). I think I should correct it, since it is likely to be a relic of early CALM design iterations, but I need to do more tests to see if it would break anything. |
|||
|
|
m_stery 20 Mar 2026, 21:49
Thank you very much. I realize that I have often made very similar mistakes and did not see them. But now I finally see it more clearly and I thank you very much.
I prefer to hide private variables in a macro rather than have them in global scope. I pass the frontend via an argument Code:
macro init_test name*
local i
calminstruction name?!
...
end calminstruction
purge init_test
end macro
|
|||
|
|
Tomasz Grysztar 20 Mar 2026, 21:53
Excellent solution!
|
|||
|
< Last Thread | Next Thread > |
Forum Rules:
|
Copyright © 1999-2026, Tomasz Grysztar. Also on GitHub, YouTube.
Website powered by rwasa.