Note
|
Milestone: 0.15.0 |
-
Make the relative control-flow structures optional and individually loadable.
-
Simplify: Remove the
?pairs
checking, or make unchecked optional versions of the control-flow structures.
Replace im1,
and im2,
with im,
; or add im0
with the m8
definer.
Tests:
Replacing im1,
and im2,
with this code costs 17 bytes of code/data
space and saves 10 bytes of name space:
: im, ( n -- ) ed, dup if 1+ then 8* 46 or c, ;
This alternative, factoring ed,
out of the four words that contain
ED c,
(sbcp,
, adcp,
, stp,
and ftp,
), costs 12 bytes of
code/data space and saves 2 bytes of name space:
: ed, ( -- ) ED c, ; : im, ( n -- ) ed, dup if 1+ then 8* 46 or c, ;
This variant costs 8 bytes of code/data space and saves 2 bytes of name space:
: ed, ( -- ) ED c, ; here 46 c, 56 c, 5E c, : im, ( n -- ) ed, [ dup ] literal + c@ c, ; drop
-
Make
addix
andaddiy
smart to detecth
in order to avoidix-op c,
andiy-op c,
, maxing the syntaxesix addix,
andiy addiy,
possible. Currently a second $DD or $FD is compiled in those cases. Other solution: makeaddp,
smart, as noted on 2017-03-12. -
Rewrite
exsp,
to accepth
,ix
orix
. -
Add
jpiy,
. -
Add
cpd,
,cpdr,
, andcpi,
with them8
definer. -
Add
ind,
,indr,
,ini,
andinir,
with them8
definer. -
Add
otdr,
andotir,
with them8
definer. -
Add
outd,
andouti,
with them8
definer. -
Add
reti,
andretn,
with them8
definer.
-
Add
rrd,
with them8
definer. -
Make
stp,
andftp,
smarter, makingsthl,
andfthl,
unnecessary.
Note
|
Milestone: 0.15.0 |
Idea from DX-Forth: a set of Forth variables analogous to Z80
registers, which doscall
fetchs before doing the call, and updates
afterwards. This way, machine code routines are easier to integrate
into Forth words, no need to factor the code part into a different
word, or manipulate the parameters in assembler.
Adapt inline
from Richard W.M. Jones' Jonesforth
(http://annexia.org/forth):
( INLINE can be used to inline an assembler primitive into the current (assembler) word. For example: : 2DROP INLINE DROP INLINE DROP ;CODE will build an efficient assembler word 2DROP which contains the inline assembly code for DROP followed by DROP (eg. two 'pop %eax' instructions in this case). Another example. Consider this ordinary FORTH definition: : C@++ ( addr -- addr+1 byte ) DUP 1+ SWAP C@ ; (it is equivalent to the C operation '*p++' where p is a pointer to char). If we notice that all of the words used to define C@++ are in fact assembler primitives, then we can write a faster (but equivalent) definition like this: : C@++ INLINE DUP INLINE 1+ INLINE SWAP INLINE C@ ;CODE One interesting point to note is that this "concatenative" style of programming allows you to write assembler words portably. The above definition would work for any CPU architecture. There are several conditions that must be met for INLINE to be used successfully: (1) You must be currently defining an assembler word (ie. : ... ;CODE). (2) The word that you are inlining must be known to be an assembler word. If you try to inline a FORTH word, you'll get an error message. (3) The assembler primitive must be position-independent code and must end with a single NEXT macro. Exercises for the reader: (a) Generalise INLINE so that it can inline FORTH words when building FORTH words. (b) Further generalise INLINE so that it does something sensible when you try to inline FORTH into assembler and vice versa. The implementation of INLINE is pretty simple. We find the word in the dictionary, check it's an assembler word, then copy it into the current definition, byte by byte, until we reach the NEXT macro (which is not copied).) HEX : =NEXT ( addr -- next? ) DUP C@ AD <> IF DROP FALSE EXIT THEN 1+ DUP C@ FF <> IF DROP FALSE EXIT THEN 1+ C@ 20 <> IF FALSE EXIT THEN TRUE ; DECIMAL ( (INLINE) is the lowlevel inline function. ) : (INLINE) ( cfa -- ) @ ( remember codeword points to the code ) BEGIN ( copy bytes until we hit NEXT macro ) DUP =NEXT NOT WHILE DUP C@ C, 1+ REPEAT DROP ; : INLINE IMMEDIATE WORD FIND ( find the word in the dictionary ) >CFA ( codeword ) DUP @ DOCOL = IF ( check codeword <> DOCOL (ie. not a FORTH word) ) ." Cannot INLINE FORTH words" CR ABORT THEN (INLINE) ; HIDE =NEXT
;code
is standard and cannot be reused, but anyway a simpler syntax
is possible and desirable, because inline
must be used with all
words:
inline: c@++ dup 1+ swap c@ ;inline
The same idea could be used also for colon words, saving the threading, using a common syntax:
: a-colon ... ; : normal bla bla bla ; : faster inline bla bla bla end-inline ; code code-a ... end-code code code-b ... end-code code code-c ... end-code code fast-code inline code-a code-b code-c end-inline end-code
Or different definers:
inline: faster bla bla bla end-inline ; inline-code fast-code code-a code-b code-c end-inline end-code
There are problems, though:
-
Matching
jp (ix)
(equivalent to "next") to finish the code inlining is not reliable, because the bytes of the corresponding opcode ($DD $E9) could be used as data, or as an address or as instruction datum $DD followed by opcode $E9 (sayld a,$DD
followed byjp (hl)
). -
Matching
exit
to finish the colon inlining is not reliable, becauseexit
may be compiled explicitly, beside being compiled by;
.
It is easier to define faster words when needed, as part of the
application, than to write smart inline:
and inline-code
.
;uses
from F83:
;USES
This is a new syntax that can be used to compile a code field whose code already exists. Similar to ;CODE
: (;USES) (S -- ) R> @ LAST @ NAME> ! ; VOCABULARY ASSEMBLER : ;USES (S -- ) ?CSP COMPILE (;USES) [COMPILE] [ REVEAL ASSEMBLER ; IMMEDIATE : (;CODE) (S -- ) R> LAST @ NAME> ! ; : ;CODE (S -- ) ?CSP COMPILE (;CODE) [COMPILE] [ REVEAL ASSEMBLER ; IMMEDIATE HEX
From Inside F83:
;USES
Insert the following code routine address into the code field of the new definition, making it a colon definition.
Make index register instructions optional. All of them:
86 ma addx, 8E ma adcx, 96 ma subx, 9E ma sbcx, A6 ma andx, AE ma xorx, B6 ma orx, BE ma cpx, 34 ma incx, 35 ma decx, 06 mb rlcx, 0E mb rrcx, 16 mb rlx, 1E mb rrx, 26 mb slax, 2E mb srax, 3E mb srlx, 46 mc bitx, 86 mc resx, C6 mc setx, : ftx, ( disp regpi reg -- ) nip 8* 46 + c, c, ; : stx, ( reg disp regpi -- ) drop swap 70 + c, c, ; : st#x, ( 8b disp regpi -- ) drop 36 c, swap c, c, ; : ftpx, ( disp regpi regp -- ) 3dup 1+ ftx, rot 1+ -rot ftx, ; : stpx, ( disp regpi regp -- ) 3dup 1+ stx, rot 1+ -rot stx, ;
Study changes needed to use ix addp,
instead of addix,
;
this means h addp,
should be used instead of addp,
Add a small layer on the assembler to compile it into the Plus D memory, and use it from there.
Note
|
Milestone: 0.15.0 |
Use the circular string buffer as pictured output buffer.
From comp.lang.forth (By Gerry Jackson, Fri, 21 Sep 2018 20:54:45 +0100):
Try
123. <# #S #> 456 . TYPE
. On popular systems such as Win32 Forth, VFX Forth and SwiftForth the output is 456 456. Gforth is a notable exception as it outputs 456 123.
view
gets trapped in wait-for-key
at the end, why?
It happens when view
is used on its own, but not when used right
after being loaded, example need view view see
.
Update: It has nothing to do with view
. The same happened after an
error #-268. Somehow the flag of the last key pressed is not updated
by the OS and the code is trapped in a loop. An emulator issue?
From CHForth’s <MISCUTIL.FRT>:
: eval" postpone s" postpone evaluate ; immediate compile-only
Replace error.definition_not_finished
(non-standard code #-264) with
error.control_structure_mismatch
(standard code #-22) in ?csp
?
This is the exception code used in Gforth’s ?csp
.
Rewrite compiling?
and interpreting?
in Z80?
Problem: state
is a user variable. Otherwise, for example, the code
of compiling?
would need only 6 bytes (its current colon definiton
needs 11 bytes):
ld hl,(state_dfa) jp zero_not_equals.hl
But fetching a user variable makes the code bigger (16 bytes):
ld de,$001E ; $1E = index of `state` ld hl,(up_dfa) ; HL = address of the user area (the value of `up`) add hl,de ; HL = address of the user variable ex de,hl ld a,(de) ld l,a inc de ld a,(de) ld h,a jp zero_not_equals.hl
The address calculation could be factored, shared with do_user
…
but it needs 6 bytes, plus 1 for the return, while the call needs 3
bytes… It does not worth. Beside, this factoring would slow down all
user variables a bit.
Adapt from 8080 F83 2.0:
: :: ( -- ) HIDE HERE >R [ ' : @ ] LITERAL , !CSP ] R@ EXECUTE R> DP ! ; \ compile and execute nameless FORTH code, then forget it
Add fast
and slow
, after ACE Forth, to deactivate/activate some checks:
?stacks
, limit
and farlimit
(not used yet), etc.
Rewrite '
after Gforth. See Gforth’s (')
, name?int
,
name>int
, etc. Factor defined
and comp'
accordingly.
Make dp
an ordinary variable? Then here
, there
and allot
could be
improved, rewritten in Z80.
Idea: in DX-Forth, last
is a 2-cell variable that holds both the nt and the
xt: last @ ( nt )
and last 2@ ( xt nt )
.
Factor the return stack manipulation done by (.")
in order to
reuse it in (abort")
and (warning")
. Use a variant of pForth’s param
.
+bal
, -bal
or similar, to change csp
:
: [+csp] ( -- ) [ cell negate ] literal csp +! ; immediate compile-only : [-csp] ( -- ) cell csp +! ; immediate compile-only
But to compile an external number inside a definition,
a trick is [ dup ] literal
and a drop
after ;
.
In order to save compilation time, move inner words to the bottom of
the dictionary. Example: (loop)
, clit
, back
, digit
…
Separate header flags from the length byte of the name field. This way more bits will fit (alias, synonym, special behaviour), word names will be actual strings, and searching the dictionary will be a bit faster.
From 8080 F83 2.0:
: MANY (S -- ) KEY? NOT IF >IN OFF THEN ; \ Re-execute the input stream until the user presses a key.
From 8080 F83 2.0:
\ Iterated Interpretation 03Apr84map VARIABLE #TIMES ( # times already performed ) 1 #TIMES ! \ A variable that keeps track of how many times. : TIMES (S n -- ) 1 #TIMES +! #TIMES @ < IF 1 #TIMES ! ELSE >IN OFF THEN ; \ Re-execute the input stream a specified number of times.
From 8080 F83 2.0:
: WHEN (S f -- ) PAUSE NOT IF R> 4 - >R THEN ; \ Re-execute the previous word until it returns true. \ NOTE: WHEN is slightly magic. \ Usage: : TEST READY WHEN BEEP ; \ Where READY returns a flag.
Use a new kind of unconditional high-level branch at the end of nest-source
and unnest-source
:
goto ( a -- )
Make it consistent with the planned changes in the current low-level branches.
Change ??
to its old version, which is more useful:
\ XXX TODO -- 2016-11-26: It seems more useful the old \ version, extended as the rest of alternative conditionals: \ \ : ?? ( f -- ) 0= if r> cell+ >r then ; compile-only \ : 0?? ( f -- ) if r> cell+ >r then ; compile-only \ : -?? ( f -- ) 0>= if r> cell+ >r then ; compile-only \ : +?? ( f -- ) 0< if r> cell+ >r then ; compile-only
Alternative:
\ : ?? ( f -- ) 0exit r> cell+ >r ; compile-only \ : 0?? ( f -- ) ?exit r> cell+ >r ; compile-only \ : -?? ( f -- ) 0> ?exit r> cell+ >r ; compile-only \ : +?? ( f -- ) 0< ?exit r> cell+ >r ; compile-only
Note
|
Milestone: 0.15.0 |
Idea: Rename branch
, 0branch
and ?branch
to (branch)
, (0branch)
and
(?branch)
. Then write branch
, 0branch
and ?branch
to compile them, as
control structures.
: branch ( a -- ) postpone (branch) , ; immediate compile-only : ?branch ( a -- ) postpone (?branch) , ; immediate compile-only : 0branch ( a -- ) postpone (0branch) , ; immediate compile-only
Also -branch
and +branch
in the library.
Ideas from cmForth:
LOOP Test the top item on the return stack. If it is zero, pop it off the return stack and continue executing the next instruction. If it is not zero, decrement it and jump to the address specified in this instruction. Address specifier is the same as in BRANCH. LOOP is compiled by NEXT.
REPEATS Repeat the next instruction if the count on top of the return stack is not zero. The count is also decremented. If count is zero, pop the return stack and continue executing the following instruction. REPEATS is compiled by TIMES or OF(.
The REPEATS instruction is used frequently to implement complicated math operations, like shifts, multiply, divide and square root, from appropriate math step instructions. It is also useful in repeating auto-indexing memory instructions.
Rename >name
and friends:
Old | Alternative 0 | Alternative 1 |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Maybe even create a deferred >name
.
From Special Words in Forth, paper by Stephen Pelc, EuroForth 2017:
SEARCH-NAME \ c-addr len -- ior | xt 0 Perform the SEARCH-WORDLIST operation on all wordlists within the current search order. On failure, just an ior (say -13) is returned. On success, the word’s xt and 0 are returned.
Reduce the number of aliases. There are 25 aliases in the kernel, and
probably more in the library. Aliases save code space, but see
shows
the oldest name associated to a code field what is the best option but
can be inconvenient.
Keep notation ">str" coherent.
Rename name>string
to name>stringer
.
Rename name>str
to name>string
(after Gforth)?
Rename line>string
to line>str
?
Improve >oldest-name
and friends?
Options:
-
Mark aliases and synonyms with a bit in the header. Pro:
>oldest-name
Definitive and useful for other needs. Con: One byte must be added to the header. -
Distinguish aliases and synonyms using the content of its code field address, e.g. using a specific jump, or a jump with a previous Z80 noop. Cons: every alias or synonym uses 3 or 4 bytes of data space; small time delay for the jump, as deferred words; distinguishing an alias or synonym from their "original" or from a deferred word needs more calculations.
-
Combine both: create a deferred word but set a bit of its header. The execution token of an alias will be different from its original. Con: delay of the additional jump.
Write color
(recolor
?) to change the attributes of the screen,
completing the "color" series: color-rectangle
and wcolor
.
Document the control characters accepted by each mode, especially the parameters of "at".
Note
|
Milestone: 0.15.0 |
In mode-32
and mode-32iso
: The channel output must be patched
(set-mode-output
) with custom routines, and the corresponding
actions of emit
must be rewritten after them. This is what
mode-64ao
does, in order to make the display mode effective in Forth
(emit
) and Z80 (rst 10
).
Improve the transition between display modes: Convert the cursor coordinates of the previous mode.
Write the definitive version of u.
in the library. The current one
is temporary, for debugging.
Finish mode-64es
, the port of "64#4", the the driver written by Einar
Saukas.
Note
|
Milestone: 0.15.0 |
Fix: The default mode-32
expects row right after control character
22, and then col, i.e in the order used by Sinclair BASIC. But
mode-64ao
and mode-42rs
expect them in reverse order.
Update (at-xy
and its documentation.
Write mode-32udg-emit
to use the full UDG 0 .. 255 as a font, after the
method used by mode-32iso-emit
.
Change the order of the cursor coordinates embedded in strings, after
the Forth convention? This is not possible with mode-32-emit
, which
uses the ROM routine.
Convert the ISO standard 64-cpl fonts included in mikroprint to the
format used by mode-64ao
and mode-64es
.
Import center-type
from Nuclear Waste Invaders and rename and
modify gigatype-center
accordingly.
Convert previous-mode
and current-mode
to deferred words; then
remove save-mode
and restore-mode
. Calculate the gain in bytes and
simplicity.
This changes implies moving defer@
to the kernel.
The Forth Standard requires standard ASCII. An alternative to non-standard character 96 is needed.
-
Detect it in
emit
and change the font only to print it, temporarily? This will ruin alternative fonts. -
Simpler: Provide an alternative standard font in disk.
Current versions of type-right-field
and type-center-field
use
spaces. This creates a banner.
Write alternative versions that move the cursor position instead.
Choose shorter names:
Current name | New name | Common name with factored execution table |
---|---|---|
|
|
|
|
|
|
|
|
|
Using the execution table as parameter has a problem:
type-left-field
does not use execution table. Besides, the execution
tables will be different for the future set of words that type without
padding spaces, so finally the number of different words will grow
anyway.
Adapt banked-mode-42
and set-banked-mode-output
to far memory or
remove them.
Windows:
-
Scroll support, with configurable pause.
-
Rewrite
wcls
in Z80, or usespaces
instead oftype
-
Save and restore windows, in Z80.
Note
|
Milestone: 0.15.0 |
Make type-ascii
configurable: store the common character in a
character variable. In fact, it would be enough to write
emit-ascii
, because emit
is deferred, and use type
.
Make type
deferred, to be configured as fartype
or other when needed.
Add support for more control characters to an alternative version of
mode-64ao
or mode-64es
.
In mode-32
, one cr
does nothing when the cursor is at the end of a
line. That is the default behaviour in Sinclair BASIC. The driver of
mode-42rs
works the same way. But the driver of mode-64ao
always
prints the carriage return, increasing the line number. Somehow the
behaviour must be unified in all modes. The behaviour of mode-64ao
seems more logical.
There’s an example how to change and restore a channel in print-42, by Ricardo Serral Wigge. Beside, it supports many (all?) control characters, unlike the implementation by Andy Jenkinson.
Idea: screen modes table?
-
0: 32 cpl original (ROM routines)
-
1: 32 cpl improved (bold, italic).
-
3: 36 cpl
-
4: 42 cpl
-
5: 51 cpl
-
6: 64 cpl
It seems more versatile to create one word to select every mode and provide a common user interface to row, column, cpl, window…
Note
|
Milestone: 0.14.0 |
Make the documentation of variables, constants, etc., coherent with other types of words. Instead of this:
myword ( — a )
A
variable
. a is the address of …
Write this:
myword ( — a )
Return the address a of …
myword
is avariable
.
I.e. first describe the action of the word in imperative.
-
Homogenize the pronunciation notation of acronyms in word names, e.g. after
dosior>ior
"dos-I-O-R-to-I-O-R",file-ids
should be "file-I-D-s".
Note
|
Milestone: 0.14.0 |
-
Duplicate the Z80 instructions table with only two columns in order to make it fit in EPUB. Problem: The EPUB made from DocBook cannot be distinguised by an Asciidoctor condition; a specific version with an attribute would be needed.
Note
|
Milestone: 0.14.0 |
-
Mark external links with an icon or "(www)" or Unicode arrow (↗).
Note
|
Milestone: 0.14.0 |
-
Preserve the .adoc extension in the target files?
-
Add "Compile the Z80 jumps required" to assembler control-flow words.
-
Cross-reference all Z80 conditions in assembler control-flow structures.
Note
|
Milestone: 0.15.0 |
-
Search for words without cross-references in order to complete them.
-
Search for words that have definitions whose main words are not cross-references.
-
Cross-reference all words used in the definitions included in the glossary?
-
Improve: "a is the address of…" → "Return address a of…".
-
Make cross-references to
{
and}
(Hayest test) explicit?
-
Document also the main words of the sample games.
-
Finally, modify the Makefile to include all programs from the library (<prog.*.fs>) into the glossary.
-
Fix rendering of footnotes in all formats (PDF, HTML and EPUB), especially in tables.
-
Homogenize the transcription of names' "<" ("less-than", "from", "backwards"). and ">" ("greater-than", "to", "forwards").
Add this sections to the manual:
-
A reference guide by subject, e.g. graphics, sound, blocks, files, control flow structures, etc.
-
A description of the library modules.
Note
|
Milestone: 0.15.0 |
Homogenize the position of the pronunciation in words that have several stack comments.
Note
|
Milestone: 0.15.0 |
Add a section about how to use more than one block disk, and link to it.
Remove "char" from the stack notation section of the manual. Update
the documentation, for example: parse ( char "ccc<char>" — ca len )
with parse ( c "ccc<c>" — ca len )
.
Also <chars>
in the stack notation table: word ( c
"<chars>ccc<char>" — ca )
?
Note
|
Milestone: 0.15.0 |
Review and homogenize the layout of "Compilation" and "Run-time" stack notations.
Include the description of the attribute OS variables into the related words, or into a section of the manual.
Fix: The glossary cross references to Forth words that contain a backslash, or that are included in code examples, are corrupted.
Update the manual: RAM banks used as far memory, the RAM disk, the different configuration in +3DOS…
Section about the AY-3-8912 sound generator, using the description from the ZX Spectrum 128 ROM0 disassembly. Replace the extracts included in the glossary with a link to the section.
Note
|
Milestone: 0.15.0 |
-
Finish and document <flow.select.fs>.
-
Add usage examples to <flow.dijktstra.fs>.
Remove the documentation of DOS subroutines that is duplicated in its corresponding entry constant, and put a note instead.
Homogenize and fix the notation about interpretation, compilation and execution/run-time semantics. Better yet, use the simpler convention of Forth-83.
Change the stack notation back to classic Forth?:
-
xt → cfa
-
nt → nfa
-
lfa
-
xtp → cfaa/cfap
Note
|
Milestone: 0.15.0 |
Homogenize the stack notation for blocks and block lines.
Change n to u or +n for blocks and block lines. +n seems the
best option, because the maximum block number that can be stored in
disk-buffer
is 32767-1.
Consult the notation used in Forth-2012.
Homogenize the following stack notations:
-
double, triple and quadruple numbers (or include all used conventions in the documentation).
Note
|
Milestone: 0.15.0 |
Remove ior from get-drive
. Only +3DOS returns an actual ior. But
is it really actual? In which cases could the operation fail? If +3DOS
returns always a no-error, it would be simpler to drop it, and then
remove the fake ones from G+DOS and TR-DOS.
+3DOS' eof?
can be moved to the common module, after implementing
file-position
and file-size
in G+DOS and TR-DOS`.
Note
|
Milestone: 0.15.0 |
Improve transfer-block
to preserve the current drive. Now the
current drive is changed by (>drive-block
, which is activated by
loading block-drives
, needed by set-block-drives
. Example on
G+DOS:
1 set-drive \ an ordinary formatted file disk 2 1 set-block-drives \ the library is in drive 2 1 load \ ok get-drive . \ but now the current drive is number 2
Support block files?
Block files can be supported easily on +3DOS (already done on DZX-Forth); with some more effort on TR-DOS; and probably also on G+DOS, after some low-level investigation. But copying the library to a disk image as a block file is not possible yet with the ordinary tools.
The only advantage of block files is having all files required to compile a project (Solo Forth loader and binary, blocks, data files, graphics, sounds, etc) in one single disk.
In practice, the problems to be solved are bigger than the possible benefit on a diskette-based system. Block files seem more useful on a hard drive, on IDEDOS or ResiDOS.
Decide if lower-level factor words return a dosior or an ior.
Making the low-level words do the conversion needs either a push and a
jump to dosior>ior
(4 bytes in total), or a direct jump to a
specific routine in the kernel (3 bytes in total), which can save some
bytes, depending on the number of calls done in the kernel and the
library.
Making the conversion in the upper-level calling words means pushing
the dosior in the factor, returning to next
, and using
dosior>ior
in the calling word (5 bytes in total).
Note
|
Milestone: 0.15.0 |
Unify G+DOS transfer-sector
and TR-DOS transfer-sectors
. Make
their behaviour and names identical. Write the +3DOS version too.
Note
|
Milestone: 0.15.0 |
Fix file-dir#
and file-dirdesc
: they always return zero because of
a limitation in (file-status
, which does not update the whole
ufia
.
Note
|
Milestone: 0.15.0 |
Fix sectors-unused
(on which depend drive-unused
and
drive-used
): G+DOS only updates its internal variable $3DD8 when a
catalogue is displayed. Therefore acat
is used. In order to solve
this problem, the scan_cat
G+DOS routine should be copied and
modified to calculate the number of sectors used.
Note
|
Milestone: 0.15.0 |
Transfer ufia
to ufia1
in ((cat
using hook xfer
, instead of
doing it in (cat
using >ufia1
. It seems safer.
Integrate printing out of cat
and friends with the printing
flag:
\ XXX TODO -- The disk catalogues can be printed out on a \ printer by storing the number 3 into SSTR1 (a field of UFIA \ that holds the stream number to use) before doing `CAT`. \ The default value is 2 (screen) and should be restored. \ Example: \ \ 3 sstr1 c! s" forth?.*" wcat 2 sstr1 c!
Factor this common code to a routine to jump to:
b pop, next ix ldp#, \ restore the Forth registers af push, ' dosior>ior jp, end-code
It could be in the kernel, right before dosior>ior
, and run into it.
Fix: When the current disk is removed before doing cat
, the
corresponding exception is thrown. But the system does not recognize
the disk when it’s inserted back. The same code is thrown: #-1006
(check disk in drive), even after set-drive
. It seems something more
is needed to make G+DOS aware of the change.
Update: Same problem in BASIC. It seems an issue of G+DOS or the Fuse
emulator. The disk is recognized after doing a cat
of the other
drive. Same problem in BASIC with DISCiPLE and GDOS.
Factor the following code, which reads a file header; it’s used by two words:
hd00 d ldp#, 9 b ld#, \ file header destination and count rbegin lbyte hook, d stap, d incp, rstep
Make cat
and family check and use printing
.
\ XXX REMARK -- The disk catalogues can be printed out on a \ printer by storing the number 3 into SSTR1 (a field of UFIA \ that holds the stream number to use) before doing `CAT`. \ The default value is 2 (screen) and should be restored. \ Example: \ \ 3 sstr1 c! s" forth?.*" wcat 2 sstr1 c!
There seems to be a problem when the library disks are inserted into
drives 2nd and 3rd, and 1 set-drive throw 1 load need
set-block-drives
is used:
1 set-drive throw ok 1 load ok need set-block-drives ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ??????????????????? ? #-256
Then get-block-drive throw .
displays 0 instead of 1.
Fix/rewrite read-system-track
: When there’s no disk in the drive, it
returns to BASIC. This affects set-drive
.
Note
|
Milestone: 0.15.0 |
Use drive letters A..D, as used in filenames.
Write drive>#
and drive#>
for converting.
Update first-drive
.
Use the 8 free sectors of the system track for 2 additional blocks. This requires changes in the fsb2-trd converter.
Note
|
Milestone: 0.15.0 |
-
Rename
read-file-descriptor
toread-fda
? -
Rename
write-file-descriptor
towrite-fda
?
The problem is "FDA" (File Descriptor Area) is the buffer where the
file descriptor is hold. read-fd
could be used instead, but "FD"
looks like "floppy disk". read-file-desc
looks like "file
description", which is a different thing.
Improve cat
: read-file-descriptor
reads the system track every
time. Explore the sector buffer instead.
Improve undelete-file
: read-file-descriptor
reads the system track every
time. Explore the sector buffer instead.
TR-DOS disk operations can be interrupted with the Break key… and the system returns to BASIC with error "BREAK into program"! There must be a way to deactivate this. Study the disassembly.
Make (acat
aware of printing
to use channel 2 or 3.
A DOS-indepedent routine will be useful to set the A register.
Rewrite dosior>ior
after G+DOS: Convert the AF register. Make the
low-level words return it unchanged.
Note
|
Milestone: 0.15.0 |
Improve read-line
with 2-character line terminators.
Replace temporary variables from read-line
. Use locals or the stack
instead.
Rewrite read-file
in assembler. Or make the assembler conditional
structures independent.
Note
|
Milestone: 0.15.0 |
Fix: Use standard exception code #-13 (undefined word) in
interpret-table
instead of more specific #-256 (not a word nor a
number).
Note
|
Milestone: 0.15.0 |
Use term "throw code" instead of "exception code"?
"throw value" is used in Forth-2012.
Idea: Add where
to the default exception message. In order to save space,
where
should be in the library and patch itself into the default message.
Idea:
The correlation between DX-Forth exception code and DOS error code is given below: Exception DOS 0 0 no error -511 1 function number invalid (not used) -510 2 file not found -509 3 path not found -508 4 too many open files -507 5 access denied -506 6 invalid handle ... ... -257 255 unspecified error Note: To convert an exception code in the range -257 to -511 to its corresponding DOS error code, use: 255 AND
Note
|
Milestone: 0.15.0 |
Fix tt
: the first time the game runs, the limits of the arena are
not displayed.
Compare emit-udga
, defined in the kernel, with the draft .udga
,
defined in <graphics.udg.fs>.
Make xy>gxy
, x>gx
and y>gy
compatible with 42-cpl and 64-cpl
modes. Or add prefix "mode-32-" and write specific variants.
From BBL:
plot ( x y color -- ) line ( x1 x2 y1 y2 color -- ) get-color ( x y -- color ) circe ( x y radius color -- ) fill-shape ( x y fill-color boundary-color -- )
Use names "-box" instead of "-rectangle"?
-
A set to draw line boxes with graphic resolution.
-
A set to manipulate the contents of boxes, with caracter resolution. This set can be reused by the text windows.
From HARTFORTH (a Forth-79 compiler for TRS-80, by A.M. Graham, 1983):
GSET x y -> Set graphics bit at co-ordinates x,y. GCLR x y -> Clear graphics bit at co-ordinates x,y. G? x y -> f f=1 if graphics bit at x,y is set, f=0 otherwise. HLINE x y l -> Draw a horizontal line of length l from co-ordinates x,y. VLINE x y l -> Draw a vertical line of length l from co-ordinates x,y; l may be negative in both HLINE and VLINE. BOX x1 y1 x2 y2 -> Draw a rectangular box, top left corner at x1,y1; bottom right corner at x2,y2.
Reorganize relation between slow-gxy>scra_
, gxy>scra_
and
fast-gxy>scra_
. Remove fast-gxy>scra_
and the deferred
gxy>scra_
, then rename slow-gxy>scra_
to gxy>scra_
.
Note
|
Milestone: 0.15.0 |
Use the alternative version of xy>scra_
, which does not use the BC
register.
Make circle-pixel
throw an error by default. It cannot be a
deferred word, because it must return the address of a routine.
Alternative method to set paper colors:
: on-blue ( b1 -- b2 ) blue papery + ; : on-red ( b1 -- b2 ) red papery + ; ' noop alias on-black immediate
The names were borrowed from Pygmy Forth.
Better in Z80:
code on-blue ( b1 -- b2 ) h pop, h a ld, blue papery add#, pusha jp, end-code
Note
|
Milestone: 0.15.0 |
Improve the documentation about the usage of UDG codes greater than
255. emit-udg
admits them.
Test the new version of (cursor-addr)
and rename it to (xy>address
or similar, and so its family. Be consistent with the planned names to
get attribute addresses from cursor and graphic coordinates.
Note
|
Milestone: 0.15.0 |
Write g-xy-attr@ ( gx gy — b )
and g-xy-attr! ( b gx gy — )
.
Write xy-attr@ ( col row — b )
and xy-attr! ( b col row — )
.
Problem: The fetch functions are provided already by xy>attr ( x y — b)
and gxy>attr ( x y — b)
, but the name notation used cannot be
extended to the store variants. Instead, xy>attr c!
and gxy>attr
c!
can be used.
Improve ocr
: Return a flag apart from the code, in order to make it possible
to recognize character zero:
\ ocr ( col row -- c true | false )
Or write a variant:
\ ocr? ( col row -- c true | false )
Factor adraw176
to write aline176
, which uses set-pixel
and is faster.
Write a similar alternative to rdraw
, rline
.
From CHForth:
STOP? "stop-question" EXTRA ( -- flag ) Return false is no key is pressed. Exception -28 occurs when the escape key was pressed. If the key was not space, return true. Wait for a second keypress and return true if it was not space, false otherwise. Exception -28 occurs when the escape key was pressed.
Remove discard-key
? It does exactly the same as key drop
, but faster, and
it uses only two bytes of data space (for push ix
).
Change: move key
to the library, as mode-key
or similar, and use a simpler
key
in the kernel (e.g. akey
from Afera).
Move the default contents of farlimit
and far-banks
, and the
configuration of RAM banks on +3DOS, which are hardcoded in cold
, to
the parameter area. When these values are changed by the application,
probably the new values should be preserved by cold
. Therefore the
application should be able to configure also the defaults.
0= ?exit
is used twice in the kernel: in ?(
and save-buffers
. 4
bytes could be saved by using 0exit
instead, which is in the
library. But 0exit
needs 8 bytes. 2 more instances of 0= ?exit
would be needed to compensate.
Words that can be moved to the library:
umin
, umax
, char+
, char-
, break-key?
,
default-break-key?
, get-drive
, np!
…
Study how to move line>string
and undefined?
to the library. They
are not used in the kernel, but they are needed by the need
utility.
Note
|
Milestone: 0.15.0 |
Rewrite m+
in Z80 (the version adapted from Z88 CamelForth doesn’t
pass the Forth-2012 Test Suite).
From CHForth’s <MISCUTIL.FRT>:
: 2^x 1 swap lshift ; : DLSHIFT 0 ?do d2* loop ; : DRSHIFT 0 ?do d2/ $7FFF and loop ;
Rename polarity
sgn
? First check which is the most common name.
sgn
is used by Forth Foundation Library in its config file, and by
Gforth.
Convert base.
into a complete definer, in order to make it more
versatile. Then document it.
Share a common random seed. Now fast-rnd
uses the OS single-cell
variable, while rnd
uses a Forth double-cell variable.
Note
|
Milestone: 0.15.0 |
Rewrite between
in Z80, just to prepare the parameters and jump into
within
? Benchmark.
Remove module <math.number.prefix.fs>, unless the standard prefixes are made optional in the kernel.
: ?ifelse ( x1 x2 f -- x1 | x2 ) if drop else nip then ; : ifelse ( x1 x2 f -- x1 | x2 ) rot ?ifelse ;
If base
were not a user variable, binary
, hex
and decimal
would be smaller in Z80 than in Forth.
Idea: 2 more bytes for base
, to be used as save-restore space.
: switch ( a -- ) dup cell+ exchange ; \ Exchange the cells stored at _a_ and the address of the \ following cell. \ Example: base switch hex base switch
Use this to factor dec.
and write decu.
or udec.
(useful in
where
).
Name switch
is taken by a control flow structure.
ROTATE n1 n2 -- n3 Rotate the value n1 left n2 bits if n2 is positive, right n2 bits if n2 is negative. Bits shifted out of one end of the cell are shifted back in at the opposite end. \ Standard: Forth-79 (Reference Word Set); Forth-83 (Appendix \ B. Uncontrolled Reference Words).
Note
|
Milestone: 0.15.0 |
The idiom -1 =
is used twice in the kernel. It could be defined this way:
_code_header minus_one_equals_,'-1=' pop hl minus_one_equals.hl: ld a,$FF cp h jp nz,false_ cp l jp nz,false_ jp true_ ; 14 B
Or:
_code_header rminus_one_equals_,'-1=' pop hl minus_one_equals.hl: ld a,$FF cp h jr nz,false_ cp l jr nz,false_ jr true_ ; 11 B
Or:
_code_header minus_one_equals_,'-1=' pop hl minus_one_equals.hl: inc h inc l ld a,h or l jp nz,false_ jp true_ ; 11 B
Or:
_code_header minus_one_equals_,'-1=' pop hl minus_one_equals.hl: inc h inc l ld a,h or l jr nz,false_ jr true_ ; 09 B
Or:
_code_header minus_one_equals_,'-1=' pop hl minus_one_equals.hl: inc hl ld a,h or l jp nz,false_ jp true_ ; 10 B
Or:
_code_header minus_one_equals_,'-1=' pop hl minus_one_equals.hl: inc h inc l jr zero_equals.hl ; 05 B
Therefore, replacing two instances of -1 =
with calls to -1=
would
save only 1 byte in total (because -1
is a code word), but probably
the code would be a bit faster.
And an alias true=
could be defined as well.
Note
|
Milestone: 0.15.0 |
Implement 2-cell operators from Spectrum Forth-83. Most of them are written in Z80.
Note
|
Milestone: 0.15.0 |
Change the order of the parameters of %
and u%
, after Starting Forth pp
103 .. 105.
Modify interpret
to be patched by a floating-point implementation in order
to recognize floating-point numbers.
Idea to improve number?
, or to write an optional alternative: Return the
chars and positions of every point, not only the last one. Convert dpl
to a
backwards compatible array:
+0 cell: position of the last point +2 byte: last point +3 cell: position of the last but one point +5 byte: last but one point etc.
A new variable #dpl
would hold the number of points.
Idea: Use the ROM calculator memories (0 .. 5) as floating-point non-recursive
locals. Problem: some calculator’s words use them (eg. |over
). They could be
recursive, because their address can be changed with the system variable MEM;
they could be pointed to a frame in the return stack.
Simpler idea: use the calculator memories them as is, as temporary storage. The ROM allocates 6*5 bytes, but 32*5 can be used.
Note
|
Milestone: 0.15.0 |
Idea:
\ Copyright Leonard Zettel 1999 \ This material is released to the public domain without \ warranty as to fitness for any purpose. \ Use at your own risk. \ Words to handle a user-created stack as a linked list with nodes of arbitrary size. : n! ( n1 .. nn addr n --) \ Store n1 to nn in consecutive cells \ starting at addr. CELLS OVER + SWAP DO I ! 1 CELLS +LOOP ; : n@ ( addr n -- n1 .. nn) \ Fetch n consecutive values starting at \ addr + (wordsize)*(n-1) & leave them \ on the stack. 1- CELLS OVER + DO I @ -1 CELLS +LOOP ;
n!
and n@
already exist in the library, but the order of the values is
reversed. They could be renamed -n!
and -n@
.
Note
|
Milestone: 0.15.0 |
Idea from Walter Elehew’s L.O.V.E. Forth, 1991:
THREAD SEGMENT
Forth high-level (:) words are compiled into a sequence of 16 bit addresses, called threads. This segment contains these threads, CONSTANT and LITERAL values, and pointers to data and code. In the majority of applications this segment fills up the fastest. Basic operators: TS:@ TS:! TS:, TS:HERE Note that there are no single byte operators - all elements in this segment are two bytes. EXECUTE ( TS:addr -- ) Accepts the code field address. TS:DUMP ( TS:addr, #bytes -- ) Dumps bytes from the specified address. Many words with compile-time usage accept or return addresses in this segment:
L.O.V.E. Forth runs on DOS using 5 segments. See its <SEGMENT.DOC> for details.
Improve (heap-in
and (heap-out
to preserve the current bank
instead of restoring the default one.
Implement the proposed registers from Updating the Forth Virtual Machine, by Pelc, Euroforth 2008. Compare with the current implementation of the A register, from Z88 CamelForth.
Note
|
Milestone: 0.15.0 |
Idea to support memory larger than 128 KiB, provided Pentagon and Scorpion:
Of course, far-banks
can be configured by the program, any time,
to use a different set of banks.
But there could be an optional, similar system to use 32-bit
addresses… farfar-banks
, vfar-banks
, 32far-banks
,
huge-banks
.
Using several switchable configurations of far-banks
seems easier,
though.
Write behead ( "name" — )
. DX-Forth uses behead ( "name1" "name2" — )
.
hidden ( nt — )
is already in the kernel.
Ideas from CFT Forth:
BASE>R R>BASE #CONTEXT ( -- a ) (numCONTEXT) The number of entries in the vocabulary stack. #WORDS ( -- n ) (countwords) Returns the number of words in the CURRENT vocabulary. !BITS ( 16b1 addr 16b2 -- ) (store-BITS) Store the value of 16b1 masked by 16b2 into the equivalent masked part of the contents of addr, without affecting bits outside the mask. +FLAG! ( u a -- ) (set-FLAG-store) The value at address a is ORred with u in-place. -FLAG! ( u a -- ) (clear-FLAG-store) The value at address a is ANDed with (NOT u) in-place. .BANKS ( -- ) (dot-BANKS) Prints out the current memory banking scheme. .BASE ( -- ) (dot-BASE) Prints out the base. .DATE ( -- ) (dot-DATE) Read and print out the date from the the real-time clock. .TIME ( -- ) (dot-TIME) Read and print out the time from the the real-time clock. .rs ( -- ) (dot-rs) Prints out the return stack non-destructively. 16* ( w -- w ) (16mul) Shift left four bits. 16/ ( u -- u ) (16div) Shift right four bits (one nybble). No sign extension. 1MS ( -- ) Delay for approximately 1 millisecond. 256* ( w -- w ) (256mul) Shift left eight bits. 256/ ( w -- w ) (256div) Shift right eight bits. >FLAGS ( a -- u ) (to-FLAGS-fetch) Given the PFA of a word, return its flags. >LINK@ ( a -- a | f ) (to-LINK-fetch) Given the PFA of a word, return the head address of the word preceding it in the vocabulary. If this is the first word in the vocabulary, false (zero) is returned.
Make the following environment question depend on the current values, which can change when multitasking is active:
$2C +origin @ constant return-stack-cells ( -- n ) \ Maximum size of the return stack, in cells. $2A +origin @ constant stack-cells ( -- n ) \ Maximum size of the data stack, in cells.
Note
|
Milestone: 0.15.0 |
Move bank
to the library?
Set first-locatable
to 1 by default and review the block headers of
the need
tool. This way, any non-library disk can be used in drive 0
without modifying first-locatable
.
Don’t include the new block 0 files into the old disks (games, tests, benchmarks) that included the library at the start.
Words that could be moved to the library, if the need
tool didn’t use them:
2over
, line>string
.
Note
|
Milestone: 0.15.0 |
-
Move the disk code, common only to +3DOS, G+DOS and TR-DOS, from <lib/dos.COMMON.fs> to <lib/dos.disk.COMMON.fs>. Keep in <lib/dos.COMMON.fs> only the code common also to NextZXOS.
-
Move
read-block
andwrite-block
to <lib/dos.disk.COMMON.fs>. -
Move
flush
to <lib/dos.disk.COMMON.fs>, because it must be included in the NextZXOS kernel.
Check need-here
: needed-word 2!
is duplicated. Compare with
locate-needed
.
Extract a common factor from need-here
and locate-needed
?
Note
|
Milestone: 0.15.0 |
Idea for a faster version of (located
: Load only the first sector of
the blocks, and do the search directly in the buffer, without the
line>string
step. It will be faster, but it’s lower level and may
give problems with recursion.
Improve load-program
: save and restore the source, in order to
continue loading after load-program
. This way, several programs can
be loaded this way.
Add //
to ignore the rest of the source, as a shorter alternative to exit
to exit the current block.
Make need-here
unnecessary: Always check the current block, just in case.
Many needed words are in the same block.
Note
|
Milestone: 0.15.0 |
Write needs
to do multiple need
on one line of a block,
saving space
needs word1 word2 word3 word4 needs word5 word6 word7 word8
Write need( )
to do the same without the one-line limit:
need( word1 word2 word3 word4 word5 word6 word7 word8 )
: need( ( "name#1" ... "name#n" "<paren>" -- ) begin parse-name 2dup s" )" str= 0= while needed repeat 2drop ;
need\
is clearer than needs
to parse the current line, but need(
seems the best option.
Problem: need(
should use refill
, in case the list is splitted
between two blocks of the program, where no block headers are
used.
Note
|
Milestone: 0.15.0 |
Finish the alternative version of indexer
to index the blocks on the fly as
they are being searched by need
and family, i.e., not in advance.
Support multiline block headers with an improved version of (located)
, in
order to make more long-name short definitions into one block:
( very-long-word-1 very-long-word-2 very-long-word-3 very-long-word-4 very-long-word-5 very-long-word-6 )
See for example <chars.fs>, <keyboard.MISC.fs>.
Problem: this would force changes in fsb and fsb2.
Title | Vo | N | Pag | Note |
---|---|---|---|---|
Turning the Stack into Local Variables |
03 |
6 |
185 |
Implemented: locals.arguments.fs |
Anonymous Variables |
06 |
1 |
033 |
Implemented: locals.anon.fs |
Local Definitions |
06 |
6 |
016 |
Discarded: |
Letter "Stack Your Locals" |
07 |
5 |
005 |
Discarded: Modification of Vo06N6 |
Local Variables |
09 |
4 |
009 |
Discarded: Complete but complex, and not recursive |
Letters "Local Variables" |
09 |
5 |
005 |
Implemented: locals.local.fs |
Letters "Code for Local Variables" |
10 |
1 |
006 |
Modification for FD Vo09N4 |
Headless Local Variables and Constants |
10 |
1 |
019 |
Interesting, but for F83 |
Letters "Local Variables Revisited" |
10 |
5 |
005 |
|
Local Variables and Arguments |
11 |
1 |
013 |
Seen |
Local Variables - Another Technique |
11 |
1 |
018 |
Seen |
Prefix Frame Operators |
11 |
1 |
023 |
Note
|
Milestone: 0.15.0 |
-
Simple locals, by Wil Baden, 1987-01-01, http://atariwiki.strotmann.de/wiki/Wiki.jsp?page=Local%20Variables
>>link far!
is used in forget-transient
, but it’s what unlink-internal
does. Factor and reuse.
Improve transient
to actually unlink all the transient words? This means
backuping and restoring the latest definition of all word lists…
Newsgroups: comp.lang.forth Date: Wed, 3 Aug 2016 01:18:18 -0700 (PDT) In-Reply-To: <[email protected]> Message-ID: <[email protected]> Subject: Re: Code management with wordlists From: hheinrich.hohl ...
Excising
This method was used in LMI PC/FORTH and UR/FORTH.
EXCISE <word1> <word5>
This command hides the headers of <word1> through <word5> by excising their headers from the linked list in the dictionary.
Together with the ability to create binary overlays, the LMI FORTH compilers enabled the user to create modules that showed only words that are relevant for the end user.
Note
|
Milestone: 0.15.0 |
-
Rename
cls-chars0
andcls-chars1
. -
Rename
(load-program
toload-program>
?
Note
|
Milestone: 0.15.0 |
Homogenize the usage of prefix "far". In some words it’s separated by a dash.
Note
|
Milestone: 0.15.0 |
Look for better names for private{
and }private
. private
and
end-private
are fine, except private
is taken.
Rename flip
to swab
? swab
was the name used by LaForth, c. 1980.
Its origin seems to be a PDP-11 mnemonic for "swap byte":
From The Jargon File (version 4.4.7, 29 Dec 2003) [jargon]: swab /swob/ [From the mnemonic for the {PDP-11} `SWAp Byte' instruction, as immortalized in the dd(1) option conv=swab (see {dd})] 1. vt. To solve the {NUXI problem} by swapping bytes in a file 2. n. The program in V7 Unix used to perform this action, or anything functionally equivalent to it. See also {big-endian}, {little-endian}, {middle-endian}, {bytesexual}.
Improve ?(
with refill
, to cross block boundaries? This would be
needed for load-program
.
When loading a program with load-program
, make (
behave like in the
Forth-2012 FILE word set.
Move words that programs don’t need (e.g. greeting
, .unused
,
version
…) to the top of the kernel definitions. Then write a word
to remove all of them, including itself, and sets the new values of
the pointers. This way, the program can get rid of all of them at the
start of the compilation and get some extra memory.
Write get-xstack
to return the latest address used by xstack
,
which should be renamed set-xstack
.
Use the code of rp@
as storage of the pointer. This save one cell
from the parameter area of the kernel. Or use any ld
hl,(return_stack_pointer)
of a more used word, to make the most from
the 10 saved T-cycles. >r
is a good candidate. Better yet, the
do_colon
part of :
. Better yet, exit
.
But this change would be incompatible with multitasking.
Note
|
Milestone: 0.15.0 |
Make the return stack grow toward high memory and move it below the data stack. This way both stacks can share a common free space. This is an advantage because you can have programs which need quite some return stack depth, but few data elements - or the inverse. "Stack overflow" means both pointers cross. The idea was taken from 4tH:
Message-ID: <[email protected]> From: Hans Bezemer Subject: Re: Stack Sizes Newsgroups: comp.lang.forth Date: Tue, 04 Oct 2016 20:46:33 +0200
Note
|
Milestone: 0.14.0 |
Include the Note Frequencies table into the manual. See <sound.48.fs>.
Note
|
Milestone: 0.15.0 |
Move the stringer
buffer to the top of the dictionary, making it
possible to to resize it at the start of the application, without
wasting its original space.
Problem: default-stringer
would not be reliable.
From CHForth’s <MAKEHELP.FRT>:
: COMPARE-UPPERCASE ( c-addr1 u1 c-addr2 u2 -- -1 | 0 | 1 ) LOCALS| u2 c2 u1 c1 | u1 u2 MIN 0 DO c1 I + C@ >UPC c2 I + C@ >UPC - ?DUP IF 0< IF -1 ELSE 1 THEN UNLOOP EXIT THEN LOOP u1 u2 - DUP IF 0< IF -1 ELSE 1 THEN THEN ;
Improve sconstant
or write a variant to store long strings: store
only the text, not the length, and create a 2constant
to return
address and length.
Add shold
(from DX-Forth):
SHOLD ( c-addr u — ) A
Add string c-addr u to the beginning of the pictured numeric output string.
It seems the only way to move stringer
to limit
(making it easier
to reconfigure by the program, without wasting its original space) is
to modify find-name-from
to page in the default bank before fetching
every character…
Generalize parse-esc-string
and (parse-esc-string)
to accept a
delimiter character, like parse
. Then implement .\(
.
Improve substitute
and replaces
with a configurable search order, similar
to that implemented for escaped strings.
Remove bounds checking from }
(Noble’s arrays)
and keep a copy of it as ?}
, for debugging.
Fix tape-file>
: when the file length attribute is not zero (zero
means undefined) or the real file lenght to be loaded, the ROM routine
returns to BASIC with "Tape loading error". This crashes the system
(because the message cannot be printed, because the lower screen has
no lines).
The simplest solution seems to remove the parameter and always use 0 internally.
Note
|
Milestone: 0.15.0 |
Fix:
Tests not passed from Forth-2012 Test Suite:
T{ 0 (\?) ! [?DEF] ?DEFTEST1 (\?) @ -> -1 }T
Convert get-time
to uptime
. Then rewrite set-time
after
set-date
and rewrite get-time
to make a calculation from the set
time and the current ticks count…
Try simpler alternative to ms
, based on this loop found in the Plus
D disassembly:
; Wait about 1 ms ld b,0 rest_1: djnz rest_1 ; 13/08 T ; 255*13+8= 3323 T
But it needs to be adjusted slightly depending on the machine.
Note
|
Milestone: 0.15.0 |
Deprecate bench{
, }bench
and family, or replace with ticks
,
elapsed
, timer
and family.
Note
|
Milestone: 0.15.0 |
Adapt from lina:
DECIMAL TICKS DNEGATE 1000 MS TICKS D+ DROP CONSTANT TICKS-PER-SECOND
Note
|
Milestone: 0.15.0 |
Fix see
: it recognizes an initial code word, e.g. see over
, but
not when that word is inside another word and Enter is pressed at it.
Improve .os-chans
: The 128 check, used by G+DOS, does not work
after a disk channel has been added. Find out how to detect the end of
the table.
Note
|
Milestone: 0.15.0 |
Improve see-colon-body
: make recursion work also with non-colon
words.
Add : #user ( — n ) udp @ ;
. #user
is proposed by Andrew Haley
in _A multi-tasking wordset for Standard Forth`, EuroForth 2017.
Update the user variables that are initialized (warnings
has been removed,
but it is used by lastblk
, which does not need initialization).
Rename (user)
to user
? That was the original name in fig-Forth, Forth-79
and Forth-83. Choose an alternative for the current user
, defined in the
library.