• portable or not? Volatile strings

    From albert@spenarnc.xs4all.nl@21:1/5 to All on Sun Aug 11 15:35:38 2024
    I come across a tetris game, and there were bricks defined in
    this way:

    : DEF-BRICK CREATE 4 0 DO
    ' EXECUTE 0 DO DUP I CHARS + C@ C, LOOP DROP
    REFILL DROP
    LOOP
    DOES> ROT 4 * ROT + 2* CHARS + ;

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    Apparently the data field of bricks are filled in some mysterious
    way by DEF-BRICK but that is not the subject.
    It does some parsing from the input stream, which is kind of
    tricky. As REFILL is not present in lina's core, you must
    do "-traditional- WANTED" , but that still is not the issue.

    I made S" " such that it ALLOT's the string at HERE, to
    prevent problems with going out of scope, even in interpret mode.
    (Only 256,000,000,000 -10 bytes left).

    This doesn't sit well with the definition of BRICK1 ,
    that sees its data area grabbed.
    You are probably not surprised that tetris doesn't work.

    The question is, is it legal to store these temporary strings
    in the dictionary in this way?

    [ It was sufficient to replace S" with S"' in order to make it run:
    : S"' &" PARSE ;
    ]

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to ruvim.pinka@gmail.com on Mon Aug 12 11:01:48 2024
    In article <v9cfp9$364en$1@dont-email.me>,
    Ruvim <ruvim.pinka@gmail.com> wrote:
    On 2024-08-11 17:35, albert@spenarnc.xs4all.nl wrote:
    I come across a tetris game, and there were bricks defined in
    this way:

    : DEF-BRICK CREATE 4 0 DO
    ' EXECUTE 0 DO DUP I CHARS + C@ C, LOOP DROP >> REFILL DROP
    LOOP
    DOES> ROT 4 * ROT + 2* CHARS + ;

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    Apparently the data field of bricks are filled in some mysterious
    way by DEF-BRICK but that is not the subject.
    It does some parsing from the input stream, which is kind of
    tricky. As REFILL is not present in lina's core, you must
    do "-traditional- WANTED" , but that still is not the issue.

    I made S" " such that it ALLOT's the string at HERE, to
    prevent problems with going out of scope, even in interpret mode.
    (Only 256,000,000,000 -10 bytes left).

    This doesn't sit well with the definition of BRICK1 ,
    that sees its data area grabbed.
    You are probably not surprised that tetris doesn't work.

    The question is, is it legal to store these temporary strings
    in the dictionary in this way?


    Strings that are stored relatively to the HERE address may become
    invalid after:
    - a definition is created via a defining word;
    - definitions are compiled with : or :NONAME;
    - data space is allocated using ALLOT, `,` (comma),
    `C,` (c-comma), or ALIGN.
    — as "3.3.3.6 Other transient regions"

    Not relevant. My "transient" region is permanent. That I have
    permission to invalidate doesn't affect me.

    <https://forth-standard.org/standard/usage#usage:transient> says.

    All affected transition regions shall be listed. If a region is not
    listed as affected, than it is not affected by allocating data space memory.

    My regions are not affected. So again this is not relevant.



    The section "11.3.4 Other transient regions" ><https://forth-standard.org/standard/file#file:buffers> says:

    | The system provides transient buffers for S" and S\" strings.
    | These buffers shall be no less than 80 characters in length,
    | and there shall be at least two buffers. The system should be
    | able to store two strings defined by sequential use of
    | S" or S\". RAM-limited systems may have environmental
    | restrictions on the number of buffers and their lifetimes.

    A permanent buffer can count as transient.



    Since this doesn't say that the buffer my become invalid after some
    memory allocation, the buffer shall not become invalid after any memory >allocation (by default).

    That is putting restriction to my buffer.


    In the same time, a Forth system is allowed to limit the buffer lifetime
    (for example, till the next memory allocation), and document it as an >environmental restriction.

    Lots of talk of whether the buffers become invalid.
    My buffers never become invalid. That is not the point.
    The standard talks about transient region. My regions are permanent
    and there are other ways to handle S" , say by using ALLOCATE.
    To call a region transient and then restrict how transient they are,
    make a region not really temporary. So in this respect I am in the clear.
    Note that as S" is in a definition, the string is bound to be permanent.

    So I think the program is not portable, because what I do is perfectly
    legal.
    I can't make out what you think.


    [ It was sufficient to replace S" with S"' in order to make it run:
    : S"' &" PARSE ;
    ]

    Okay let's say it out loud. Classic Forth is not fit for handling strings.
    A denotation that generates a constant string "blablabla" that has
    a status as a number is long overdue.
    The mindset of formulating standards is so 70's.


    Groetjes Albert
    --
    Ruvim


    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to ruvim.pinka@gmail.com on Mon Aug 12 11:31:17 2024
    In article <v9ch3d$364en$2@dont-email.me>,
    Ruvim <ruvim.pinka@gmail.com> wrote:
    On 2024-08-11 17:35, albert@spenarnc.xs4all.nl wrote:
    I come across a tetris game, and there were bricks defined in
    this way:

    : DEF-BRICK CREATE 4 0 DO
    ' EXECUTE 0 DO DUP I CHARS + C@ C, LOOP DROP >> REFILL DROP
    LOOP
    DOES> ROT 4 * ROT + 2* CHARS + ;

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    Apparently the data field of bricks are filled in some mysterious
    way by DEF-BRICK but that is not the subject.
    It does some parsing from the input stream, which is kind of
    tricky. As REFILL is not present in lina's core, you must
    do "-traditional- WANTED" , but that still is not the issue.

    I made S" " such that it ALLOT's the string at HERE,

    This is not allowed, without any options.

    The alloted data space regions shall be contiguous unless "definitions
    are added to or removed from the dictionary between allocations"
    (3.3.3.2), or the function of `INCLUDED` is performed (11.6.1.1718, >11.6.2.1714). No other conditions are mentioned anywhere.

    That settles it. Note that it applies to interpret mode only,
    during a definition being permanent is not an issue because it is in a definition.
    This is a defect ("bug") in S" in ciforth.

    The only solution is to make S" state smart:
    : S" STATE @ IF POSTPONE " ELSE &" PARSE ; IMMEDIATE

    [ Before it was an alias for the "-as-a-prefix without the
    prefix flag.
    : S" POSTPONE " ; IMMEDIATE
    It sticks to the design rule for ciforth that only denotations,
    generalisation of numbers, are allowed to be state smart. ]


    to prevent problems with going out of scope, even in interpret mode.
    (Only 256,000,000,000 -10 bytes left).

    This doesn't sit well with the definition of BRICK1 ,
    that sees its data area grabbed.
    You are probably not surprised that tetris doesn't work.

    The question is, is it legal to store these temporary strings
    in the dictionary in this way?

    [ It was sufficient to replace S" with S"' in order to make it run:
    : S"' &" PARSE ;
    ]



    --
    Ruvim

    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to albert@spenarnc.xs4all.nl on Mon Aug 12 12:36:18 2024
    On 12/08/2024 10:01, albert@spenarnc.xs4all.nl wrote:
    In article <v9cfp9$364en$1@dont-email.me>,
    Ruvim <ruvim.pinka@gmail.com> wrote:
    is way?


    Strings that are stored relatively to the HERE address may become
    invalid after:
    - a definition is created via a defining word;
    - definitions are compiled with : or :NONAME;
    - data space is allocated using ALLOT, `,` (comma),
    `C,` (c-comma), or ALIGN.
    — as "3.3.3.6 Other transient regions"

    Not relevant. My "transient" region is permanent. That I have
    permission to invalidate doesn't affect me.

    <https://forth-standard.org/standard/usage#usage:transient> says.

    All affected transition regions shall be listed. If a region is not
    listed as affected, than it is not affected by allocating data space memory.

    My regions are not affected. So again this is not relevant.



    The section "11.3.4 Other transient regions"
    <https://forth-standard.org/standard/file#file:buffers> says:

    | The system provides transient buffers for S" and S\" strings.
    | These buffers shall be no less than 80 characters in length,
    | and there shall be at least two buffers. The system should be
    | able to store two strings defined by sequential use of
    | S" or S\". RAM-limited systems may have environmental
    | restrictions on the number of buffers and their lifetimes.

    A permanent buffer can count as transient.



    Since this doesn't say that the buffer my become invalid after some
    memory allocation, the buffer shall not become invalid after any memory
    allocation (by default).

    That is putting restriction to my buffer.


    In the same time, a Forth system is allowed to limit the buffer lifetime
    (for example, till the next memory allocation), and document it as an
    environmental restriction.

    Lots of talk of whether the buffers become invalid.
    My buffers never become invalid. That is not the point.
    The standard talks about transient region. My regions are permanent
    and there are other ways to handle S" , say by using ALLOCATE.
    To call a region transient and then restrict how transient they are,
    make a region not really temporary. So in this respect I am in the clear. Note that as S" is in a definition, the string is bound to be permanent.

    So I think the program is not portable, because what I do is perfectly
    legal.
    I can't make out what you think.


    [ It was sufficient to replace S" with S"' in order to make it run:
    : S"' &" PARSE ;
    ]

    Okay let's say it out loud. Classic Forth is not fit for handling strings.
    A denotation that generates a constant string "blablabla" that has
    a status as a number is long overdue.
    The mindset of formulating standards is so 70's.


    Yes, transient regions are another Forth anachronism from the early days
    of Forth when memory was scarce and expensive. In my system all
    transient regions are permanent so I don't worry about them getting
    corrupted. The standard ought to be updated to make them permanent or
    make provision for the user to allot or allocate them.

    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to ruvim.pinka@gmail.com on Mon Aug 12 21:34:31 2024
    In article <v9crjs$364en$5@dont-email.me>,
    Ruvim <ruvim.pinka@gmail.com> wrote:
    On 2024-08-12 13:31, albert@spenarnc.xs4all.nl wrote:
    In article <v9ch3d$364en$2@dont-email.me>,
    Ruvim <ruvim.pinka@gmail.com> wrote:
    On 2024-08-11 17:35, albert@spenarnc.xs4all.nl wrote:
    [...]
    I made S" " such that it ALLOT's the string at HERE,

    This is not allowed, without any options.

    The alloted data space regions shall be contiguous unless "definitions
    are added to or removed from the dictionary between allocations"
    (3.3.3.2), or the function of `INCLUDED` is performed (11.6.1.1718,
    11.6.2.1714). No other conditions are mentioned anywhere.

    That settles it. Note that it applies to interpret mode only,
    during a definition being permanent is not an issue because it is in a
    definition.
    This is a defect ("bug") in S" in ciforth.

    The only solution is to make S" state smart:
    : S" STATE @ IF POSTPONE " ELSE &" PARSE ; IMMEDIATE

    This implementation implies an environmental restriction: the string
    returned by the interpretation semantics of `S"` is valid until a
    subsequent invocation of `REFILL`, because the returned string is
    located in the input buffer.

    Remember ciforth is not only "computer intelligence Forth"
    it is also "close to iso forth", cutting corners for simplicity.
    There is no REFILL in ciforth, all files are slurped.

    In my lisp , manx , ciasdis I never needed REFILL.
    In the above tetris example, this S" works with REFILL.

    I implemented REFILL in the library. Dutch Forth Users wanted
    that.
    For each nested include you need a separate buffer for each file.
    Fortunately the block/screen buffers can serve because they have a
    lock/unlock state.
    Still it was a pain, and you have to carefully load all facilities
    belonging to a -traditional- expansion at the same time,
    because you probably need WORD FIND .
    7 blocks have to be loaded,

    In the presence of REFILL I have to load the ALLOCATE wordset
    and follow $" PARSE with $MAKE-PERMANENT or some such.

    But ... the code becomes better without REFILL.

    In my book the code should be

    " "
    "###### "
    " ## "
    " "
    DEF-BRICK BRICK1

    Instead of

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    The code (untested) could be
    : DEF-BRICK CREATE
    2>R 2>R 2>R 2>R
    2R> ,, 2R> ,, 2R> ,, 2R> ,,
    DOES> ... ;

    More Forth like. First data then creation of a structure with it.
    More readable code. No brain twisting REFILL where the first word
    is looked up in the dictionary via ' .

    At the expense of storing the strings two times in the dictionary.
    (I know most Forthers really get sick by the idea alone.)



    [ Before it was an alias for the "-as-a-prefix without the
    prefix flag.
    : S" POSTPONE " ; IMMEDIATE

    In this implementation the interpretation semantics are incorrect, right?

    Right. S" aap" does the same as "aap" storing the string at HERE.
    The former finds `` S" '' in the dictionary, the latter `` " ''
    found as a prefix. S"aap" is not found, because S" is not marked
    PREFIX.



    It sticks to the design rule for ciforth that only denotations,
    generalisation of numbers, are allowed to be state smart. ]



    --
    Ruvim

    NOTE:
    : ,, HERE SWAP DUP ALLOT MOVE ;
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to dxforth@gmail.com on Tue Aug 13 10:39:25 2024
    In article <66badc17$1@news.ausics.net>, dxf <dxforth@gmail.com> wrote:
    On 13/08/2024 5:34 am, albert@spenarnc.xs4all.nl wrote:
    ...
    In my book the code should be

    " "
    "###### "
    " ## "
    " "
    DEF-BRICK BRICK1

    Instead of

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    The code (untested) could be
    : DEF-BRICK CREATE
    2>R 2>R 2>R 2>R
    2R> ,, 2R> ,, 2R> ,, 2R> ,,
    DOES> ... ;

    OTOH it's no less difficult to write...

    : M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;

    : DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;

    DEF-BRICK BRICK1 M" "
    M" ###### "
    M" ## "
    M" "


    There you are!
    My solution is even more extreme, because it avoids
    parsing words altogether, apart from
    denotations^H^H^H^H^H^H numbers.

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to do-not-use@swldwa.uk on Wed Aug 14 12:38:55 2024
    In article <v9i05q$dh3v$1@dont-email.me>,
    Gerry Jackson <do-not-use@swldwa.uk> wrote:
    On 14/08/2024 08:03, Anton Ertl wrote:

    However, if we adopt Gerry Jackson's attitude and make every transient
    region permanent, creating a new permanent word (in a separate
    section) for every parsed number, string, etc. is fine, and ticking
    that word is fine, too. For most programs, the space taken by the
    recognized words is proportional to the size of the source code, which
    is acceptable on desktops with GBs of RAM. However, programs that use
    EVALUATE a lot will need more recognized-word storage. A contrived
    example is:

    : foo 1000000000 0 ?do s" 123" evaluate drop loop ; foo

    I wasn't clear enough when I suggested making transient areas
    'permanent'. Currently transient areas are overwritten either by the
    user or the system when it decides to re-use the transient region for >something else. If we take the <# buffer as an example, I meant that the
    user would declare the memory to be used for that buffer once and that
    would be used thereafter. It's permanent in the sense that the
    allocation is permanent, not the contents - the system would not be
    allowed to corrupt it. THe user would be free to re-use it or to make
    the contents permanent by declaring another bit of memory to be used for
    the buffer. If the user ALLOCATEd the memory it could later be FREEd by
    the user. The user manages it not the system.

    Constant strings should not be stored in a "transient area".
    Then trigger endless discussion for how long transient means.

    You are near my idea's of : $! $@ $+! $C+ $/
    Have low level abstractions of strings, but do not mix the
    storage requirements of this strings into these low level abstraction.

    Example
    CREATE $VAR1 100 ALLOT
    "AAP" \ is permanent. (somehow )
    2DUP $VAR1 $! \ You take responsibilty that `$VAR is large enough
    \ The constant string is still on the stack and can be reused.


    --
    Gerry

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Gerry Jackson@21:1/5 to Anton Ertl on Wed Aug 14 11:16:30 2024
    On 14/08/2024 08:03, Anton Ertl wrote:

    However, if we adopt Gerry Jackson's attitude and make every transient
    region permanent, creating a new permanent word (in a separate
    section) for every parsed number, string, etc. is fine, and ticking
    that word is fine, too. For most programs, the space taken by the
    recognized words is proportional to the size of the source code, which
    is acceptable on desktops with GBs of RAM. However, programs that use EVALUATE a lot will need more recognized-word storage. A contrived
    example is:

    : foo 1000000000 0 ?do s" 123" evaluate drop loop ; foo

    I wasn't clear enough when I suggested making transient areas
    'permanent'. Currently transient areas are overwritten either by the
    user or the system when it decides to re-use the transient region for
    something else. If we take the <# buffer as an example, I meant that the
    user would declare the memory to be used for that buffer once and that
    would be used thereafter. It's permanent in the sense that the
    allocation is permanent, not the contents - the system would not be
    allowed to corrupt it. THe user would be free to re-use it or to make
    the contents permanent by declaring another bit of memory to be used for
    the buffer. If the user ALLOCATEd the memory it could later be FREEd by
    the user. The user manages it not the system.

    --
    Gerry

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to dxforth@gmail.com on Thu Aug 15 11:04:41 2024
    In article <66bd607c$1@news.ausics.net>, dxf <dxforth@gmail.com> wrote:
    On 15/08/2024 5:46 am, minforth wrote:
    On Wed, 14 Aug 2024 18:49:45 +0000, albert@spenarnc.xs4all.nl wrote:
    Ticking a constant or constant string makes no sense.

    Try

    ' +INF

    It takes forever.

    Some folks think this works :)

    ' God


    Some Forth try to speed up by predefining constants:

    ' 0
    OK
    .S

    S[ 4206176 ] OK
    SEE 0

    0000,0000,0000,0000 CONSTANT 0

    What has to do with anything?

    Groetjes Albert
    --
    Don't praise the day before the evening. One swallow doesn't make spring.
    You must not say "hey" before you have crossed the bridge. Don't sell the
    hide of the bear until you shot it. Better one bird in the hand than ten in
    the air. First gain is a cat purring. - the Wise from Antrim -

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to the.beez.speaks@gmail.com on Thu Aug 22 12:59:15 2024
    In article <nnd$274f6c32$10db022f@ea48fe6bf4bc59ed>,
    Hans Bezemer <the.beez.speaks@gmail.com> wrote:
    On 13-08-2024 06:07, dxf wrote:
    On 13/08/2024 5:34 am, albert@spenarnc.xs4all.nl wrote:
    ...
    In my book the code should be

    " "
    "###### "
    " ## "
    " "
    DEF-BRICK BRICK1

    Instead of

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    The code (untested) could be
    : DEF-BRICK CREATE
    2>R 2>R 2>R 2>R
    2R> ,, 2R> ,, 2R> ,, 2R> ,,
    DOES> ... ;

    OTOH it's no less difficult to write...

    : M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;

    : DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;

    DEF-BRICK BRICK1 M" "
    M" ###### "
    M" ## "
    M" "


    In 4tH, the easiest solution would be:

    : BRICK@ ROT + @C SWAP 2* CHARS + ;

    CREATE BRICK1
    ," "
    ," ###### "
    ," ## "
    ," "
    DOES> BRICK@ ;

    I dislike the use of parsing here by ," . It happens to work
    because ," doesn't destroy the concatenation of HERE.
    So you couldn't check the solution without digging into the 4TH
    documentation.

    In these case parsing is more or less advantageous because it allows
    easier represent the bricks. The introduction of an auxiliary word M"
    that is easily understood and checked is far superior using ," .

    I changed my version to use the proposed M" now and it works fine.


    I could throw a bit of preprocessor magic in the mix, so it would
    resemble your solution even closer, but I guess you can do without ;-)

    Hans Bezemer
    --
    Temu exploits Christians: (Disclaimer, only 10 apostles)
    Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
    Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
    And Gifts For Friends Family And Colleagues.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From albert@spenarnc.xs4all.nl@21:1/5 to dxforth@gmail.com on Sat Aug 24 12:10:57 2024
    In article <66c94c52$1@news.ausics.net>, dxf <dxforth@gmail.com> wrote:
    On 22/08/2024 8:59 pm, albert@spenarnc.xs4all.nl wrote:
    In article <nnd$274f6c32$10db022f@ea48fe6bf4bc59ed>,
    Hans Bezemer <the.beez.speaks@gmail.com> wrote:
    On 13-08-2024 06:07, dxf wrote:
    On 13/08/2024 5:34 am, albert@spenarnc.xs4all.nl wrote:
    ...
    In my book the code should be

    " "
    "###### "
    " ## "
    " "
    DEF-BRICK BRICK1

    Instead of

    DEF-BRICK BRICK1 S" "
    S" ###### "
    S" ## "
    S" "

    The code (untested) could be
    : DEF-BRICK CREATE
    2>R 2>R 2>R 2>R
    2R> ,, 2R> ,, 2R> ,, 2R> ,,
    DOES> ... ;

    OTOH it's no less difficult to write...

    : M" [CHAR] " PARSE HERE OVER ALLOT SWAP MOVE ;

    : DEF-BRICK CREATE DOES> ROT 4 * ROT + 2* CHARS + ;

    DEF-BRICK BRICK1 M" "
    M" ###### "
    M" ## "
    M" "


    In 4tH, the easiest solution would be:

    : BRICK@ ROT + @C SWAP 2* CHARS + ;

    CREATE BRICK1
    ," "
    ," ###### "
    ," ## "
    ," "
    DOES> BRICK@ ;

    I dislike the use of parsing here by ," . It happens to work
    because ," doesn't destroy the concatenation of HERE.
    So you couldn't check the solution without digging into the 4TH
    documentation.

    In these case parsing is more or less advantageous because it allows
    easier represent the bricks. The introduction of an auxiliary word M"
    that is easily understood and checked is far superior using ," .
    ...

    For the general case that's true. OTOH 4tH is free to exploit what it has. >The original ANS-Forth version tried using S" but it got complicated due
    to the dual-action word. If standard compliance is the goal then options
    are limited. OTOH a Gforth user not caring about compliance could exploit >what he had and define things more succinctly:

    : M" \"-parse mem, ;

    (assuming he knew these words existed)

    I accept the use of non standard words if there is an advantage for it.
    In this case a small change keeps the program totally standard,
    at the same time allowing to escape confusion over allocation
    situations and having it run on a ciforth 10% of the complexity of
    gforth.

    I occasionally promote ciforth techniques, if they are substantially
    simpler and standard programs look akward in comparison.

    Probably mem, is the same as my
    : ,, HERE SWAP DUP ALLOT MOVE ;

    Groetjes Albert
    --
    Temu exploits Christians: (Disclaimer, only 10 apostles)
    Last Supper Acrylic Suncatcher - 15Cm Round Stained Glass- Style Wall
    Art For Home, Office And Garden Decor - Perfect For Windows, Bars,
    And Gifts For Friends Family And Colleagues.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)