Re: Problems with TIB again, I think



Did you get the problem resolved?

Christoph wrote:

\ parses a string (up to char on stack) and stores it, count before,
\ in the data-space
: str, ( c -- )
parse dup >r ( count on return stack )
here cell+
swap cmove ( move string to one cell after here )
r@ , ( compile count to here )
r> allot align ( get count and allocate mem for string, then align )
;

The issue here was moving the data before the space is allotted.
The second minor issue is that if you align first, then you know it's
aligned.

\ given the start address of a menu entry, returns the address
\ of the next entry
: nextmitem ( maddr -- maddr' )
cell+ ( proceed to string count )
dup @ aligned + ( get string count: convert to cells used )
cell+ ( to end of string and start of next entry )
;

\ given the address of a menu entry, returns address
\ and count of the menu item text
: getmenutext ( a -- a n )
1 cells + ( to string count )
dup @ ( get count )
swap 1 cells + swap
;

You know, you've made a data structure. You might feel like it's
clearer if you make words to deal with that.

: menuaction ( addr -- xt )
@ ;
\ address of string
: menustring ( addr -- addr' )
cell+ cell+ ;
\ length of string
: menustringlength ( addr -- n )
cell+ @ ;

Then you have the bother of the long words, but you don't ever again
have to think about how your data structure is set up. It's less
efficient, more address manipulation, but you always start with the
address of the start of the structure, which is simpler to think about
and easier to write stack diagrams for.

Not needed. You got it working fine without the extra layer of
abstraction. When it gets complicated at some point it turns into a
tossup whether you're better off keeping track of all the details in
your head or whether it's better to keep track of all the names. Either
way can be bad.

: getmenutext ( maddr -- saddr len )
dup menustring swap menustrenglength ;

: nextmitem ( maddr -- maddr' )
getmenutext aligned +
;

: :menu
create
does>
page 1 over ( badr cnt itemadr )
begin
dup @ ( get addr from menuitem )
0 = not while ( as long as end of entries not reached )

isn't 0= not redundant? Unless it makes it clearer for you.

\ print out menu, with index numbers
over . ( print counter )
dup getmenutext ( badr cnt itemadr txtadr txtcnt )
type cr ( print menuitem text ) ( badr cnt itemadr )
nextmitem ( proceed to next menuitem )
swap 1+ swap ( inc menuitem counter ) ( badr cnt itemadr )
repeat
drop ( drop address )
( badr cnt)
\ now wait for key and execute menuitem word
key 49 - 0 max swap 2 - min ( get number between 0 and counter )
( badr cnt )
0 ?do
nextmitem
loop
@ execute
;

This looks like a long word but it isn't -- it just looks long because
it has so many comments. And it needs the comments because the stack
goes 5 deep.

\ print out menu item, with index number
: .menuitem ( addr n -- )
cr . ( print counter )
getmenutext type ( print menuitem text )
;

: :menu
create
does>
page dup 0 ( badr itemadr count )
begin
over @ while ( as long as end of entries not reached )
1+ 2dup .menuitem
>r nextmitem r>
repeat
nip ( drop address )
( badr cnt)

\ now wait for key and execute menuitem word
key 49 - 0 max swap min ( get number between 0 and counter )

if you used [char] 1 - it would be easier for people who don't remember
their ASCII.
If somebody puts in a random key they get either the first menu item or
the last.
Is that what you want, or would you rather do something else, like let
them try again?

You're limiting the menu to 9 items. That should be plenty, but you
could easily change it to start with A if you decide to have a bad long
menu.

( badr cnt )
0 ?do
nextmitem
loop
@ execute
;

: (menuitem) ( char addr -- )
, ( store address )
str, ( compile string: count followed by string )
;

It's customary to put the align at the beginning jof (menuitem) instead
of at the end of str, . I don't think it would help this time. If
somehow anything were to happen to unalign things between one
(menuitem) and the next, you'd have a great big problem either way.
It's just the custom to set up what you need when you start, instead of
depending on everything to be set up when you start and then you clean
up after yourself. Maybe sometimes that custom lets you look for
trouble in the routine that didn't set things up right, instead of
finding the problem in one routine and looking for the one that messed
things up.

: menuitem ( addr -- )
bl swap (menuitem)
;

Here you can't have a space in your string.

: menuitem" ( addr -- )
[char] " swap (menuitem)
;

Here you can't have a " in your string.

If you're willing to put each string on a new line in your source code,
you could put anything but a line terminator in them. And there's no
ANS way to put a line terminator into a string anyway. ;)

Your examples all put the string at the end of the line, reasonably
enough.


Now that I think about it, when will you ever have a menu string longer
than 255 characters? Never, ever, it's already limited to one line by
PARSE . So instead of using a cell for the count you could just use a
counted string, and use COUNT to get the address-and-count for TYPE to
use. WORD would give you the counted string. It all gets simpler.
Except I'm not sure whether WORD is still in use by all the systems you
might want to run on. And there are a few systems that use COUNT in
peculiar ways, depending on WORD etc to give them counted strings.


Sorry to go on so long. I didn't intend criticism of your coding style,
I just started looking at possibilities. Extra time spent simplifying
code can pay off. However, I just looked at the code and came up with
things and didn't test any of it on any system. So I certainly made
mistakes that should be easy to fix with testing.

Regards,
Jet

.



Relevant Pages

  • Re: eForth 64bit trouble
    ... OVER CELL+! ... SWAP CELL+ SWAP CELL+ ... STOP NE E SE path-masks ... DUP 1 AND IF OVER R@ SWAP C! ...
    (comp.lang.forth)
  • Re: LSE64 in standard Forth
    ... believe few 32 bit Standard Forths implement a 64 bit cell size. ... : dup 2dup; ... : swap 2swap; ... This already includes split stacks. ...
    (comp.lang.forth)
  • Re: Size-specific memory access words
    ... IF 0 DO SWAP OVER CELL 1c!-le CELL+ LOOP ... THEN R> ?DUP IF 1c!-le ELSE DROP THEN; ... IF ROT DUP ROT 1c@-le -ROT SWAP THEN ?DUP ...
    (comp.lang.forth)
  • Problems with TIB again, I think
    ... cell, count of menu entry desciption string: ... swap cmove ... nextmitem (proceed to next menuitem) ...
    (comp.lang.forth)
  • VB, implementing the high score within this code
    ... Private possibleAs String ... Private Function SolvePuzzleAs Boolean ... ' Calculates the possible values for all the cell ...
    (microsoft.public.dotnet.languages.vb)