Page 1 of 1
How to write an inlining CONST word?
Posted: Thu Jan 22, 2026 12:33 pm
by pdragon
It seems like CONSTANT words compile a reference to themselves, so the value isn't looked up til run-time.
I guess this allows the value to change before the word executes which is perhaps a benefit in some cases.
I want to make a CONST word which just inlines itself at compile-time, so the value is guaranteed and it runs a bit faster.
Code: Select all
42 CONSTANT a
: foo a + ; \ the word a executes at runtime to deliver its value
: foo [ a ] literal + ; \ the value of a is inlined at compile time
Below is what I came up with - is there a better way?
Code: Select all
: CONST ( n "name" -- )
CREATE , IMMEDIATE
DOES> @ STATE @ IF POSTPONE LITERAL THEN
;
Re: How to write an inlining CONST word?
Posted: Thu Jan 22, 2026 8:41 pm
by GARTHWILSON
What threading model are you interested in doing this in? The way I do it in my ITC Forth is almost the same for CONSTANT as for VARIABLE, both putting a number on the stack, but for a variable the number is expected to be an address. It was many years ago that I wrote it, but it looks like if I were to really get into the details now I would find not more than a cycle or two difference in execution speed in my '816 Forth. That's for when the target computer is running. When I'm forming the kernel in another computer, whether assembling or compiling, for a ROM-based system where the variable's data cannot be right there with the variable's header, they truly are the same, and VARIABLE just returns the (constant) number which is the address of the variable's data in RAM. The runtime is const for both VARIABLE and CONSTANT. No difference.
In your example though, if you have an assembler onboard and it's super easy to write primitives, why not just do that. In the simplest example, 1+ in the '816 with accumulator width set to 16-bit becomes just INC 0,X, rather that putting 1 on the stack as a constant and then running the add routine. If there's a number you need to add frequently and quickly, make it a primitive, for example 42+ becomes (for 65816 with accumulator width option set to 16-bit):
Re: How to write an inlining CONST word?
Posted: Thu Jan 22, 2026 9:06 pm
by SamCoVT
If you want speed instead of size, you can forgo using LITERAL and just put the assembly to get the value on the stack (looks like Garth beat me to it):
Code: Select all
assembler-wordlist >order
: const create , immediate does>
@ STATE @ IF
postpone dex postpone dex
$100 /mod
postpone lda.# 1 postpone sta.zx
postpone lda.# 0 postpone sta.zx
THEN ;
If you are doing a lot of 8-bit work, you could also make a version that just uses STZ for the high byte.
All of the POSTPONEs on the assembly words essentially create an assembly macro.
Edit: To answer Garth's question, I'm assuming this is for Tali Forth 2, an STC Forth, which makes it super easy to mix in some assembly.
Re: How to write an inlining CONST word?
Posted: Thu Jan 22, 2026 11:15 pm
by pdragon
yes, for Tali. Looks like it automatically does the inlining from the postpone literal already
Code: Select all
42 const fubar ok
fubar . 42 ok
.s <0> ok
: snafu fubar + ; ok
see snafu
...
943 2A lda.#
945 dex
946 dex
947 0 sta.zx
949 1 stz.zx
94B 80BE jsr 2 STACK DEPTH CHECK
94E clc
94F 0 lda.zx
951 2 adc.zx
953 2 sta.zx
955 1 lda.zx
957 3 adc.zx
959 3 sta.zx
95B inx
95C inx
ok
.s <0> ok
7 snafu . 49 ok
Re: How to write an inlining CONST word?
Posted: Thu Jan 22, 2026 11:18 pm
by pdragon
yes, i like Garth's idea of adding a couple of primitives too. I think I can speed up the 65c02-on-65c02 emulator a lot with inlined const and some well-chosen bit-twiddling words for all the flag updates. needs a bit of thought about exactly what words tho.