If you come across the word "chains" read it as "strings". Google translator does not understand the context and in Czech it is simply an overloaded/multiple meaning word.
With the non-definition of how a table with chain links should be created in Forth is problematic.
In Forth, it can be created once, even by hand (although perhaps Forth does not support strings other than words) at the beginning.
I can easily make it as "dw" items when compiling, but...
The compiler will not understand that it is a constant list. So he can substitute values for "dw", but at the same time he will try to overwrite them to these values somewhere at the beginning of the program (in the definition area in the source). Because he doesn't know that they will never be changed. And if something were to change there, the program would fail when restarted.
That's quite enough code for the initialization.
Code: Select all
ld hl, x1; 3:10 a.m
ld [addr_x1],x1 ; 3:16 a.m
ld hl, x2; 3:10 a.m
ld [addr_x2],x1 ; 3:16 a.m
...
Code: Select all
ld hl, x1; 3:10 a.m
ld [addr_x1],x1 ; 3:16 a.m
ld l, x2; 2:7
ld [addr_x2],x1 ; 3:16 a.m
...
I actually tested it by setting my org to 0x4000 and splitting the image into a long list of "num ," and the resulting code was able to copy it faster than the beam caught up with me. (So the compilation takes hours and I had to rewrite the code several times because it takes up gigabytes of RAM memory. Well, it's still just a macro, but the result is a code that a human cannot write by hand.)
I was just looking at how I got the non-standard word >," < and when I tested it again like gforth has it, it's wrong/different.
gforth creates a computer chain and I create a normal chain with the difference that instead of STRING_SECTION I store it in VARIABLE_SECTION. No initialization.
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'COMMASTRING({"Hi"})'
; comma"string" ,"Hi"
VARIABLE_SECTION:
; +2 bytes?
db "Hi"
;# ============================================================================
if ($<0x0100)
.error Overflow 64k! over 0..255 bytes
endif
if ($<0x0200)
.error Overflow 64k! over 256..511 bytes
endif
if ($<0x0400)
.error Overflow 64k! over 512..1023 bytes
endif
if ($<0x0800)
.error Overflow 64k! over 1024..2047 bytes
endif
if ($<0x1000)
.error Overflow 64k! over 2048..4095 bytes
endif
if ($<0x2000)
.error Overflow 64k! over 4096..8191 bytes
endif
if ($<0x3000)
.error Overflow 64k! over 8192..12287 bytes
endif
if ($<0x4000)
.error Overflow 64k! over 12288..16383 bytes
endif
if ($>0xFF00)
.warning Data ends at 0xFF00+ address!
endif
; seconds: 0 ;[ 0:0]
Then I already tested different procedures and they are functional but a bit laborious to write.
The resource then looked something like this:
Code: Select all
CREATE(MonthTable)
STRING({"January"}) DCOMMA
STRING({"February"}) DCOMMA
STRING({"March"}) DCOMMA
STRING({"April"}) DCOMMA
STRING({"May"}) DCOMMA
STRING({"June"}) DCOMMA
STRING({"July"}) DCOMMA
STRING({"August"}) DCOMMA
STRING({"September"}) DCOMMA
STRING({"October"}) DCOMMA
STRING({"November"}) DCOMMA
STRING({"December"}) DCOMMA
Code: Select all
CREATE(_jan)
COMMASTRING({"January",0})
CREATE(_feb)
COMMASTRING({"February",0})
CREATE(_mar)
COMMASTRING({"March",0})
CREATE(_apr)
COMMASTRING({"April",0})
CREATE(_may)
COMMASTRING({"May",0})
CREATE(_jun)
COMMASTRING({"June",0})
CREATE(_jul)
COMMASTRING({"July",0})
CREATE(_aug)
COMMASTRING({"August",0})
CREATE(_sep)
COMMASTRING({"September",0})
CREATE(_oct)
COMMASTRING({"October",0})
CREATE(_nov)
COMMASTRING({"November",0})
CREATE(_dec)
COMMASTRING({"December",0})
CREATE(MonthIndexTable)
PUSH(_jan) COMMA
PUSH(_feb) COMMA
PUSH(_mar) COMMA
PUSH(_apr) COMMA
PUSH(_may) COMMA
PUSH(_jun) COMMA
PUSH(_jul) COMMA
PUSH(_aug) COMMA
PUSH(_sep) COMMA
PUSH(_oct) COMMA
PUSH(_nov) COMMA
PUSH(_dec) COMMA
So I created the word COMMA STRING (>,c" <)
Code: Select all
dworkin@dw-A15:~/Programovani/ZX/Forth/M4$ ../check_word.sh 'COMMACSTRING({"Hi"})'
; commac"string" ,c"Hi"
STRING_SECTION:
string101:
db 2,"Hi"
size101 EQU $ - string101
if (size101 != 3)
.error: Incorrectly calculated character string size, does not match the actual size!
endif
VARIABLE_SECTION:
dw string101 ; +2 bytes
;# ============================================================================
if ($<0x0100)
.error Overflow 64k! over 0..255 bytes
endif
if ($<0x0200)
.error Overflow 64k! over 256..511 bytes
endif
if ($<0x0400)
.error Overflow 64k! over 512..1023 bytes
endif
if ($<0x0800)
.error Overflow 64k! over 1024..2047 bytes
endif
if ($<0x1000)
.error Overflow 64k! over 2048..4095 bytes
endif
if ($<0x2000)
.error Overflow 64k! over 4096..8191 bytes
endif
if ($<0x3000)
.error Overflow 64k! over 8192..12287 bytes
endif
if ($<0x4000)
.error Overflow 64k! over 12288..16383 bytes
endif
if ($>0xFF00)
.warning Data ends at 0xFF00+ address!
endif
; seconds: 0 ;[ 0:0]
Code: Select all
create ascii_table
c" " , \ space
c" -.-.--" , \ ! ( or ---...-) (or +)
c" .-..-." , \ "
c" ..--.." , \ # --> ? --> "num"?
...
Code: Select all
create ascii_table
,c" " \ space
,c" -.-.--" \ ! ( or ---...-) (or +)
,c" .-..-." \ "
,c" ..--.." \ # --> ? --> "num"?
...
I should probably hang this up for all kinds of chains. Because I can do this even for null-terminated string characters, etc. Then just one word COUNTZ is added and it can be worked with like a normal string.
Rewritable chains would simply have to be created with the help of initialization by copying MOVE etc. from the constant chain. This is probably the best way. I'm still not sure. Because it would really like to see some program/task that requires it.
In addition, it seems that the definition of the standard for computer chains is made in such a way that physically the chains do not have to look like Pascal. It can be combined byte_length + pointer_to_the_first_character.
In theory, this should make various operations on strings easier. Because the pointer to this (construction? hell, I forgot how to name it) would remain the same (it wouldn't change the address).
It's amazing how many problems can be caused by just a suggestion of how to design it. And not how to do it.
Make a translator (another wrong translation = compiler) is like playing on a children's playground that has no back border.
PS: Not to mention it completely. The difference between the proposal of how to divide words into primitive words before (khamurapi) and now (morse_code) is that before it was a code for real forth (gforth) and now it has to be translated for ZX Spectrum. So too many nested words will create inefficient code. And here again the question arises what to do with it? Disguise it and have transparent source code.
But which ones? Original Forth, so run the fth2m4.sh script on top of that first? So I should somehow test whether the words are "leaf" and in M4_FORTH is "inline".
Or should I solve it with M4_FORTH? By word size? Are there leaves? Inline just before the sheet too? Feel like using it? When one automatically mit inline? And then how to solve EXECUTE? Do not look at these words inline? But if the translator will solve it himself, then again I lose a little control over the result... too many problems... .)))
Especially who I'm targeting. For someone who can write an effective forth program, so why compile it anyway? Someone you don't like
of C translations are inefficient? He probably won't want to learn Forth... Hard to say. Especially when I come across some error that worked before, but stopped after some change... and I realize that it was a few months ago and NO ONE complained. So no one has probably tried it. I wonder if anyone ever does
really useful.