Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Adding thousands separators

167 views
Skip to first unread message

Ed

unread,
Feb 13, 2012, 5:24:22 AM2/13/12
to
No-frills code for adding thousands separators to a decimal
numeric string.

Assumes your Forth has some way of generating numeric
strings e.g. (D.) (F.) etc. If the source string lies in the PNO
buffer it will need copying elsewhere first. Customize for
your locale. If you can do it in less, let us know.

--

\ COMMAS.F
\
\ Add thousands separator to a decimal numeric string
\
\ version: 2012-02-13
\
\ - decimal input string must include a decimal point
\ - output string resides in the Forth pictured numeric
\ output buffer
\
\ This code is PUBLIC DOMAIN. Use at your own risk.

\ Extract character from end of string
: STRING/C ( a u -- a u-1 char )
1- 2dup chars + c@ ;

variable cnt

: COMMA$ ( a1 u1 -- a2 u2 )
<#
begin dup while
string/c dup hold [char] . =
until then
cnt off
begin dup while
string/c
dup [char] 0 - 10 u< cnt @ 3 = and
if [char] , hold cnt off then
hold 1 cnt +!
repeat
#> ;

[defined] DXFORTH [if] behead cnt cnt [then]


1 [if]
cr .( testing )
s" " comma$ cr type
s" -123." comma$ cr type
s" -1234.E-1000" comma$ cr type
s" -123456789.4500" comma$ cr type
s" +100000000.0000" comma$ cr type
s" $10000000" comma$ cr type
s" -INFINITY" comma$ cr type
s" NANS(32767)" comma$ cr type
s" !#$%'()*+-." comma$ cr type
[then]

--



Hugh Aguilar

unread,
Feb 13, 2012, 4:05:54 PM2/13/12
to
My novice package (http://www.forth.org/novice.html) has BIG. for
doing that. I also generate engineering and scientific formats.

Hans Bezemer

unread,
Feb 15, 2012, 2:48:04 AM2/15/12
to
Ed wrote:

> No-frills code for adding thousands separators to a decimal
> numeric string.
Hi Ed!

Since I don't use the largely useless NOVICE package, I'd be happy to
include this code in the next release of 4tH.

Thanks, clean, portable code - it seems like a very nice addition!

Hans

Ed

unread,
Feb 15, 2012, 6:19:16 PM2/15/12
to
Hugh Aguilar wrote:
> On Feb 13, 3:24 am, "Ed" <nos...@invalid.com> wrote:
> > No-frills code for adding thousands separators to a decimal
> > numeric string.
> >
> > Assumes your Forth has some way of generating numeric
> > strings e.g. (D.) (F.) etc. If the source string lies in the PNO
> > buffer it will need copying elsewhere first. Customize for
> > your locale. If you can do it in less, let us know.
> >
> > ...
>
> My novice package (http://www.forth.org/novice.html) has BIG. for
> doing that. I also generate engineering and scientific formats.

Yes. If processing [double] integers is all that's required
then the approach you took can be more efficient. Another
example can be found in FD 15/5 which adds #,S to the
regular <# #> words.





Doug Hoffman

unread,
Feb 15, 2012, 8:18:57 PM2/15/12
to
On 2/13/12 5:24 AM, Ed wrote:

> : COMMA$ ( a1 u1 -- a2 u2 )
> <#
> begin dup while
> string/c dup hold [char] . =
> until then
> cnt off
> begin dup while
> string/c
> dup [char] 0 - 10 u< cnt @ 3 = and
> if [char] , hold cnt off then
> hold 1 cnt +!
> repeat
> #> ;

Took me awhile to realize that "[char] 0 - 10 u<" was a test for valid
numeral. Equivalent to "[char] 0 [char] 9 1+ within" I think. Might be
a useful factor:

: numeral? ( char -- f ) [char] 0 - 10 u< ;


> s" !#$%'()*+-." comma$ cr type

Were you attempting to filter *all* garbage input? Not suggesting that
you should.

s" !#$%'(4*+-." comma$ cr type

-Doug

Doug Hoffman

unread,
Feb 16, 2012, 1:21:42 PM2/16/12
to
Years ago I grew tired of having to build the same/similar string
routines from scratch every time, and so created a string library. A
string library a solution could be something like the following:

string+ s
: numeral? ( char -- f ) [char] 0 [char] 9 1+ within ;
: comma$' ( a1 u1 -- a2 u2 )
s !:
s 1st: numeral? { num? }
[char] . s chsearch: \ is there a decimal point?
if
begin
s end: @ \ get position
4 - dup 0 > \ are there at least 5 chars left?
while
dup 1 > \ Are there >1 chars left?
num? or \ or is the first char a numeral?
while
s end: ! \ set new position and insert comma
[char] , s chinsert:
repeat then drop
then s @: ;

The local is easily discarded if desired.

While words like 1st: chsearch: and chinsert: may seem foreign and with
hidden complexity, for me they are familiar and are used as primitives
because they are *always* loaded. I suspect that others using their own
string libraries do the same.

-Doug

Ed

unread,
Feb 16, 2012, 8:29:03 PM2/16/12
to
Doug Hoffman wrote:
> ...
> Took me awhile to realize that "[char] 0 - 10 u<" was a test for valid
> numeral. Equivalent to "[char] 0 [char] 9 1+ within" I think. Might be
> a useful factor:
>
> : numeral? ( char -- f ) [char] 0 - 10 u< ;

I thought the same too! I called it DIGIT? and added it to my library.
The definition is dependent on 2's complement.

I considered WITHIN but it looked clumsy. I was going to define
BETWEEN but the definition above turned out simpler - and
even readable :)

>
> > s" !#$%'()*+-." comma$ cr type
>
> Were you attempting to filter *all* garbage input? Not suggesting that
> you should.

Just intended to show formatting required the presence of both
decimal point and decimal digits.



Paul Rubin

unread,
Feb 16, 2012, 11:44:35 PM2/16/12
to
"Ed" <nos...@invalid.com> writes:
> No-frills code for adding thousands separators to a decimal
> numeric string.

The string hacking seems a bit out of place to me. The following code
is pretty painful but I like that it's normal arithmetic. Floating and
double interfaces should be straightforward to add.

: z3 ( n -- ) \ print 1-3 digit n left-filled with leading zeros
s>d <# # # # #> type ;

: n3 ( n -- ) \ print 1-3 digit n with no zero-fill.
s>d <# #s #> type ;

: commafy ( n -- ) \ print n with comma separators every 3 places
dup 0< if [char] - emit negate endif
dup 1000 < if n3 else 1000 /mod recurse [char] , emit z3 endif ;

BruceMcF

unread,
Feb 17, 2012, 12:42:35 PM2/17/12
to
On Feb 16, 8:29 pm, "Ed" <nos...@invalid.com> wrote:
> Doug Hoffman wrote:

> > : numeral? ( char -- f ) [char] 0 - 10 u< ;

> I thought the same too!  I called it  DIGIT?  and added it to my
> library. The definition is dependent on 2's complement.

Why wouldn't it work in one's complement? Isn't '0' subtracted from an
ascii code one less than it "-1", which is $FE bit extended up? It
looks fine to me for ASCII7, or 8bit code pages based on ASCII7. Isn't
it good for a single Unicode code point as well (assuming sufficient
cell width)?

Don't know about signed-magnitude, but I don't see why its problematic
for either complement encoding.

Coos Haak

unread,
Feb 17, 2012, 3:32:40 PM2/17/12
to
Op Thu, 16 Feb 2012 20:44:35 -0800 schreef Paul Rubin:

> "Ed" <nos...@invalid.com> writes:
>> No-frills code for adding thousands separators to a decimal
>> numeric string.
>
> The string hacking seems a bit out of place to me. The following code

But the elegance of Ed's code is that COMMA$ omits TYPE.
It uses the practice of <# #> # etc. to build a string. You can TYPE that
but also store it somewhere, perhaps in a database or write it in aligned
columns.

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

A. K.

unread,
Feb 17, 2012, 4:41:46 PM2/17/12
to
From ANS 3.3.3.6:
The size of the pictured numeric output string buffer shall be at least
(2*n) + 2 characters, where n is the number of bits in a cell. Programs
that consider it a fixed area with unchanging access parameters have an
environmental dependency.

By using HOLD you fill the pict.numout buffer with additional commas
after each 3rd digit.
Shouldn't then the buffer size be increased by 33% ?

Andreas

BruceMcF

unread,
Feb 17, 2012, 9:52:10 PM2/17/12
to
On Feb 17, 4:41 pm, "A. K." <a...@nospam.org> wrote:
> By using HOLD you fill the pict.numout buffer with additional commas
> after each 3rd digit.
> Shouldn't then the buffer size be increased by 33% ?

No, the size of the HOLD buffer is sufficient for binary output,
comma's after each third digit is for decimal output, in which case
the hold buffer should have ample room for the comma's.

The glossary entry should perhaps note that it is intended for decimal
output.

A. K.

unread,
Feb 18, 2012, 4:39:19 AM2/18/12
to
Oops, of course you're right.
(although IF I print binary, I place a dot between every group of 4
digits for better readability, but that's just my way)

Ed

unread,
Feb 18, 2012, 5:22:37 AM2/18/12
to
ANS specs are minimums. In Fig-Forth the PNO buffer could
HOLD up to 68 characters - plenty for your formatted binary :)



A. K.

unread,
Feb 18, 2012, 7:12:38 AM2/18/12
to
#> et al digest double numbers. so worst case for such formatted binary
would mean
82 chars in a 32 bit system.

what's the actual market price for a byte?


Peter Knaggs

unread,
Feb 18, 2012, 11:30:10 AM2/18/12
to
Actually, in section 3.3.3.6 (Other transient regions) the standard states:

The size of the pictured numeric output string buffer shall be at
least (2n)+2 characters, where n is the number of bits in a cell."

Or, in other words, 34 characters in a 32 bit system. You can check
the size of this region by looking up the /HOLD environment query.

--
Peter Knaggs

Jan Coombs

unread,
Feb 18, 2012, 12:08:31 PM2/18/12
to
On 18/02/12 16:30, Peter Knaggs wrote:
>
> Actually, in section 3.3.3.6 (Other transient regions) the standard
> states:
>
> The size of the pictured numeric output string buffer shall be at
> least (2n)+2 characters, where n is the number of bits in a cell."
>
> Or, in other words, 34 characters in a 32 bit system. You can check
> the size of this region by looking up the /HOLD environment query.
>
Or in other other words perhaps 66B for a 32b system, enough to
hold a double expressed in binary?

BruceMcF

unread,
Feb 18, 2012, 5:46:51 PM2/18/12
to
On Feb 18, 11:30 am, "Peter Knaggs" <p...@bcs.org.uk> wrote:

> A. K. wrote:
>> On 18.02.2012 11:22, Ed wrote:

>>> ANS specs are minimums.  In Fig-Forth the PNO buffer could
>>> HOLD up to 68 characters - plenty for your formatted binary :)

Yes, my point was with respect to the minimums: space for unformatted
binary is space for decimal point and thousands-commas decorated
decimal.

For source intended to be portable, *requiring* more than an ANS spec
minimum ought to be documented. Simplest is to note that it is
intended for decimal output, in which case the ANS spec minimums are
ample.

>> #> et al digest double numbers. so worst case for such formatted
>> binary would mean 82 chars in a 32 bit system.

Yes ~ assuming no decimal point or sign, 16 more than the minimum
required to be available. On my reckoning base 3's OK, so "this
assumes that BASE is greater than 2" would be the most generic
assumption.

> Actually, in section 3.3.3.6 (Other transient regions) the standard
> states:

>      The size of the pictured numeric output string buffer shall be at
>      least (2n)+2 characters, where n is the number of bits in a
> cell."

> Or, in other words, 34 characters in a 32 bit system.  You can check
> the size of this region by looking up the /HOLD environment query.

(2*32+2)=66, as Jan noted. 34 chars is the minimum *possible* minimum,
since a 16bit system is the minimum standard cell size.

Anton Ertl

unread,
Feb 20, 2012, 10:24:56 AM2/20/12
to
BruceMcF <agi...@netscape.net> writes:
>On Feb 16, 8:29=A0pm, "Ed" <nos...@invalid.com> wrote:
>> Doug Hoffman wrote:
>
>> > : numeral? ( char -- f ) [char] 0 - 10 u< ;
>
>> I thought the same too! =A0I called it =A0DIGIT? =A0and added it to my
>> library. The definition is dependent on 2's complement.
>
>Why wouldn't it work in one's complement?

On one hand, with any of the three common representations for signed
nymbers, if the result of the subtraction is negative, it will appear
as a very large positive number when interpreted as unsigned number
(MSB is set).

On the other hand, the hardware may not really support full-width
unsigned numbers on non-2s-complement hardware (I am not an expert on
such hardware, so this is just guesswork), and u may be the same as
+n, and the implementation of U< may be the same as <. In that case
the code above would produce true for characters <'0'.

The justification for the non-standardness of the code above (allowing
the system to produce such unexpected results) would be that, if the
input is a u, the "-" produced an underflow (non-standard); or if the
input is seen as n, the "-" produced an "n", and you cannot apply U<
on it in a standard program (type error). This is all not solid,
because it's not clear if the standard defines a consistent type
system.

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2011: http://www.euroforth.org/ef11/

BruceMcF

unread,
Feb 20, 2012, 11:41:45 PM2/20/12
to
On Feb 20, 10:24 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:
> On the other hand, the hardware may not really support full-width
> unsigned numbers on non-2s-complement hardware (I am not an expert on
> such hardware, so this is just guesswork), and u may be the same as
> +n, and the implementation of U< may be the same as <.  In that case
> the code above would produce true for characters <'0'.

Yeah, I can see that for signed magnitude, that:
[+]$2F - [+]$30 = [-]$1

... might have domain problems for U< it's the one's complement that
puzzled me. Other than the result as an unsigned being one smaller, it
looks as kosher in one's complement as in two's complement to me.

Anton Ertl

unread,
Feb 21, 2012, 11:46:15 AM2/21/12
to
BruceMcF <agi...@netscape.net> writes:
>Yeah, I can see that for signed magnitude, that:
> [+]$2F - [+]$30 =3D [-]$1
>
>... might have domain problems for U< it's the one's complement that
>puzzled me.

If the sign bit is the MSB, and the hardware has a comparison
operation that considers a number with set MSB as a large number
(i.e., an "unsigned compare"), then a Forth system will use that
unsigned compare for U< and 9 -1 U< will be true whether -1 is
represented in 2s-complement, 1's complement, or sign-magnitude.

However, if the hardware does not have such an unsigned comparison,
only a signed comparison, and the Forth system implements U< to just
use this signed comparison without provision for dealing with negative
numbers, then 9 -1 U< will be false whether -1 is represented in
2s-complement, 1's complement, or sign-magnitude.

Andrew Haley

unread,
Feb 21, 2012, 1:23:03 PM2/21/12
to
Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
> BruceMcF <agi...@netscape.net> writes:
>>Yeah, I can see that for signed magnitude, that:
>> [+]$2F - [+]$30 =3D [-]$1
>>
>>... might have domain problems for U< it's the one's complement that
>>puzzled me.
>
> If the sign bit is the MSB, and the hardware has a comparison
> operation that considers a number with set MSB as a large number
> (i.e., an "unsigned compare"), then a Forth system will use that
> unsigned compare for U< and 9 -1 U< will be true whether -1 is
> represented in 2s-complement, 1's complement, or sign-magnitude.
>
> However, if the hardware does not have such an unsigned comparison,
> only a signed comparison, and the Forth system implements U< to just
> use this signed comparison without provision for dealing with negative
> numbers, then 9 -1 U< will be false whether -1 is represented in
> 2s-complement, 1's complement, or sign-magnitude.

Or, just use WITHIN ! :-)

Andrew.

BruceMcF

unread,
Feb 21, 2012, 2:29:16 PM2/21/12
to
On Feb 21, 11:46 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:
> However, if the hardware does not have such an unsigned comparison,
> only a signed comparison, and the Forth system implements U< to just
> use this signed comparison without provision for dealing with negative
> numbers, then 9 -1 U< will be false whether -1 is represented in
> 2s-complement, 1's complement, or sign-magnitude.

why then does a 2s-complement encoding guarantee that it will
necessarily work? Its the distinction between 2s-complement and 1s-
complement in the guarantee offered that I don't see.

BruceMcF

unread,
Feb 21, 2012, 2:32:16 PM2/21/12
to
On Feb 21, 1:23 pm, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
> Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
You could, indeed, conditionally compile:

[ -1 0 U< ] [IF] ... [ELSE] ... [THEN]

... but just using WITHIN is simpler, since then whether the U< works
correctly outside its standard domain is not an issue.

Ed

unread,
Feb 21, 2012, 8:46:18 PM2/21/12
to
BruceMcF wrote:
>
> ... but just using WITHIN is simpler, since then whether the U< works
> correctly outside its standard domain is not an issue.

Using WITHIN may be "simpler" but it has its costs. See below.

I make no apology for comparison technique I used. It's cheap,
easy, and works. I baulk at the notion of having to support
non 2's-complement machines at the cost of efficiency or
complicated compile-time options. Forth is not a strictly 'typed'
language. If we can exploit 2's complement machines to our
benefit, it would be amiss of us not to use it.

--

VFX Forth for Windows IA32
c MicroProcessor Engineering Ltd, 1998-2007

Version: 4.02 [build 2438]
Build date: 14 August 2007

Free dictionary = 7680282 bytes [7500kb]


: test1 [char] 0 [char] 9 1+ within ; ok
: test2 [char] 0 - 10 u< ; ok
ok

see test1
TEST1
( 004AAF10 8D6DF8 ) LEA EBP, [EBP+-08]
( 004AAF13 C7450030000000 ) MOV DWord Ptr [EBP], 00000030
( 004AAF1A 895D04 ) MOV [EBP+04], EBX
( 004AAF1D BB3A000000 ) MOV EBX, 0000003A
( 004AAF22 E88DDFF5FF ) CALL 00408EB4 WITHIN
( 004AAF27 C3 ) NEXT,
( 24 bytes, 6 instructions )
ok

see within
WITHIN
( 00408EB4 8B4500 ) MOV EAX, [EBP]
( 00408EB7 8B4D04 ) MOV ECX, [EBP+04]
( 00408EBA 2BD8 ) SUB EBX, EAX
( 00408EBC 2BC8 ) SUB ECX, EAX
( 00408EBE 8D6D08 ) LEA EBP, [EBP+08]
( 00408EC1 2BCB ) SUB ECX, EBX
( 00408EC3 1BDB ) SBB EBX, EBX
( 00408EC5 C3 ) NEXT,
( 18 bytes, 8 instructions )
ok

see test2
TEST2
( 004AAF50 83C3D0 ) ADD EBX, -30
( 004AAF53 83FB0A ) CMP EBX, 0A
( 004AAF56 0F92C3 ) SETB/NAE BL
( 004AAF59 F6DB ) NEG BL
( 004AAF5B 0FBEDB ) MOVSX EBX, BL
( 004AAF5E C3 ) NEXT,
( 15 bytes, 6 instructions )
ok



Anton Ertl

unread,
Feb 22, 2012, 4:56:14 AM2/22/12
to
BruceMcF <agi...@netscape.net> writes:
>On Feb 21, 11:46=A0am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
>wrote:
>> However, if the hardware does not have such an unsigned comparison,
>> only a signed comparison, and the Forth system implements U< to just
>> use this signed comparison without provision for dealing with negative
>> numbers, then 9 -1 U< will be false whether -1 is represented in
>> 2s-complement, 1's complement, or sign-magnitude.
>
>why then does a 2s-complement encoding guarantee that it will
>necessarily work?

It doesn't. However, AFAIK all 2s-complement hardware has an unsigned
comparison. For 1s-complement or sign-magnitude hardware, I would
expect that it only has unsigned comparison if it also has unsigned
addition (for 2s-complement there is no difference between signed and
unsigned addition).

Anton Ertl

unread,
Feb 22, 2012, 5:08:58 AM2/22/12
to
"Ed" <nos...@invalid.com> writes:
>I make no apology for comparison technique I used. It's cheap,
>easy, and works. I baulk at the notion of having to support
>non 2's-complement machines at the cost of efficiency or
>complicated compile-time options.

Yes, I think we should standardize 2s-complement machines and the
various properties that they have. If anyone ever does a Forth for a
non-2s-complement machine, it would have some environmental
restrictions.

> Version: 4.02 [build 2438]
> Build date: 14 August 2007

That's pretty old, but 4.40 from December 2009 gives the same results.
Interestingly, it does much better if WITHIN is defined in Forth:

: within over - >r - r> u< ; \ depends on the same properties as test2
: test1 [char] 0 [char] 9 1+ within ;
: test2 [char] 0 - 10 u< ;
see test1
see test2

TEST1
( 080B9D40 6A0A ) PUSH 0A
( 080B9D42 83C3D0 ) ADD EBX, -30
( 080B9D45 5A ) POP EDX
( 080B9D46 3BDA ) CMP EBX, EDX
( 080B9D48 0F92C3 ) SETB/NAE BL
( 080B9D4B F6DB ) NEG BL
( 080B9D4D 0FBEDB ) MOVSX EBX, BL
( 080B9D50 C3 ) NEXT,
( 17 bytes, 8 instructions )

TEST2
( 080B9D70 83C3D0 ) ADD EBX, -30
( 080B9D73 83FB0A ) CMP EBX, 0A
( 080B9D76 0F92C3 ) SETB/NAE BL
( 080B9D79 F6DB ) NEG BL
( 080B9D7B 0FBEDB ) MOVSX EBX, BL
( 080B9D7E C3 ) NEXT,
( 15 bytes, 6 instructions )

VFX is (was?) not perfect at eliminating the return stack traffic, but
otherwise it performs the same optimizations as the human who coded
TEST2. I wonder why the builtin WITHIN is worse.

Andrew Haley

unread,
Feb 22, 2012, 5:28:15 AM2/22/12
to
Ed <nos...@invalid.com> wrote:
> BruceMcF wrote:
>>
>> ... but just using WITHIN is simpler, since then whether the U< works
>> correctly outside its standard domain is not an issue.
>
> Using WITHIN may be "simpler" but it has its costs. See below.
>
> I make no apology for comparison technique I used.

> : test1 [char] 0 [char] 9 1+ within ; ok
> : test2 [char] 0 - 10 u< ; ok

But it's exactly the same operations, written differently.

WITHIN is

over - >r - r> u<

so let's try inlining WITHIN:

: test3 [char] 0 [char] 9 1+ over - >r - r> u< ; ok
see test3
TEST3
( 080B9CC0 6A0A ) PUSH 0A
( 080B9CC2 83C3D0 ) ADD EBX, -30
( 080B9CC5 5A ) POP EDX
( 080B9CC6 3BDA ) CMP EBX, EDX
( 080B9CC8 0F92C3 ) SETB/NAE BL
( 080B9CCB F6DB ) NEG BL
( 080B9CCD 0FBEDB ) MOVSX EBX, BL
( 080B9CD0 C3 ) NEXT,
( 17 bytes, 8 instructions )

Not bad at all. My wild-assed guess is that VFX is seeing R-stack
operations and refusing to inline the WITHIN.

Andrew.

Stephen Pelc

unread,
Feb 22, 2012, 9:59:59 AM2/22/12
to
On Wed, 22 Feb 2012 04:28:15 -0600, Andrew Haley
<andr...@littlepinkcloud.invalid> wrote:

>Not bad at all. My wild-assed guess is that VFX is seeing R-stack
>operations and refusing to inline the WITHIN.

WITHIN is part of the first stage build before any optimisation
tools are compiled. Redefining WITHIN gives good results:

: w1 \ n1|u1 n2|u2 n3|u3 -- flag
over - >r - r> u<
;

: w2 \ n1|u1 n2|u2 n3|u3 -- flag
over - -rot - swap u<
;

: twa \ u -- flag
[char] 0 [char] 9 1+ within
;

: twb \ u -- flag
[char] 0 [char] 9 1+ w2
;

dis twa
TWA
( 004C91C0 8D6DF8 ) LEA EBP, [EBP+-08]
( 004C91C3 C7450030000000 ) MOV DWord Ptr [EBP],
00000030
( 004C91CA 895D04 ) MOV [EBP+04], EBX
( 004C91CD BB3A000000 ) MOV EBX, 0000003A
( 004C91D2 E81DF4F3FF ) CALL 004085F4 WITHIN
( 004C91D7 C3 ) NEXT,
( 24 bytes, 6 instructions )
ok
dis twb
TWB
( 004C9200 83C3D0 ) ADD EBX, -30
( 004C9203 83FB0A ) CMP EBX, 0A
( 004C9206 0F92C3 ) SETB/NAE BL
( 004C9209 F6DB ) NEG BL
( 004C920B 0FBEDB ) MOVSX EBX, BL
( 004C920E C3 ) NEXT,
( 15 bytes, 6 instructions )
ok

In a future release, we'll get rid of another two instructions in TWB.

Stephen

--
Stephen Pelc, steph...@mpeforth.com
MicroProcessor Engineering Ltd - More Real, Less Time
133 Hill Lane, Southampton SO15 5AF, England
tel: +44 (0)23 8063 1441, fax: +44 (0)23 8033 9691
web: http://www.mpeforth.com - free VFX Forth downloads

BruceMcF

unread,
Feb 22, 2012, 10:37:17 AM2/22/12
to
On Feb 22, 4:56 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:
> It doesn't.  However, AFAIK all 2s-complement hardware has an unsigned
> comparison.  For 1s-complement or sign-magnitude hardware, I would
> expect that it only has unsigned comparison if it also has unsigned
> addition (for 2s-complement there is no difference between signed and
> unsigned addition).

There is no difference between signed and unsigned addition with one's
complement machines, either: just like 2's complement, it adds past
max-signed and overflows into the top bit, and the difference between
signed integers and unsigned addresses is the interpretation of that
overflow ~ and I don't see why you wouldn't handle that by return an
overflow flag in the operation just as with 2's complement hardware.

After all, the difference is that the conversion between positive and
negative can be done as a bitwise invert operation with no +1 step,
which in the worst case can propagate a carry across most of the
machine word. If you're only doing it in hardware enroute to a
subtract, you just invert the bits and invert the carry as a borrow
flag and its no difference, and so the scope of applications where
that is a difference that makes a difference would seem to be quite
small.

Subtracting equal negatives gives -0 and subtracting equal positives
gives +0 and so algorithms that assume that all 0 results are
positives need care, but I don't see that going on here.

BruceMcF

unread,
Feb 22, 2012, 10:49:17 AM2/22/12
to
On Feb 21, 8:46 pm, "Ed" <nos...@invalid.com> wrote:
> BruceMcF wrote:
>
> > ... but just using WITHIN is simpler, since then whether the U< works
> > correctly outside its standard domain is not an issue.
>
> Using WITHIN may be "simpler" but it has its costs.
> See below.
...

> : test1  [char] 0 [char] 9 1+ within ;  ok
> : test2  [char] 0 - 10 u< ;  ok

I think the "this is only guaranteed to work with two's complement" is
a phurphee ... after all, its *not* guaranteed with work with 2's
complement, it just does.

That's because of the way that the hardware typically implements
signed and unsigned operations, and there's absolutely no reason to
expect 1's complement to be different on that score just because it
has a -0 where 2's complement has a -1.

If anyone has implemented a Forth on a 1's complement signal processor
in the past twenty years, I'd be interested in hearing about it, but
to implement a Forth an on integer signed magnitude machine that is
not an antique, first someone must build the signed magnitude machine
~ I would expect as an FPGA core, but I have no idea *why* they would
build it.

Andrew Haley

unread,
Feb 22, 2012, 11:30:12 AM2/22/12
to
BruceMcF <agi...@netscape.net> wrote:
> On Feb 22, 4:56?am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
> wrote:
>> It doesn't. ?However, AFAIK all 2s-complement hardware has an unsigned
>> comparison. ?For 1s-complement or sign-magnitude hardware, I would
>> expect that it only has unsigned comparison if it also has unsigned
>> addition (for 2s-complement there is no difference between signed and
>> unsigned addition).
>
> There is no difference between signed and unsigned addition with one's
> complement machines, either: just like 2's complement, it adds past
> max-signed and overflows into the top bit, and the difference between
> signed integers and unsigned addresses is the interpretation of that
> overflow ~ and I don't see why you wouldn't handle that by return an
> overflow flag in the operation just as with 2's complement hardware.

Think about adding -1 and -1:

11111110 + 11111110 -> carry + 111111100

You have an end-around carry that has to be added back to get -2:

111111100 + 1 -> 111111101

Andrew.

Anton Ertl

unread,
Feb 22, 2012, 11:24:32 AM2/22/12
to
BruceMcF <agi...@netscape.net> writes:
>There is no difference between signed and unsigned addition with one's
>complement machines, either: just like 2's complement, it adds past
>max-signed and overflows into the top bit,

Hmm, if I signed-add 11...10 (-1) and 11...10 (-1) on a 1s-complement
machine, I expect the result to be either 11...101 (-2), whereas I
would expect an unsigned add to give 11...100. So I see a difference
between signed and unsigned addition on such a machine.

> and the difference between
>signed integers and unsigned addresses is the interpretation of that
>overflow ~ and I don't see why you wouldn't handle that by return an
>overflow flag in the operation just as with 2's complement hardware.

I don't need to deal with overflow flags to get the same result for
this addition on 2s-complement hardware.

Stephen Pelc

unread,
Feb 22, 2012, 1:05:02 PM2/22/12
to
On Wed, 22 Feb 2012 14:59:59 GMT, steph...@mpeforth.com (Stephen
Pelc) wrote:

>In a future release, we'll get rid of another two instructions in TWB.

As of VFX Forth build 3270:

: twa \ u -- flag
[char] 0 [char] 9 1+ within
;

dis twa
TWA
( 004C9190 83C3D0 ) ADD EBX, -30
( 004C9193 83FB0A ) CMP EBX, 0A
( 004C9196 1BDB ) SBB EBX, EBX
( 004C9198 C3 ) NEXT,
( 9 bytes, 4 instructions )
ok

Elizabeth D. Rather

unread,
Feb 22, 2012, 1:51:05 PM2/22/12
to
On 2/22/12 12:08 AM, Anton Ertl wrote:
> "Ed"<nos...@invalid.com> writes:
>> I make no apology for comparison technique I used. It's cheap,
>> easy, and works. I baulk at the notion of having to support
>> non 2's-complement machines at the cost of efficiency or
>> complicated compile-time options.
>
> Yes, I think we should standardize 2s-complement machines and the
> various properties that they have. If anyone ever does a Forth for a
> non-2s-complement machine, it would have some environmental
> restrictions.

Well, that's one approach, but it's pretty easy to document your code as
dependent on 2's complement arithmetic and not worry about it further.
No one *has* to support non-2's complement arithmetic!

I truly don't understand why everyone is so allergic to declaring
dependencies, as though it were a mark of shame.

Cheers,
Elizabeth

--
==================================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310.999.6784
5959 West Century Blvd. Suite 700
Los Angeles, CA 90045
http://www.forth.com

"Forth-based products and Services for real-time
applications since 1973."
==================================================

Paul Rubin

unread,
Feb 22, 2012, 3:46:53 PM2/22/12
to
BruceMcF <agi...@netscape.net> writes:
> If anyone has implemented a Forth on a 1's complement signal processor
> in the past twenty years, I'd be interested in hearing about it, but
> to implement a Forth an on integer signed magnitude machine that is
> not an antique, first someone must build the signed magnitude machine
> ~ I would expect as an FPGA core, but I have no idea *why* they would
> build it.

Chuck Moore apparently made a chip where (I guess in order to save a few
transistors) it sounds like he had logic high = 1 for some bits in a
word and high=0 for other bits. So to transfer data from a PC to his
chip, instead of having to either send the bits unchanged or xor them
with 0xffff (inverting them all), you had to xor with 0xaaaa (flipping
every other bit). See:

http://www.ultratechnology.com/ahatalk.htm

BruceMcF

unread,
Feb 22, 2012, 5:28:20 PM2/22/12
to
On Feb 22, 1:51 pm, "Elizabeth D. Rather" <erat...@forth.com> wrote:
> Well, that's one approach, but it's pretty easy to document your code as
> dependent on 2's complement arithmetic and not worry about it further.
> No one *has* to support non-2's complement arithmetic!

It's not dependency on two's complement arithmetic in particular, its
a dependency on U< treating all positive integers as less than all
negative integers.

That's *true* for both one's complement and two's complement encodings
of negatives, since for each +0 to max positive then overflows to
largest magnitude negative through to smallest magnitude negative. Now
in 2's complement the smallest magnitude negative is -1 and in 1's
complement its -0, but the dependency is satisfied by either
complementary encoding of negative integers.

As far as Anton's worry that 1's complement hardware will not reflect
that aspect of the 1's complement encoding and that will be reflected
in U< possibly not satisfying the dependency ~ well, equally well so
could some exotic 2's complement FPGA processor core.

As far as it actually ever existing, I'd expect its more likely to
exist in some 2's complement hardware somewhere, because its such an
unlikely occurrence, and when the probability of an individual
occurrence of a mutation is very low, you need a much larger
reproducing population to expect to ever see an instance.

BruceMcF

unread,
Feb 22, 2012, 9:24:04 PM2/22/12
to
On Feb 22, 3:46 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
> BruceMcF <agil...@netscape.net> writes:
>> If anyone has implemented a Forth on a 1's complement signal
>> processor in the past twenty years, I'd be interested in hearing
>> about it, but to implement a Forth an on integer signed magnitude
>> machine that is not an antique, first someone must build the signed
>> magnitude machine ~ I would expect as an FPGA core, but I have no
>> idea *why* they would build it.

> Chuck Moore apparently made a chip where (I guess in order to save a
> few transistors) it sounds like he had logic high = 1 for some bits
> in a word and high=0 for other bits.

Alternating bits, yes. However, that is the physical current levels ~
stack bits and memory bits line up ~ even stack bits got to even
memory bits, odd stack bits got to odd memory bits ~ so its not
difference at code level. As that link noted, its just like connecting
a 1 high system to a 0 high system ~ at the I/O edge, you have to
convert, but each processor works just fine on the data it is
generating and processing itself.

Whether its for gates or speed or stability (at least some of those
chips are clockless) or some combination, but internally, aren't those
are all 2's complement chips? If an advantage of 2's complement is
gate count, after all, wouldn't that tilt Chuck even more strongly
than it tilted the evolution of microprocessors?

Brad

unread,
Feb 23, 2012, 10:44:37 AM2/23/12
to
On Feb 22, 8:37 am, BruceMcF <agil...@netscape.net> wrote:
> After all, the difference is that the conversion between positive and
> negative can be done as a bitwise invert operation with no +1 step,
> which in the worst case can propagate a carry across most of the
> machine word. If you're only doing it in hardware enroute to a
> subtract, you just invert the bits and invert the carry as a borrow
> flag and its no difference, and so the scope of applications where
> that is a difference that makes a difference would seem to be quite
> small.

Since C drives CPU design these days, does C expect 2s complement
hardware? If so, it's a safe dependency to have.

Anton Ertl

unread,
Feb 23, 2012, 8:13:44 AM2/23/12
to
"Elizabeth D. Rather" <era...@forth.com> writes:
>On 2/22/12 12:08 AM, Anton Ertl wrote:
>> Yes, I think we should standardize 2s-complement machines and the
>> various properties that they have. If anyone ever does a Forth for a
>> non-2s-complement machine, it would have some environmental
>> restrictions.
>
>Well, that's one approach, but it's pretty easy to document your code as
>dependent on 2's complement arithmetic and not worry about it further.

Well, that code is not dependent on 2s-complement arithmetic, but on
some properties that Forth systems on 2s-complement machines tend to
have, but others maybe not (and these properties are not guaranteed on
2s-complement machines, either).

>I truly don't understand why everyone is so allergic to declaring
>dependencies, as though it were a mark of shame.

Well, Ed actually did declare a dependency, it just was not the right
dependency. That's one reason for standardizing instead of just
declaring: Standards tend to be more precise than individual
declarations.

Also the standardization question is not about allergies, but about
common practice. And Forth systems on 2s-complement machines, with
properties such as the one that Ed depended on, but did not declare,
are not just common, but universal practice. And Forth programs
relying on such properties are pretty common, too.

In particular, for such universal and widely-used properties, why
should it be a good idea to burden the programmers with the
requirement to declare dependencies on them, in many programs, instead
of just documenting them just once in the standard.

Bernd Paysan

unread,
Feb 23, 2012, 11:54:24 AM2/23/12
to
Brad wrote:
> Since C drives CPU design these days, does C expect 2s complement
> hardware? If so, it's a safe dependency to have.

AFAIK, the C standard does not. But the reality is that most C programs
depend on a bunch of assumptions:

* byte-addressed machines
* 2's complement
* unified address space
* ordered memory access

Well, essentially, x86 is the dominant platform, and what's guaranteed
on x86 is taken for granted. ARM has some slight deviations, especially
on multi-core memory modell. But that doesn't seem to be a major
problem. Most programmer programm for a single plattform, without
portability in mind.

Therefore, we can take the above as "almost for granted", and any
plattform that significantly deviats is obscure and non-mainstream.

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

Anton Ertl

unread,
Feb 23, 2012, 11:51:23 AM2/23/12
to
Brad <hwf...@gmail.com> writes:
>Since C drives CPU design these days, does C expect 2s complement
>hardware?

No. And even on 2s-complement hardware, some C compilers (in
particular, gcc) fail to satisfy properties that are easy to satisfy
on the hardware. Their implementors aspire to implement a
higher-level language, i.e., all the disadvantages of Java without the
advantages; although actually Java defines that it runs on
2s-complement machines, and that it's arithmetic has the usual
properties (which C does not define, and which is the excuse used by
these C implementors).

> If so, it's a safe dependency to have.

It is definitely a safe dependency to have. Nobody has reported a
Forth implementation on a non-2s-complement machine, and such machines
appear to be a thing of the past. And I don't expect Forth
implementors to be as crazy as the gcc people (and if any of this
crazyness infects a Forth implementor, just ignore his system).

Andrew Haley

unread,
Feb 23, 2012, 12:49:07 PM2/23/12
to
Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
> Brad <hwf...@gmail.com> writes:
>>Since C drives CPU design these days, does C expect 2s complement
>>hardware?
>
> No. And even on 2s-complement hardware, some C compilers (in
> particular, gcc) fail to satisfy properties that are easy to satisfy
> on the hardware.

I think I know what you're talking about, i.e. signed overflow being
undefined, and actually they're not at all easy to satisfy if you want
to do comprehensive loop optimization. Also, you can turn those
optimizations off and get all the properties of 2's complement
arithmetic if you want.

Andrew.

Paul Rubin

unread,
Feb 23, 2012, 4:26:37 PM2/23/12
to
Andrew Haley <andr...@littlepinkcloud.invalid> writes:
> I think I know what you're talking about, i.e. signed overflow being
> undefined, and actually they're not at all easy to satisfy if you want
> to do comprehensive loop optimization. Also, you can turn those
> optimizations off and get all the properties of 2's complement
> arithmetic if you want.

I could see a case for adding a pragma to guarantee some behavior of
signed overflow by avoiding certain optimizations, but going in the
opposite direction (expecting compiling with optimization turned off
without a specific pragma or flag) to change the program semantics
doesn't sound like a good idea. That assumes the undefined overflow
behavior is consistent with the standard.

This actually doesn't sound like what Anton is referring to though,
in the comment about aspiring to be a higher-level language.

Andrew Haley

unread,
Feb 23, 2012, 4:58:41 PM2/23/12
to
Paul Rubin <no.e...@nospam.invalid> wrote:
> Andrew Haley <andr...@littlepinkcloud.invalid> writes:
>> I think I know what you're talking about, i.e. signed overflow being
>> undefined, and actually they're not at all easy to satisfy if you want
>> to do comprehensive loop optimization. Also, you can turn those
>> optimizations off and get all the properties of 2's complement
>> arithmetic if you want.
>
> I could see a case for adding a pragma to guarantee some behavior of
> signed overflow by avoiding certain optimizations, but going in the
> opposite direction (expecting compiling with optimization turned off
> without a specific pragma or flag) to change the program semantics
> doesn't sound like a good idea.

That is a rather convoluted sentence, so forgive me if I'm
misinterpreting your meaning, but I think you'll find that the former
is the case. Although the latter is the case too. :-)

> This actually doesn't sound like what Anton is referring to though,
> in the comment about aspiring to be a higher-level language.

Oh, who knows...

Andrew.

BruceMcF

unread,
Feb 23, 2012, 6:02:52 PM2/23/12
to
On Feb 22, 4:56 am, an...@mips.complang.tuwien.ac.at (Anton Ertl)
wrote:
>>why then does a 2s-complement encoding guarantee that it will
>>necessarily work?

> It doesn't.  However, AFAIK all 2s-complement hardware has an
> unsigned comparison.

Ah, reading the borrow flag on a trial subtraction acts as an unsigned
comparison if nothing else is available, and with 1's complement, the
borrow wraps around. Since 1's complement word arithmetic does not
necessarily extend into arbitrary multi-word integers, a borrow flag
is not an intermediate result flag, but rather similar to an overflow
flag, and while one might expect one to be available, given the highly
specialized niches that benefit from one's complement processing,
unless the algorithms its designed for require it, it could well be
omitted.

You threw me with the suggestion that 1's complement arithmetic
requires an different adder for unsigned addition...

Assume an 8bit word:

$7F + $01 =
%0111 1111 + %0000 0001 =
%1000 0000 + %0000 0000 = (no carry)
%1000 0000 = $80

And of course $80+$01=$81 because adding one to max-negative results
in an integer one greater than max-negative.

This makes is clear why signed magnitude is problematic, since the
signed magnitude machines of bygone days did their internal arithmetic
in 1's complement and converted on the fly, inverting in either
direction if the sign bit is set (1's rather than 2's because of that
ease of converting on the fly) ... and that makes a final step:

... Internal(%1 000 000) -> %1 111 1111 - $FF

Ed

unread,
Feb 23, 2012, 9:23:23 PM2/23/12
to
BruceMcF wrote:
> ...
> I think the "this is only guaranteed to work with two's complement" is
> a phurphee ... after all, its *not* guaranteed with work with 2's
> complement, it just does.
> ...

What was actually said was:

"The definition is dependent on 2's complement."

The statement was in a response to a reader who expressed
difficulty comprehending aspects of the code I posted. Since
the algorithm used was "tricky" I felt I owed an explanation.
Other number representations were not considered as I see
them as unlikely targets for any code that I post.



Ed

unread,
Feb 23, 2012, 10:32:31 PM2/23/12
to
Elizabeth D. Rather wrote:
> ...
> I truly don't understand why everyone is so allergic to declaring
> dependencies, as though it were a mark of shame.

It is a mark of shame.

ANS-Forth is God (and Bruce his prophet). Portability is
the holy grail of ANS-Forth. The more portable our code,
the closer we must be to God. Anything less indicates
failure on our part.

What is not portable is sin. Sinning can be corrected with
punishment and flagellation on c.l.f. Bruce whips us until
we are pure and clean - worthy acolytes of the great God
ANS-Forth.

:)



Elizabeth D. Rather

unread,
Feb 24, 2012, 12:53:25 AM2/24/12
to
Ok, have your joke, but I think Bruce is as practical as the next person
when it comes to making a realistic assessment of what practical
portability is needed.

Hugh Aguilar

unread,
Feb 24, 2012, 1:46:23 AM2/24/12
to
On Feb 22, 11:51 am, "Elizabeth D. Rather" <erat...@forth.com> wrote:
> On 2/22/12 12:08 AM, Anton Ertl wrote:
>
> > "Ed"<nos...@invalid.com>  writes:
> >> I make no apology for comparison technique I used.  It's cheap,
> >> easy, and works.  I baulk at the notion of having to support
> >> non 2's-complement machines at the cost of efficiency or
> >> complicated compile-time options.
>
> > Yes, I think we should standardize 2s-complement machines and the
> > various properties that they have.  If anyone ever does a Forth for a
> > non-2s-complement machine, it would have some environmental
> > restrictions.
>
> Well, that's one approach, but it's pretty easy to document your code as
> dependent on 2's complement arithmetic and not worry about it further.
> No one *has* to support non-2's complement arithmetic!
>
> I truly don't understand why everyone is so allergic to declaring
> dependencies, as though it were a mark of shame.
>
> Cheers,
> Elizabeth
>
> --
> ==================================================
> Elizabeth D. Rather   (US & Canada)   800-55-FORTH
> FORTH Inc.                         +1 310.999.6784
> 5959 West Century Blvd. Suite 700
> Los Angeles, CA 90045http://www.forth.com
>
> "Forth-based products and Services for real-time
> applications since 1973."
> ==================================================

This is one case in which I agree with Elizabeth Rather. All of this
talk about ones-complement arithmetic is incredible foolishness. The
needle on the common-senso-meter is not even twitching; you guys are
at a rock-solid zero. AFAIK, nobody has built a ones-complement
processor since the 1960s, and it was widely considered to be a dumb
idea then too. I think that we are pretty safe in ignoring ones-
complement processors in the year 2012.

I have many times said that the problem with ANS-Forth is that it is
trying to be everything to everybody. You heard that somebody
somewhere is using ones-complement, so you supported ones-complement
lest that that person should abandon Forth. As another example, you
have both local variables and >R etc.. You also say that locals "may"
be held on the return stack. Your frequent use of the word "may" is a
red flag indicating that you don't know what you are talking about.
Obviously, there is going to be a conflict here if the return stack is
used for both. The ANS-Forth committee just wanted to please
everybody. Some people were using locals on the return stack, so you
said: "Sure! That is ANS-Forth compliant!" Other people were using >R
etc., so you said: "Sure! That is ANS-Forth compliant!" You just
wanted to please everybody. The fact that these solutions were in
obvious conflict, didn't bother you at all. This reminds me of how
Bill Clinton used to always tailor his speeches to his audience, and
just tell them what they wanted to hear. His speeches would be in
complete contradiction from one day to the next however, because he
would be speaking to different audiences with different agendas. The
ANS-Forth committee is ultra-liberal in the same way that Bill Clinton
is ultra-liberal.

It seems a bit late for Elizabeth Rather to realize that pleasing
everybody everywhere (including the guy living in a cave running a
ones-complement computer) is not a viable plan. ANS-Forth is an
incredible mess because it tries to please everybody everywhere --- it
is self-contradicting --- it is possibly the worst standard ever
designed. Who are we supposed to blame for this other than you?

On Feb 15, 12:48 am, Hans Bezemer <the.beez.spe...@gmail.com> wrote:
> Ed wrote:
> > No-frills code for adding thousands separators to a decimal
> > numeric string.
>
> Hi Ed!
>
> Since I don't use the largely useless NOVICE package, I'd be happy to
> include this code in the next release of 4tH.
>
> Thanks, clean, portable code - it seems like a very nice addition!
>
> Hans

Beez, you are trying to get my goat, but you just make a fool of
yourself.

The guy's code was not clean. He is dismantling one string to make
another string. What??? I just wrote a typical picture-number function
that takes a double and generates a string using # and HOLD and all
that. There was a chapter on this stuff in "Starting Forth" ---
anybody who has read that book should be able to succeed at writing
the BIG. function. It was trivial. Also, he wrote a really long
function that badly needed factoring. This is very novice-level Forth.
If you guys were the experts that you claim to be, you would be
helping him to improve his Forth. Instead the Beez congratulates him
on his "clean" code and says that it qualifies for inclusion in the
4TH compiler, and the whole crowd immediately launches into a
discussion of ones-complement arithmetic. What??? The poor guy is not
going to learn anything about Forth from you guys --- I predict that
he is going to drop Forth pretty soon, just like everybody else who
tries to learn it.

A. K.

unread,
Feb 24, 2012, 2:07:46 AM2/24/12
to
On 24.02.2012 07:46, Hugh Aguilar wrote:
> On Feb 22, 11:51 am, "Elizabeth D. Rather"<erat...@forth.com> wrote:
>> On 2/22/12 12:08 AM, Anton Ertl wrote:
>>
>>> "Ed"<nos...@invalid.com> writes:
>>>> I make no apology for comparison technique I used. It's cheap,
>>>> easy, and works. I baulk at the notion of having to support
>>>> non 2's-complement machines at the cost of efficiency or
>>>> complicated compile-time options.
>>
>>> Yes, I think we should standardize 2s-complement machines and the
>>> various properties that they have. If anyone ever does a Forth for a
>>> non-2s-complement machine, it would have some environmental
>>> restrictions.
>>
>> Well, that's one approach, but it's pretty easy to document your code as
>> dependent on 2's complement arithmetic and not worry about it further.
>> No one *has* to support non-2's complement arithmetic!
>>
>> I truly don't understand why everyone is so allergic to declaring
>> dependencies, as though it were a mark of shame.
>>
>> Cheers,
>> Elizabeth
>>
>> --
>> ==================================================
>> Elizabeth D. Rather (US& Canada) 800-55-FORTH
This was a rather hughly statement.

BruceMcF

unread,
Feb 24, 2012, 8:04:37 AM2/24/12
to
On Feb 23, 10:32 pm, "Ed" <nos...@invalid.com> wrote:
> ANS-Forth is God (and Bruce his prophet).  Portability is
> the holy grail of ANS-Forth.  The more portable our code,
> the closer we must be to God.  Anything less indicates
> failure on our part.

Wow, I had not idea I had that job. I reckon I have been rather
massively falling far short of such an august and important
responsibility. In any event, for this particular case,

{pronouncement tone="sonorous"} Inspired by ANS-Forth, our peculiarly
agent-free God, this code is DEPENDENT upon U< finding all negative
signed values to be greater than all positive signed values. It is
only PORTABLE to systems exhibiting this behavior, believed to be all
systems in existence but not necessarily all conceivable systems, and
SHOULD ONLY BE SO PORTED. So mote it be. {/pronouncement}

Hans Bezemer

unread,
Feb 24, 2012, 9:00:56 AM2/24/12
to
Hugh Aguilar wrote:


> The guy's code was not clean. He is dismantling one string to make
> another string. What??? I just wrote a typical picture-number function
> that takes a double and generates a string using # and HOLD and all
> that.
Oops! No floating point. Oops, another "function". I won't say that there
aren't drawbacks to Ed's word but it's pretty portable Forth and quite
flexible. Given the code size and possible application I think it's pretty
useful.

> Also, he wrote a really long function that badly needed factoring.
Says the man who wrote code like this:

: <big.> ( d -- adr cnt ) \ used for big numbers that need
commas for clarity
2dup d0< to sgn dabs
<#
# ?# ?# ?comma
?# ?# ?# ?comma
?# ?# ?# ?comma
?# ?# ?# ?comma
?# ?# ?# ?comma
?# ?# ?# ?comma
?#
#> ;

And this:

: <6array> { dim1 dim2 dim3 dim4 dim5 dim6 siz1 name | adr siz siz2 siz3
siz4 siz5 siz6 -- }
dim1 siz1 * to siz2 dim2 siz2 * to siz3 dim3 siz3 * to siz4
dim4 siz4 * to siz5 dim5 siz5 * to siz6 dim6 siz6 * to siz
align here to adr siz allot
name get-current :name \ runtime: x1 x2 x3
x4 x5 x6 -- element-adr
dim6 <check6>
siz6 lit*, swap, \ runtime: -- x1 x2
x3 x4 x6*s6 x5
dim5 <check5>
siz5 lit*, +, swap, \ runtime: -- x1 x2
x3 x6*s6+x5*s5 x4
dim4 <check4>
siz4 lit*, +, swap, \ runtime: -- x1 x2
x6*s6+x5*s5+x4*s4 x3
dim3 <check3>
siz3 lit*, +, swap, \ runtime: -- x1
x6*s6+x5*s5+x4*s4+x3*s3 x2
dim2 <check2>
siz2 lit*, +, swap, \ runtime: --
x6*s6+x5*s5+x4*s4+x3*s3+x2*s2 x1
dim1 <check1>
siz1 lit*, +, adr lit+, ;, \ runtime: --
x6*s6+x5*s5+x4*s4+x3*s3+x2*s2+x1*s1
c" ^" name get-current :2name \ runtime: -- adr
adr lit, ;,
c" lim-" name get-current :2name \ runtime: --
adr-past
adr siz + lit, ;,
name c" -zero" get-current :2name \ runtime: --
adr lit, siz lit, s" erase ; " evaluate
name c" -size" get-current :2name \ runtime: -- siz1
siz1 lit, ;,
name c" -dim" get-current :2name \ runtime: -- dim1
dim2 dim3 dim4 dim5 dim6
dim1 lit, dim2 lit, dim3 lit, dim4 lit, dim5 lit, dim6 lit, ;,
;

BTW, in Forth it isn't called a "function", but a "word". Any newbie knows
that. Unless he's been using a massive NOVICE.4TH perhaps.

> What??? The poor guy is not going to learn anything about Forth from you
> guys --- I predict that he is going to drop Forth pretty soon, just like
> everybody else who tries to learn it.
I think Ed has made his track record by providing some nice FP I/O words. I
don't always agree with every construct he uses, but he won't agree on mine
as well. And that's ok. I haven't dropped Forth in 20 years and I'm not
going to do it very soon. Neither is Ed, I guess. And why should he?

I rarely see Forth code I really, really like. Most often because it is
badly factored, uses locals or other C-stuff or is plain TOO LONG. Gee,
most of your code should be single line definitions, few variables and no
locals. Stack should be shallow.

For your entertainment, here is 4tH's version. Note I'm still thinking about
clobbering the NPO when you try to convert a number that already resides in
the NPO. But you'll have to agree, it is better factored:

[UNDEFINED] fs>comma [IF]
[UNDEFINED] is-digit [IF] include lib/istype.4th [THEN]
[UNDEFINED] string/c [IF] include lib/cstring.4th [THEN]

char . value dp-char \ decimal point character
char , value 1000-char \ separator character

: s>comma
0 >r \ setup counter
begin
dup \ end of string?
while
string/c dup is-digit dup \ is it a digit?
r@ 3 /mod 0<> swap 0= and and \ should we add a 1000 separator?
if 1000-char hold then \ if so, add 1000 separator
if r> 1+ >r then hold \ increment counter
repeat r> drop \ drop counter
[DEFINED] 4TH# [IF] drop [THEN] \ 4tH expects a single number
;
\ with a decimal point
: fs>comma ( a1 u1 -- a2 u2 )
<# \ setup number generation
begin \ find decimal point
dup \ end of string?
while
string/c dup hold dp-char = \ decimal point found?
until s>comma \ if not, continue
#>
;
\ without a decimal point
: ds>comma <# s>comma #> ; ( a1 u1 -- a2 u2 )

[DEFINED] 4TH# [IF]
hide s>comma
[THEN]
[THEN]

Hans Bezemer

Elizabeth D. Rather

unread,
Feb 24, 2012, 1:30:26 PM2/24/12
to
Gosh, Bruce, thanks for stepping up to the plate! We'll look forward to
your future pronouncements with enthusiasm!

Elizabeth D. Rather

unread,
Feb 24, 2012, 1:29:06 PM2/24/12
to
On 2/24/12 4:00 AM, Hans Bezemer wrote:
> For your entertainment, here is 4tH's version. Note I'm still thinking about
> clobbering the NPO when you try to convert a number that already resides in
> the NPO. But you'll have to agree, it is better factored:

Nicely factored. But I wish you'd use stack comments with your definitions.

Hans Bezemer

unread,
Feb 24, 2012, 6:11:50 PM2/24/12
to
Elizabeth D. Rather wrote:

> On 2/24/12 4:00 AM, Hans Bezemer wrote:
>> For your entertainment, here is 4tH's version. Note I'm still thinking
>> about clobbering the NPO when you try to convert a number that already
>> resides in the NPO. But you'll have to agree, it is better factored:
>
> Nicely factored. But I wish you'd use stack comments with your
Oops, did I forget one for a private word? Ok, here it is:

s>comma ( 4tH: a1 n1 -- n2)
( ANS: a1 n1 -- d1)

The typing may be a bit off, but that's how it is with a no-type language.

Hans Bezemer

Bernd Paysan

unread,
Feb 25, 2012, 8:25:14 PM2/25/12
to
Andrew Haley wrote:
> I think I know what you're talking about, i.e. signed overflow being
> undefined, and actually they're not at all easy to satisfy if you want
> to do comprehensive loop optimization.

What I remember is that GCC once failed to compile

(u1 + u2) < u1

correctly (which is just a check for carry when adding u1 + u2), because
u1 + u2 will only be < u1 if there is an overflow, and overflow results
are undefined, so it could as well assume that this condition is false
all the time. m(

This idiom is necessary for bignum arithmetics and similar things (even
doubles in Forth need that, that's how we found the bug). As Anton
says, GCC is developed as if C is a high-level language, and this
approach is really silly (startig with an assumptin that is wrong can't
lead to correct results). A good high-level language has managed memory
(i.e. garbage collection), bignums, first class strings (no need to
worry about buffer overflows on simple string operations), and a hell
lot more.

The time where each new version of GCC broke Gforth is fortunately over
(but then, we have added workarounds for everything), and sometimes I
even see improvements again.

Andrew Haley

unread,
Feb 26, 2012, 4:24:26 AM2/26/12
to
Bernd Paysan <bernd....@gmx.de> wrote:
> Andrew Haley wrote:
>> I think I know what you're talking about, i.e. signed overflow being
>> undefined, and actually they're not at all easy to satisfy if you want
>> to do comprehensive loop optimization.
>
> What I remember is that GCC once failed to compile
>
> (u1 + u2) < u1
>
> correctly (which is just a check for carry when adding u1 + u2), because
> u1 + u2 will only be < u1 if there is an overflow, and overflow results
> are undefined, so it could as well assume that this condition is false
> all the time.

I'm pretty sure that this wasn't true, and if it did happen it was a
bug that got fixed. Unsigned arithmetic is always well-defined, and
overflows are computed modulo the word size. Only signed overflow is
undefined, and the simple rule is to use unsigned arithmetic if you
think you might overflow.

> This idiom is necessary for bignum arithmetics and similar things (even
> doubles in Forth need that, that's how we found the bug).

Sure, of course. It must have been a fairly short-lived bug, because
it is well-defined in C, and this would break thousands of things.

> As Anton says, GCC is developed as if C is a high-level language,
> and this approach is really silly (startig with an assumptin that is
> wrong can't lead to correct results).

As opposed to a portable assembler, I take it. This really was the
decision of the technical committee that produced C90 rather than any
compiler writer, and AFAIK all industrial-strength compilers follow
the specification and optimize on that basis, not on the basis of some
ill-defined notion of what a portable assembly language might be.
This is nothing to do with GCC per se,

> A good high-level language has managed memory (i.e. garbage
> collection), bignums, first class strings (no need to worry about
> buffer overflows on simple string operations), and a hell lot more.

Indeed, but C is not one of those either: it's somewhere in between,
which perhaps explains its success!

Andrew.

Anton Ertl

unread,
Feb 26, 2012, 8:40:51 AM2/26/12
to
Andrew Haley <andr...@littlepinkcloud.invalid> writes:
>Bernd Paysan <bernd....@gmx.de> wrote:
>> What I remember is that GCC once failed to compile
>>
>> (u1 + u2) < u1
>>
>> correctly (which is just a check for carry when adding u1 + u2), because
>> u1 + u2 will only be < u1 if there is an overflow, and overflow results
>> are undefined, so it could as well assume that this condition is false
>> all the time.
>
>I'm pretty sure that this wasn't true, and if it did happen it was a
>bug that got fixed. Unsigned arithmetic is always well-defined, and
>overflows are computed modulo the word size. Only signed overflow is
>undefined, and the simple rule is to use unsigned arithmetic if you
>think you might overflow.

I don't remember the idiom above ever failing, and I think I would
have noticed, because this idiom is used in the implementation of D+
on systems with downgraded long longs, and I don't remember such a
bug.

However, I tried to test for MININT efficiently with n-1>n, and gcc
miscompiled this test into false. One might think that one can work
around this misfeature of gcc by forcing an unsigned - and signed >
through casts, but this does not work at least in gcc-2.95 (and maybe
other versions). It does not help that this bug has been fixed in
later versions, because we don't want to restrict ourself to just the
latest version of gcc, especially because later versions tend to
produce much slower code (we try to work around that, but it's hard to
keep up).

>As opposed to a portable assembler, I take it. This really was the
>decision of the technical committee that produced C90 rather than any
>compiler writer

AFAIK the ANSI C TC did not standardize many things because the
implementations varied (no common practice), or because they wanted to
support implementations on a wide range of hardware.

For example, they explicitly wrote that they support 2s-complement,
1's-complement, and sign-magnitude hardware; with that in mind, one
may be able to define common properties of signed integer overflow on
any of these arithmetics, but it's probably too complicated and not
worth the effort, so they didn't. OTOH, for unsigned arithmetic there
is only one representation, and all hardware overflows the same way,
so they standardized that.

Of course, if you have a statement by the C90 committee from the time
that states that they did not standardize these things so that
compilers could "optimize" code, I would be interested in a reference.
However, if that was their intention, I wonder why they standardized,
e.g., unsigned overflow behaviour; after all, not standardizing it
would allow even more "optimizations".

>and AFAIK all industrial-strength compilers follow
>the specification and optimize on that basis, not on the basis of some
>ill-defined notion of what a portable assembly language might be.
>This is nothing to do with GCC per se,

I talked to a guy from Sun's compiler group and he said that their
compiler does not break code like gcc does. I have not verified this
claim, though.

Concerning the claim that the proper behaviour of a C compiler is
ill-defined, it's not: earlier versions of gcc (up to about 2.95, with
a few exceptions like the one above) behaved properly even with -O,
and even recent versions behave mostly properly if you turn of
"optimization". So it's not as if the gcc people don't know how to
compile the code properly, they just prefer to miscompile it (I guess
it gives slightly better results on the SPEC benchmarks).

>Indeed, but C is not one of those either: it's somewhere in between,
>which perhaps explains its success!

It was successful before gcc started miscompiling; it's still
successful, but has lost quite a bit of popularity since then.

A part of why it is still somewhat successful is that those of us who
need a portable assembler have no alternative yet; we work around the
miscompilations that gcc produces, but once we get an alternative, we
will switch. Then the C part of gcc will only be used for legacy
code. Or do you think that there are projects who are looking for a
language that combines the disadvantages of Java with the
disadvantages of a portable assembler without offering the benefits of
either?

Andrew Haley

unread,
Feb 26, 2012, 12:06:00 PM2/26/12
to
Anton Ertl <an...@mips.complang.tuwien.ac.at> wrote:
> Andrew Haley <andr...@littlepinkcloud.invalid> writes:
>
>>As opposed to a portable assembler, I take it. This really was the
>>decision of the technical committee that produced C90 rather than any
>>compiler writer
>
> AFAIK the ANSI C TC did not standardize many things because the
> implementations varied (no common practice), or because they wanted to
> support implementations on a wide range of hardware.

Well, maybe. But they wrote what they wrote.

> For example, they explicitly wrote that they support 2s-complement,
> 1's-complement, and sign-magnitude hardware; with that in mind, one
> may be able to define common properties of signed integer overflow on
> any of these arithmetics, but it's probably too complicated and not
> worth the effort, so they didn't.

Indeed, as even trapping integer overflows are in theory possible.

> OTOH, for unsigned arithmetic there is only one representation, and
> all hardware overflows the same way, so they standardized that.

Right.

> Of course, if you have a statement by the C90 committee from the
> time that states that they did not standardize these things so that
> compilers could "optimize" code, I would be interested in a
> reference.

I think I have seen that, but I can't remember where, and I'd have to
read all of the DRs. If I ever find it, I'll be sure to let you know.

> However, if that was their intention, I wonder why they
> standardized, e.g., unsigned overflow behaviour; after all, not
> standardizing it would allow even more "optimizations".

I think we've got the best of both worlds with the current behaviour:
unsigned arithmetic gives you well-defined properties regardless of
overflow, and signed arithmetic allows more loop optimizations. It's
a compromise, but IMO a good one.

Also, as I have said many, many times, you can have wrapping integer
arithmetic if you really want it, with a compiler switch. It's not
clear what the substance of your complaint is. What more could anyone
do to satisfy you?

>>and AFAIK all industrial-strength compilers follow the specification
>>and optimize on that basis, not on the basis of some ill-defined
>>notion of what a portable assembly language might be. This is
>>nothing to do with GCC per se,
>
> I talked to a guy from Sun's compiler group and he said that their
> compiler does not break code like gcc does. I have not verified this
> claim, though.
>
> Concerning the claim that the proper behaviour of a C compiler is
> ill-defined, it's not: earlier versions of gcc (up to about 2.95, with
> a few exceptions like the one above) behaved properly even with -O,

for some definition of "proper"!

> and even recent versions behave mostly properly if you turn of
> "optimization". So it's not as if the gcc people don't know how to
> compile the code properly, they just prefer to miscompile

hmph.

> it (I guess it gives slightly better results on the SPEC
> benchmarks).

I would expect so, given that SPECint is a reasonably representative
set of C programs.

>>Indeed, but C is not one of those either: it's somewhere in between,
>>which perhaps explains its success!
>
> It was successful before gcc started miscompiling; it's still
> successful, but has lost quite a bit of popularity since then.

LOL! :-)

Do you think C has really lost popularity, though? I know that it's
lost market share as a proportion of the whole, but there are
enormously more programmers.

> A part of why it is still somewhat successful is that those of us
> who need a portable assembler have no alternative yet; we work
> around the miscompilations that gcc produces, but once we get an
> alternative, we will switch. Then the C part of gcc will only be
> used for legacy code.

It'll be used for C code, of course; C isn't just used as a substitute
for a portable assembler.

> Or do you think that there are projects who are looking for a
> language that combines the disadvantages of Java with the
> disadvantages of a portable assembler without offering the benefits
> of either?

No.

But as I said, your argument is not with any C compiler vendor, but
with the C standard. It would be easy to change the standard to make
two's complement overflow well-defined on two's complement machines,
and that behaviour would then be portable to compilers other than GCC.

Andrew.

Hugh Aguilar

unread,
Feb 28, 2012, 2:28:26 AM2/28/12
to
On Feb 24, 7:00 am, Hans Bezemer <the.beez.spe...@gmail.com> wrote:
> Hugh Aguilar wrote:
> > The guy's code was not clean. He is dismantling one string to make
> > another string. What??? I just wrote a typical picture-number function
> > that takes a double and generates a string using # and HOLD and all
> > that.
>
> Oops! No floating point. Oops, another "function". I won't say that there
> aren't drawbacks to Ed's word but it's pretty portable Forth and quite
> flexible. Given the code size and possible application I think it's pretty
> useful.

When working with numeric data, it is best to work with it as a
number. Working with numeric data as a string is cumbersome --- that
is the kind of thing that a Perl programmer would do!

My SCIENTIFIC and ENGINEERING do work with floats. I could have easily
added commas to ENGINEERING (they wouldn't make sense for SCIENTIFIC).
The reason why I didn't was so that these strings I am generating can
be fed back into a Forth interpreter as source-code and/or given to
>FLOAT to be converted back into floats, or even interpreted by
another language other than Forth. All of this work on generating
string representations of floats came about because I wanted the slide-
rule program to generate ascii files of raw data that another program
could input. One guy did write a program that input my raw-data files
and made a slide-rule emulator out of them. I think he wrote his
program in JavaScript and converted my raw-data into SVG, but I don't
know as I never looked at his source-code (I don't have any interest
in slide-rule emulators, as I am only interested in building physical
slide-rules).

Everything in the novice package is portable to any ANS-Forth system
(I've tested Gforth, SwiftForth and Win32Forth).

> > Also, he wrote a really long function that badly needed factoring.
>
> Says the man who wrote code like this:
>
> : <big.> ( d -- adr cnt )
>     2dup d0< to sgn  dabs
>     <#
>      # ?# ?#  ?comma
>     ?# ?# ?#  ?comma
>     ?# ?# ?#  ?comma
>     ?# ?# ?#  ?comma
>     ?# ?# ?#  ?comma
>     ?# ?# ?#  ?comma
>     ?#
>     #> ;

That looks like beautiful well-factored Forth code to me. It is longer
than 7 lines (according to "Thinking Forth," functions should
generally be 7 lines or less), but it follows a simple pattern so it
is quite readable despite its length.

Ask Anton Ertl what he thinks of it --- he is the professor.

> And this:
>
> : <6array> { dim1 dim2 dim3 dim4 dim5 dim6 siz1 name | adr siz siz2 siz3
> siz4 siz5 siz6 -- }
> ...

I have already said many times that some of the code in the novice
package is low-level. The implementation of an array definer is very
low-level --- the important goal with arrays is execution speed ---
rules for readability that apply to high-level code get waived for low-
level code.

Also, all of those meta-definers that use :NAME were originally
written and tested as several ordinary colon words. After I got them
to work, I made them into meta-definers. See WBUF for an example in
which I provided the original testing words in a separate file so the
user could see how this development process is done.

> BTW, in Forth it isn't called a "function", but a "word". Any newbie knows
> that. Unless he's been using a massive NOVICE.4TH perhaps.

I use the word "function" just like everybody else in the programming
world. It was a mistake for Chuck Moore to use "word" to mean a
function, because "word" is more commonly used to mean a single-
precision integer. He most likely did that because in an indirect-
threaded-code system, functions do get compiled as single-precision
integers. That was in the 1970s though --- that is no longer true, and
it is irrelevant to the user what the internal representation is
anyway --- using "word" like that now is just confusing.

> > What??? The poor guy is not going to learn anything about Forth from you
> > guys --- I predict that he is going to drop Forth pretty soon, just like
> > everybody else who tries to learn it.
>
> I think Ed has made his track record by providing some nice FP I/O words. I
> don't always agree with every construct he uses, but he won't agree on mine
> as well. And that's ok. I haven't dropped Forth in 20 years and I'm not
> going to do it very soon. Neither is Ed, I guess. And why should he?

I don't want Ed or anybody else to drop Forth. But I see people show
up on comp.lang.forth filled with enthusiasm for learning Forth, and
then they disappear after a few weeks. It is because you guys don't
offer any support for novices. This thread is a good example of how
you fail to support novices. Talking about ones-complement arithmetic
makes us look like idiots --- that is not helping to convince anybody
to stick with Forth.

I'm not aware of Ed's "track record" providing FP I/O words. In my
novice package I provide GET-FLOAT for input and SCIENTIFIC and
ENGINEERING for output. Did he write something like that?

This kind of stuff is trivial. It is useful, which is why I provided
it in the novice package, but it is pretty basic. There is a lot more
important code in the novice package than this stuff.

I'm not aware of anybody on comp.lang.forth who is in my league. The
only person who is capable of writing something comparable to the
novice package is Anton Ertl, but he spends all of his time dinking
around with Gforth which is just a toy interpreter, and he seems to
have no interest in supporting application programming. You know,
there is a reason why so few applications have been written in Forth
--- it is because the Forth experts aren't providing libraries of code
that would be useful for application programming.

Alex McDonald

unread,
Feb 28, 2012, 4:37:48 AM2/28/12
to
On Feb 28, 7:28 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:

>
> I'm not aware of anybody on comp.lang.forth who is in my league.

There's a truth in that somewhere.

Ron Aaron

unread,
Feb 28, 2012, 8:06:28 AM2/28/12
to
The deepest truths are often stated in simplest terms.

Hugh Aguilar

unread,
Feb 28, 2012, 8:03:40 PM2/28/12
to
On Feb 13, 3:24 am, "Ed" <nos...@invalid.com> wrote:
> No-frills code for adding thousands separators to a decimal
> numeric string.
>
> Assumes your Forth has some way of generating numeric
> strings e.g. (D.) (F.) etc.  If the source string lies in the PNO
> buffer it will need copying elsewhere first.  Customize for
> your locale.  If you can do it in less, let us know.

The problem is that we don't have any standard way of generating
numeric strings e.g. (D.) (F.) etc.. Did you yourself actually write
(D.) and (F.) in ANS-Forth standard code? Or did you just find (D.)
and (F.) provided as part of some particular Forth system? If it is
the latter, then you are effectively being a salesman for that
particular Forth system. The vendors try to trap their users into
writing code that is not ANS-Forth standard but which relies on code
that is not open-source and/or can not be easily written in ANS-Forth.
The user will then not be able to port his program over to another
vendor's Forth system, but will be stuck using that vendor's system.
Both MPE and Forth Inc. rely heavily on this trick for trapping their
customers.

This is a chronic problem with the ANS-Forth standard. The high-level
code such as D. and F. was standardized, but the low-level code such
as (D.) and (F.) was not standardized. This is why I had to write
SCIENTIFIC and ENGINEERING --- to make up for the lack of code to
convert a float into a string. This is despite the fact that F.
obviously does have this code buried inside of it. Stephen Pelc and
Elizabeth Rather are largely denouncing my novice package because I
provide code such as SCIENTIFIC and ENGINEERING written in ANS-Forth
--- I'm messing up their trick for trapping their customers --- and
Anton Ertl goes along with this because he is their stooge.

The similar problem arose in regard to my :NAME definer. Obviously,
colon has this code buried inside of it. Colon first gets the string
out of the input stream, and then it calls something like :NAME to
make a colon word with that string as the name.

The fact that ANS-Forth doesn't standardize the low-level code but
only the high-level code, is a big part of why ANS-Forth is a complete
failure in the programming world. Forth was taken seriously in the
1980s, but it died out in the 1990s. ANS-Forth (released in 1994) was
what killed Forth more than anything else. People could see through
these petty little tricks that Stephen Pelc and Elizabeth Rather were
foisting on the Forth community --- everybody just abandoned Forth
altogether because the ANS-Forth standard was no good --- and
Forth-200x is just more of the same.

Notice in my novice package that I always provide both the low-level
and the high-level code. For example, I have:

: <big.> ( d -- adr cnt )
...

and:

: big. ( d -- )
<big.> type ;


Also, I have:

: <6array> { dim1 dim2 dim3 dim4 dim5 dim6 siz1 name
| adr siz siz2 siz3 siz4 siz5 siz6 -- }
...

and:

: 6array ( dim1 dim2 dim3 dim4 dim5 dim6 size -- )
bl word hstr dup >r <6array> r> dealloc ;

Ed

unread,
Feb 29, 2012, 1:20:50 AM2/29/12
to
Hugh Aguilar wrote:
>
> The guy's code was not clean. He is dismantling one string to make
> another string. What??? I just wrote a typical picture-number function
> that takes a double and generates a string using # and HOLD and all
> that.

Nothing wrong with processing strings. The application was intended
to convert string output from my floating-point package. Were integers
my only consideration the following would have sufficed:

\ Comma formatted numeric output
\ Adapted from code by C.Curley FD15/5

\ like #S but inserts commas after each 3 digits
: #,S ( ud -- 0. )
0 begin >r # 2dup or while
r> 1+ dup 3 = if [char] , hold drop 0 then
repeat r> drop ;

> Also, he wrote a really long
> function that badly needed factoring. This is very novice-level Forth.
> If you guys were the experts that you claim to be, you would be
> helping him to improve his Forth. Instead the Beez congratulates him
> on his "clean" code and says that it qualifies for inclusion in the
> 4TH compiler, and the whole crowd immediately launches into a
> discussion of ones-complement arithmetic. What??? The poor guy is not
> going to learn anything about Forth from you guys --- I predict that
> he is going to drop Forth pretty soon, just like everybody else who
> tries to learn it.

A novice after 25 years! If being a novice means there is still
something I can learn, well that sounds like a good thing. Better
to be a novice than an "expert" who's constantly in fear of being
upstaged. Personally I can't think of anything more exciting than
to discover something which I had believed to be true, turns out
false. The trick is to never hitch one's wagon to anything so
permanently that it destroys one when the time comes to let it go.
For me, Forth is just such a thing.





A. K.

unread,
Feb 29, 2012, 1:51:42 AM2/29/12
to
On 29.02.2012 07:20, Ed wrote:
> The trick is to never hitch one's wagon to anything so
> permanently that it destroys one when the time comes to let it go.
> For me, Forth is just such a thing.

You'll be destroyed by the time anyhow,
even when the time comes
when SWAP isn't SWAP any more.

[Book of MormoF]


Hans Bezemer

unread,
Feb 29, 2012, 3:29:30 AM2/29/12
to
Hugh Aguilar wrote:
> When working with numeric data, it is best to work with it as a
> number. Working with numeric data as a string is cumbersome --- that
> is the kind of thing that a Perl programmer would do!
I'd say it's just an additional formatter that can be added to an already
generated FP or double number. I don't see anything wrong with that. As a
matter of fact, adding an entirely new formatter would duplicate a lot of
code (especially in FP).

> That looks like beautiful well-factored Forth code to me. It is longer
> than 7 lines (according to "Thinking Forth," functions should
> generally be 7 lines or less), but it follows a simple pattern so it
> is quite readable despite its length.
I don't say it's not readable: it just could be factored even more.

> Ask Anton Ertl what he thinks of it --- he is the professor.
I tend to be on Chuck's side a lot of the time. Why? That's a good one..
Lemme think.. Oh yeah, I remember: he invented the language!

> I have already said many times that some of the code in the novice
> package is low-level. The implementation of an array definer is very
> low-level --- the important goal with arrays is execution speed ---
> rules for readability that apply to high-level code get waived for low-
> level code.
I agree that library grade code has to follow slightly different rules than
user programs. Still, this is a monster.

> I use the word "function" just like everybody else in the programming
> world. It was a mistake for Chuck Moore to use "word" to mean a
> function, because "word" is more commonly used to mean a single-
> precision integer. He most likely did that because in an indirect-
> threaded-code system, functions do get compiled as single-precision
> integers. That was in the 1970s though --- that is no longer true, and
> it is irrelevant to the user what the internal representation is
> anyway --- using "word" like that now is just confusing.
You're entitled to an opinion, but everybody still uses the accepted Forth
nomenclature.

> I don't want Ed or anybody else to drop Forth. But I see people show
> up on comp.lang.forth filled with enthusiasm for learning Forth, and
> then they disappear after a few weeks. It is because you guys don't
> offer any support for novices. This thread is a good example of how
> you fail to support novices. Talking about ones-complement arithmetic
> makes us look like idiots --- that is not helping to convince anybody
> to stick with Forth.
There is no separate group for Forth experts, so the discussions can get as
high level as they get. And I think it's required to have such discussions,
even if they go nowhere or just confirm the (sometimes uncomfortable)
status quo.

> I'm not aware of Ed's "track record" providing FP I/O words. In my
> novice package I provide GET-FLOAT for input and SCIENTIFIC and
> ENGINEERING for output. Did he write something like that?
Better. I've worked with Ed on several occasions and I'm more than happy
with his contributions

> This kind of stuff is trivial. It is useful, which is why I provided
> it in the novice package, but it is pretty basic. There is a lot more
> important code in the novice package than this stuff.
Sorry, I don't see it. Wrappers to ALLOCATE, lots of stuff to treat the
stack as an array, lists (is this LISP?), duplicates of Forth200x words,
etc. I've seen most and usually better.

> I'm not aware of anybody on comp.lang.forth who is in my league. The
> only person who is capable of writing something comparable to the
> novice package is Anton Ertl, but he spends all of his time dinking
> around with Gforth which is just a toy interpreter, and he seems to
> have no interest in supporting application programming.
You have a lot of respect for your guru, so much is clear. Where's your
ultimate Forth compiler Hugh?

> You know,
> there is a reason why so few applications have been written in Forth
> --- it is because the Forth experts aren't providing libraries of code
> that would be useful for application programming.
4tH comes with 270+ libraries, totaling 500+ kB of code.

Hans Bezemer

Andrew Haley

unread,
Feb 29, 2012, 4:00:35 AM2/29/12
to
Hans Bezemer <the.bee...@gmail.com> wrote:
> I agree that library grade code has to follow slightly different rules than
> user programs. Still, this is a monster.

How do you make the distinction? This is Forth, where everybody is a
systems programmer; there is no class system, no priesthood that gets
to write library code.

Andrew.

The Beez

unread,
Feb 29, 2012, 6:44:30 AM2/29/12
to
On 29 feb, 10:00, Andrew Haley <andre...@littlepinkcloud.invalid>
wrote:
> How do you make the distinction?  This is Forth, where everybody is a
> systems programmer; there is no class system, no priesthood that gets
> to write library code.
In 4tH it's quite simple to see what is library code: its in the /lib
subdirectory. I cannot speak for others.

Of course, that's kind of oversimplification: library files in 4tH
have some special constructs that makes them suitable for library
files. Note that Chuck also made that distinction, he called them
"files with compiler words" contrary to "application (user) words".

I think it is good factoring when you see some code repetition across
files to upgrade that code to "library files" and include it. On the
other hand Chuck doesn't really believe in "reusuable code", he rather
rewrites the code so that it is better suited for a sopecific
application. I guess I'm much lazier than Chuck ;-)

Hans Bezemer


Andrew Haley

unread,
Feb 29, 2012, 12:19:34 PM2/29/12
to
The Beez <the.bee...@gmail.com> wrote:
> On 29 feb, 10:00, Andrew Haley <andre...@littlepinkcloud.invalid>
> wrote:
>> How do you make the distinction? ?This is Forth, where everybody is a
>> systems programmer; there is no class system, no priesthood that gets
>> to write library code.
> In 4tH it's quite simple to see what is library code: its in the /lib
> subdirectory. I cannot speak for others.
>
> Of course, that's kind of oversimplification: library files in 4tH
> have some special constructs that makes them suitable for library
> files. Note that Chuck also made that distinction, he called them
> "files with compiler words" contrary to "application (user) words".

Ah, okay. I'm perfectly happy with that distinction; after all, it's
easy to determine which files contain compiler words.

> I think it is good factoring when you see some code repetition across
> files to upgrade that code to "library files" and include it.

Fair enough. I just don't think that library code is a different kind
of thing. It's all Forth...

Andrew.

hughag...@yahoo.com

unread,
Mar 1, 2012, 12:26:11 AM3/1/12
to
On Tuesday, February 28, 2012 11:20:50 PM UTC-7, Ed wrote:
> Hugh Aguilar wrote:
> >
> > The guy's code was not clean. He is dismantling one string to make
> > another string. What??? I just wrote a typical picture-number function
> > that takes a double and generates a string using # and HOLD and all
> > that.
>
> Nothing wrong with processing strings.

Processing strings representing numbers is a messy way to process numbers. For one thing, you get into a lot of error-checking to make sure that the string is in the format that you are expecting --- that it is actually a string representing a number and that it was generated by whatever float>string function that you are assuming that it was generated by.

It is very bad design to write a function that depends upon getting input which is the output of specific other functions. That is a DEPENDENCY (a bad thing). What happens if that other function gets modified, and now this function that depends upon it stops working because it is being given bad input?

Especially bad is that you don't tell us what function is generating these strings that you are working with, so we don't know what we are dependent upon. You mentioned (D.) and (F.) but those aren't standard functions, and you are not providing the source-code for them. There are myriad ways that strings representing numbers could be generated --- does your code support cases in which there is no decimal point, for example?

> The application was intended
> to convert string output from my floating-point package. Were integers
> my only consideration the following would have sufficed:
>
> \ Comma formatted numeric output
> \ Adapted from code by C.Curley FD15/5
>
> \ like #S but inserts commas after each 3 digits
> : #,S ( ud -- 0. )
> 0 begin >r # 2dup or while
> r> 1+ dup 3 = if [char] , hold drop 0 then
> repeat r> drop ;

That is pretty good code.

I think that it is a good idea to have a function that works with doubles and another function that works with floats. Remember the "universal processor" cartoon in the "Thinking Forth" book? Avoid writing overly general functions --- "Let the dictionary do the deciding."

> > Also, he wrote a really long
> > function that badly needed factoring. This is very novice-level Forth.
> > If you guys were the experts that you claim to be, you would be
> > helping him to improve his Forth. Instead the Beez congratulates him
> > on his "clean" code and says that it qualifies for inclusion in the
> > 4TH compiler, and the whole crowd immediately launches into a
> > discussion of ones-complement arithmetic. What??? The poor guy is not
> > going to learn anything about Forth from you guys --- I predict that
> > he is going to drop Forth pretty soon, just like everybody else who
> > tries to learn it.
>
> A novice after 25 years! If being a novice means there is still
> something I can learn, well that sounds like a good thing.

Sorry; I didn't know that you had been a Forther for 25 years. I just assumed that you were a novice because your code was badly designed and badly factored, and you were presenting a trivial function all by itself for us to look at and comment on. Try writing something comparable to my novice package to convince us that you are an expert --- a single tiny function doesn't make much of a blip on the radar screen (I've already spent more time on this thread than the amount of time that I spent writing BIG.).

> Better
> to be a novice than an "expert" who's constantly in fear of being
> upstaged. Personally I can't think of anything more exciting than
> to discover something which I had believed to be true, turns out
> false. The trick is to never hitch one's wagon to anything so
> permanently that it destroys one when the time comes to let it go.
> For me, Forth is just such a thing.

All of this inspirational talk is nonsense. The ANS-Forth standard was a complete failure. It should have standardized basic code such as the conversion of floats to strings. It is ridiculous that the Forth application programmers should have to write code like this ourselves (especially in the year 2012).

Writing a program that generates an ascii file containing numeric data seems like a pretty common and mundane job. In any other language it would be easy. In AMS-Forth, the programmer is required to write his own function to convert a float into a string. Writing a program in ANS-Forth is somewhat like building a cabin using only an axe, just like the pioneers did in the 1800s. You know, this might be the reason why ANS-Forth did not become popular for application programming --- do you think?

But hey --- it is only 2012, so it is not too late for us to finally write some code to convert floats into strings (actually I wrote SCIENTIFIC and ENGINEERING in 2010, but nobody noticed so we are still dinking around with this stuff in 2012).

hughag...@yahoo.com

unread,
Mar 1, 2012, 1:48:11 AM3/1/12
to
On Wednesday, February 29, 2012 1:29:30 AM UTC-7, The Beez wrote:
> Hugh Aguilar wrote:
> > When working with numeric data, it is best to work with it as a
> > number. Working with numeric data as a string is cumbersome --- that
> > is the kind of thing that a Perl programmer would do!
> I'd say it's just an additional formatter that can be added to an already
> generated FP or double number. I don't see anything wrong with that. As a
> matter of fact, adding an entirely new formatter would duplicate a lot of
> code (especially in FP).

Of course anybody who writes a function to convert a float into a string is duplicating code --- F. certainly has this code buried inside of it --- the problem is that we can't get access to that buried code.

> > That looks like beautiful well-factored Forth code to me. It is longer
> > than 7 lines (according to "Thinking Forth," functions should
> > generally be 7 lines or less), but it follows a simple pattern so it
> > is quite readable despite its length.
> I don't say it's not readable: it just could be factored even more.
>
> > Ask Anton Ertl what he thinks of it --- he is the professor.
> I tend to be on Chuck's side a lot of the time. Why? That's a good one..
> Lemme think.. Oh yeah, I remember: he invented the language!

You're just name-dropping. I doubt that you have ever met Chuck Moore. I haven't.

You are not the only person that name-drops Chuck Moore's name --- Elizabeth Rather endlessly brags about the fact that she knew Chuck Moore in the 1970s, and plasters this all over the Forth Inc. website --- strangely enough though, Chuck Moore doesn't brag about the fact that he knew her.

Similarly, lot of people (including myself) invoke Chuck Moore's name on comp.lang.forth, but Chuck Moore hasn't visited comp.lang.forth in many years --- apparently because he thinks that c.l.f. is a big waste of time, and that there is nothing to be learned on c.l.f. (I would give him credit for being perceptive!).

> > I have already said many times that some of the code in the novice
> > package is low-level. The implementation of an array definer is very
> > low-level --- the important goal with arrays is execution speed ---
> > rules for readability that apply to high-level code get waived for low-
> > level code.
> I agree that library grade code has to follow slightly different rules than
> user programs. Still, this is a monster.

Most likely you don't understand how <6ARRAY> works, but have just noticed its length. It is actually generating several colon words using :NAME --- those are distinct functions, each of which is fairly short --- it is not a monolithic function.

> > I don't want Ed or anybody else to drop Forth. But I see people show
> > up on comp.lang.forth filled with enthusiasm for learning Forth, and
> > then they disappear after a few weeks. It is because you guys don't
> > offer any support for novices. This thread is a good example of how
> > you fail to support novices. Talking about ones-complement arithmetic
> > makes us look like idiots --- that is not helping to convince anybody
> > to stick with Forth.
> There is no separate group for Forth experts, so the discussions can get as
> high level as they get. And I think it's required to have such discussions,
> even if they go nowhere or just confirm the (sometimes uncomfortable)
> status quo.

A discussion of ones-complement arithmetic is neither low-level nor high-level --- it is just dumb.

Besides that, doesn't everybody claim to be a Forth expert? Almost every time that I have mentioned that I am a Forth programmer (such as in a job interview), the person that I was talking to has informed me that he is a Forth expert. This claim is almost always based on the fact that he once implemented a Forth interpreter in C (or Perl for Passaniti). He expects me to be highly impressed, assuming that I am a mere application programmer and believe that compiler-writers are demi-gods. Invariably, in the next breath the self-proclaimed expert will tell me that Forth is too inefficient and too lacking in basic features to be used for application programming, but that implementing a Forth interpreter in C is a mildly fun C project.

> > This kind of stuff is trivial. It is useful, which is why I provided
> > it in the novice package, but it is pretty basic. There is a lot more
> > important code in the novice package than this stuff.
> Sorry, I don't see it. Wrappers to ALLOCATE, lots of stuff to treat the
> stack as an array, lists (is this LISP?), duplicates of Forth200x words,
> etc. I've seen most and usually better.

Those wrappers for ALLOCATE are extremely useful, because they allow ALLOCATION to work (which I tried to get into Forth-200x to no avail). This is useful for cloning data-structures when the nodes are of various types and of various sizes. Also, I have compatibility between heap and dictionary allocation, so I can have data structures that contain some nodes in the heap and some in the dictionary. If I deallocate a node that is in the dictionary, it doesn't crash the computer (nothing happens). This allows me to shift some processing over to compile-time (putting the data-structure in the dictionary) that had previously been done at run-time (putting the data-structure in the heap), without having to modify the code that works with those data-structures. Go over that stuff again --- you might learn something. Read the file (http://www.forth.org/novice.pdf) for a discussion of what this stuff does.

Your other comments were just nonsense. For example, saying that I have "lots of stuff to treat the stack as an array" isn't true. I have THIRD and all that, but those are just a handful of functions. I only use them when speed is an issue, but otherwise I use local variables. And what is wrong with lists? I was impressed by how Factor used "sequences" as its primary data-structure. My lists are my answer to Factor's sequences. Every language needs some kind of data-structure to use primarily (lists for Lisp, tables for Lua, sequences for Factor, etc.).

> > I'm not aware of anybody on comp.lang.forth who is in my league. The
> > only person who is capable of writing something comparable to the
> > novice package is Anton Ertl, but he spends all of his time dinking
> > around with Gforth which is just a toy interpreter, and he seems to
> > have no interest in supporting application programming.
> You have a lot of respect for your guru, so much is clear. Where's your
> ultimate Forth compiler Hugh?

I think Anton Ertl is a good Forth programmer. I also think that he has allowed himself to become a stooge of Forth Inc. and MPE. For example, he standardized BUFFER: in Forth-200x because both SwiftForth and VFX have it. That is ridiculous! He is dinking around with Gforth only because it is slower than SwiftForth and hence doesn't represent a threat to Forth Inc. --- he should be writing a library comparable to my novice package in order to support application programming --- he is supposed to be a teacher, and a library of code is the best way to teach students how to write applications.

I have abandoned ANS-Forth and Forth-200x. I'm writing my own Forth, which I will call Straight Forth (my slogan will be: "Don't be gay --- program Straight"). It is coming --- there is a lot of work involved in writing a compiler (I should know, as I've done it professionally once before).

Maybe I will just forget about Forth altogether. Imagine what a happy day that would be for Elizabeth Rather --- she would be dancing in the streets! Nobody in the real world cares about Forth. People graduate from college as computer programmers without ever hearing of Forth (when I have said that I'm a Forth programmer, the most common response is for people to think that I'm mispronouncing "Fortran"). Forth is a complete failure --- it is a waste of time. I'm one of a tiny handful of people who have worked professionally as a Forth programmer --- when I quit Testra in the late 1990s, I may have been the last of the Mohicans --- the last professional Forther on the planet (I don't consider Elizabeth Rather to be a programmer, so she doesn't count).

> > You know,
> > there is a reason why so few applications have been written in Forth
> > --- it is because the Forth experts aren't providing libraries of code
> > that would be useful for application programming.
> 4tH comes with 270+ libraries, totaling 500+ kB of code.
>
> Hans Bezemer

I'm somewhat interested in your 4TH. Is it ANS-Forth compliant? Does it generate machine-code, or is it just a threaded system?

Hans Bezemer

unread,
Mar 1, 2012, 2:38:16 AM3/1/12
to
hughag...@yahoo.com wrote:

> On Wednesday, February 29, 2012 1:29:30 AM UTC-7, The Beez wrote:
>> Hugh Aguilar wrote:
> You're just name-dropping. I doubt that you have ever met Chuck Moore. I
> haven't.
No, I never met Chuck, but I've read just about anything he wrote on Forth.
It highly influenced my own compiler. I don't have to shake hands with a
person and say "pleased to meet you" to know what he's saying. We invented
writing a few thousand years ago for that.

> Similarly, lot of people (including myself) invoke Chuck Moore's name on
> comp.lang.forth, but Chuck Moore hasn't visited comp.lang.forth in many
> years --- apparently because he thinks that c.l.f. is a big waste of time,
> and that there is nothing to be learned on c.l.f. (I would give him credit
> for being perceptive!).
Chuck moved on - and I agree with him on that, yes. I think modern Forth is
a travesty of what it should be. Maybe not for the same reasons you have,
but still.

> Most likely you don't understand how <6ARRAY> works, but have just noticed
> its length. It is actually generating several colon words using :NAME ---
> those are distinct functions, each of which is fairly short --- it is not
> a monolithic function.
Given the length I still doubt whether it's a good concept or a good design.

> Besides that, doesn't everybody claim to be a Forth expert? Almost every
> time that I have mentioned that I am a Forth programmer (such as in a job
> interview), the person that I was talking to has informed me that he is a
> Forth expert. This claim is almost always based on the fact that he once
> implemented a Forth interpreter in C (or Perl for Passaniti). He expects
> me to be highly impressed, assuming that I am a mere application
> programmer and believe that compiler-writers are demi-gods. Invariably, in
> the next breath the self-proclaimed expert will tell me that Forth is too
> inefficient and too lacking in basic features to be used for application
> programming, but that implementing a Forth interpreter in C is a mildly
> fun C project.
Like I've said all my life: gimme your criteria and I'll tell you what I am.
If I agree with your criteria I agree with you what I am. Very much fun in
a bar, when a guy calls you a $%&^@# and goes nuclear when you pose him
that question. ;-)

> Those wrappers for ALLOCATE are extremely useful, because they allow
> ALLOCATION to work (which I tried to get into Forth-200x to no avail).
> This is useful for cloning data-structures when the nodes are of various
> types and of various sizes. Also, I have compatibility between heap and
> dictionary allocation, so I can have data structures that contain some
> nodes in the heap and some in the dictionary. If I deallocate a node that
> is in the dictionary, it doesn't crash the computer (nothing happens).
> This allows me to shift some processing over to compile-time (putting the
> data-structure in the dictionary) that had previously been done at
> run-time (putting the data-structure in the heap), without having to
> modify the code that works with those data-structures. Go over that stuff
> again --- you might learn something. Read the file
> (http://www.forth.org/novice.pdf) for a discussion of what this stuff
> does.
I wrote my own wordset. ALLOCATION is called ALLOCATES there. My style of
programming doesn't find much use for it. You knew it when you defined it
and now you forgot? Cute, just like istype() with OO.

> Your other comments were just nonsense. For example, saying that I have
> "lots of stuff to treat the stack as an array" isn't true. I have THIRD
> and all that, but those are just a handful of functions.
You got up to the fifth level and that's just BAD!

> I think Anton Ertl is a good Forth programmer. He is dinking around with
> Gforth only because it is slower than SwiftForth and hence doesn't
> represent a threat to Forth Inc. --- he should be writing a library
> comparable to my novice package in
> order to support application programming --- he is supposed to be a
> teacher, and a library of code is the best way to teach students how to
> write applications.
Speed is only one quality of a compiler/interpreter. There are others.

> I have abandoned ANS-Forth and Forth-200x. I'm writing my own Forth, which
> I will call Straight Forth (my slogan will be: "Don't be gay --- program
> Straight"). It is coming --- there is a lot of work involved in writing a
> compiler (I should know, as I've done it professionally once before).
Just do it! I've always said that the quality of Forth is that it can emerge
in so many concepts. And even I hate Forth200x / ANS a lot, it offers the
possibility to exchange code. E.g. I tried to port my stackoptimizer to ANS
and in minutes it ran. I pinched DSQRT from NOVICE.4TH (yes, BSD licence +
proper credits) and it ran. Good thing!

> Maybe I will just forget about Forth altogether. Imagine what a happy day
> that would be for Elizabeth Rather --- she would be dancing in the
> streets!
I think you overestimate the emotions concerning your person. Although you
tend to irritate, I must admit, but that's how it is with nerds ;-)

> Nobody in the real world cares about Forth. People graduate from
> college as computer programmers without ever hearing of Forth (when I have
> said that I'm a Forth programmer, the most common response is for people
> to think that I'm mispronouncing "Fortran").
All too true. Still, I have used Forth in the real world (and still use it)
and tend to outperform most common languages.

> I'm somewhat interested in your 4TH. Is it ANS-Forth compliant? Does it
> generate machine-code, or is it just a threaded system?
Neither. It's a bytecode compiler - and a real one for that. It doesn't
feature a dictionary, but uses a symboltable. It's even got a preprocessor.
See: http://code.google.com/p/4th/wiki/Short4tHreview

Hans Bezemer

Hugh Aguilar

unread,
Mar 1, 2012, 3:57:50 AM3/1/12
to
On Mar 1, 12:38 am, Hans Bezemer <the.beez.spe...@gmail.com> wrote:
> hughaguila...@yahoo.com wrote:
> > Most likely you don't understand how <6ARRAY> works, but have just noticed
> > its length. It is actually generating several colon words using :NAME ---
> > those are distinct functions, each of which is fairly short --- it is not
> > a monolithic function.
>
> Given the length I still doubt whether it's a good concept or a good design.

It is just multiplication --- I didn't invent arrays --- they have
been around for many decades.

If you don't like multiplication, try ARY instead --- it uses arrays
of pointers to effect multiple dimensions.

> > Those wrappers for ALLOCATE are extremely useful, because they allow
> > ALLOCATION to work (which I tried to get into Forth-200x to no avail).
> > This is useful for cloning data-structures when the nodes are of various
> > types and of various sizes. Also, I have compatibility between heap and
> > dictionary allocation, so I can have data structures that contain some
> > nodes in the heap and some in the dictionary. If I deallocate a node that
> > is in the dictionary, it doesn't crash the computer (nothing happens).
> > This allows me to shift some processing over to compile-time (putting the
> > data-structure in the dictionary) that had previously been done at
> > run-time (putting the data-structure in the heap), without having to
> > modify the code that works with those data-structures. Go over that stuff
> > again --- you might learn something. Read the file
> > (http://www.forth.org/novice.pdf) for a discussion of what this stuff
> > does.
>
> I wrote my own wordset. ALLOCATION is called ALLOCATES there. My style of
> programming doesn't find much use for it. You knew it when you defined it
> and now you forgot? Cute, just like istype() with OO.

I often have types derived from other types. The data-structure
contains a mixture of parent and child type nodes. Also, I use lists
for almost everything.

ALLOCATION is a half-step toward istype; all it provides is the size.
If all the nodes in the data-structure are derived from each other
however, then it is impossible for any of them to have the same size,
so obtaining the size is just as good as obtaining the type. Mostly
ALLOCATION is used for cloning a data-structure. See CLONE-LIST in
LIST.4TH. In the slide-rule program, a lot of the scales are just
slightly modified clones of each other (DI and DF are modified
versions of D, for example).

What I have is not as powerful as OOP, but it is extremely fast
executing. I don't have any of the housekeeping that is normally
involved in OOP (especially polymorphism), but I have inheritance
which is the important aspect of OOP. In my experience, most programs
don't need polymorphism or any of that other stuff --- what I provide
is adequate for even large programs. If I had had this when I wrote my
dxf-to-gcode program at Testra, it would have been much simpler ---
and it would have still been just as fast.

> > I have abandoned ANS-Forth and Forth-200x. I'm writing my own Forth, which
> > I will call Straight Forth (my slogan will be: "Don't be gay --- program
> > Straight"). It is coming --- there is a lot of work involved in writing a
> > compiler (I should know, as I've done it professionally once before).
>
> Just do it! I've always said that the quality of Forth is that it can emerge
> in so many concepts. And even I hate Forth200x / ANS a lot, it offers the
> possibility to exchange code. E.g. I tried to port my stackoptimizer to ANS
> and in minutes it ran. I pinched DSQRT from NOVICE.4TH (yes, BSD licence +
> proper credits) and it ran. Good thing!

Other than Mark Willis' ongoing encouragement, that is the first
encouragement I've heard. Thanks!

I don't mind if people borrow from the novice package --- that is why
I made it BSD license. DSQRT is a rather trivial function though ---
there is a lot better stuff in there than that. Steal big!

> > Nobody in the real world cares about Forth. People graduate from
> > college as computer programmers without ever hearing of Forth (when I have
> > said that I'm a Forth programmer, the most common response is for people
> > to think that I'm mispronouncing "Fortran").
>
> All too true. Still, I have used Forth in the real world (and still use it)
> and tend to outperform most common languages.

Has anybody ever written an application program in 4TH that was used
in the real world? By the "real world" I mean everything that exists
beyond the edges of your desk.

> > I'm somewhat interested in your 4TH. Is it ANS-Forth compliant? Does it
> > generate machine-code, or is it just a threaded system?
>
> Neither. It's a bytecode compiler - and a real one for that. It doesn't
> feature a dictionary, but uses a symboltable. It's even got a preprocessor.
> See:http://code.google.com/p/4th/wiki/Short4tHreview

It looks like you need to learn how to write a cross-compiler. You
shouldn't have different names for host and targ words --- such as
your [*] and * words --- the cross-compiler should be smart enough to
know that a word used in interpretive mode is host and a word used
inside of a colon definition is targ.

What you have got reminds me a lot of my first cross-compiler (for the
65c02). I used different names like that. Later on when I wrote MFX at
Testra for the MiniForth however, I figured out how to do it
correctly. I remember that I was totally baffled by the concept of
cross-compilation. Just putting the host and targ words in separate
vocabularies isn't enough. I went on long bicycle rides to clear my
head. One evening while riding near Papago Park I suddenly had a
revelation --- I knew the trick for writing a cross-compiler! ---
after that everything was easy.

Don't worry though --- you aren't the only person who doesn't know how
to write a cross-compiler. Stephen Pelc has publicly stated that a
cross-compiler needs to simulate the target processor at compile-time.
Really! He said that! If he would just ask me how to write a cross-
compiler, I would tell him --- but he hasn't asked --- so he still
doesn't know. I've never met anybody who knew.

BTW, do you know about STAAPL? It similar to what you've got, except
that its preprocessor code is written in Scheme. That is not much
different from using [*] for multiplication --- a different syntax for
host code!

Hans Bezemer

unread,
Mar 1, 2012, 12:23:39 PM3/1/12
to
Hugh Aguilar wrote:
> It is just multiplication --- I didn't invent arrays --- they have
> been around for many decades.
We're talking a novice package with 6(!!) dimensional arrays. I don't think
newbies need 6-dimensional arrays. If you're fluent in Forth, you should be
able to write your own 6-dimensional addressing word.

> Other than Mark Willis' ongoing encouragement, that is the first
> encouragement I've heard. Thanks!
I don't use StrongForth myself, but I think it is a welcome addition to the
family. Like yours: it sounds like an interesting concept. Just go for it,
man!

> I don't mind if people borrow from the novice package --- that is why
> I made it BSD license. DSQRT is a rather trivial function though ---
> there is a lot better stuff in there than that. Steal big!
I'm not done with NOVICE.4TH yet.. ;-)

> Has anybody ever written an application program in 4TH that was used
> in the real world? By the "real world" I mean everything that exists
> beyond the edges of your desk.
Man, I don't know what my users are up to. Most stuff they send me are quite
useful, quite elaborate libraries

> It looks like you need to learn how to write a cross-compiler. You
> shouldn't have different names for host and targ words --- such as
> your [*] and * words --- the cross-compiler should be smart enough to
> know that a word used in interpretive mode is host and a word used
> inside of a colon definition is targ.
I'm not sure about that. 4tH has a Harvard architecture, that's why it
shares some resemblance with a cross compiler. You can't add [*] anywhere,
just when two literals have to be multiplied at compiletime (since you
don't know the contents of the variables or stack values yet). 4tH has a
tiny peephole optimizer that optimizes instructions like "4 +", which it
transforms into "self adding constants". However, if you would probe
DEEPER, you could recognize expressions like "2 4 +" and make 4tH do it for
you. However, that would have several implications and break lots of code.
So for the time being, I left it that way, which means you have to write "2
4 [+]".

> Don't worry though --- you aren't the only person who doesn't know how
> to write a cross-compiler.
When I designed 4tH I didn't know a bit about writing compilers or
interpreters. Later I found out about parsers, tokenizers, virtual
machines, token-threading, etc. Good for me, because otherwise I don't
think the design would have been the same. Sometimes you know just a little
too much to do it right.

> BTW, do you know about STAAPL? It similar to what you've got, except
> that its preprocessor code is written in Scheme. That is not much
> different from using [*] for multiplication --- a different syntax for
> host code!
Well, STAAPL has a different basic architecture than 4tH. My preprocessor is
a very conventional one, simply a programmable "rewriter" (like CPP, M4).
And the resulting code is not stored in a dictionary, but a bytecode image.
But sure, there are similarities.

Hans Bezemer

WJ

unread,
Mar 1, 2012, 1:13:27 PM3/1/12
to
Ed wrote:

> No-frills code for adding thousands separators to a decimal
> numeric string.
>
> Assumes your Forth has some way of generating numeric
> strings e.g. (D.) (F.) etc. If the source string lies in the PNO
> buffer it will need copying elsewhere first. Customize for
> your locale. If you can do it in less, let us know.
>
> --
>
> \ COMMAS.F
> \
> \ Add thousands separator to a decimal numeric string
> \
> \ version: 2012-02-13
> \
> \ - decimal input string must include a decimal point
> \ - output string resides in the Forth pictured numeric
> \ output buffer
> \
> \ This code is PUBLIC DOMAIN. Use at your own risk.
>
> \ Extract character from end of string
> : STRING/C ( a u -- a u-1 char )
> 1- 2dup chars + c@ ;
>
> variable cnt
>
> : COMMA$ ( a1 u1 -- a2 u2 )
> <#
> begin dup while
> string/c dup hold [char] . =
> until then
> cnt off
> begin dup while
> string/c
> dup [char] 0 - 10 u< cnt @ 3 = and
> if [char] , hold cnt off then
> hold 1 cnt +!
> repeat
> #> ;
>
> [defined] DXFORTH [if] behead cnt cnt [then]
>
>
> 1 [if]
> cr .( testing )
> s" " comma$ cr type
> s" -123." comma$ cr type
> s" -1234.E-1000" comma$ cr type
> s" -123456789.4500" comma$ cr type
> s" +100000000.0000" comma$ cr type
> s" $10000000" comma$ cr type
> s" -INFINITY" comma$ cr type
> s" NANS(32767)" comma$ cr type
> s" !#$%'()*+-." comma$ cr type
> [then]

Doesn't work.

s" 23456" comma$ cr type
23456 ok

WJ

unread,
Mar 1, 2012, 1:52:13 PM3/1/12
to
def commafy( str )
pre, num, post = str.match( /^([-+ ]*)(\d*)(.*)$/ ).captures
pre +
num.reverse.gsub( /...(?=.)/, '\&,' ).reverse +
post
end

%w( 123 12345 123456 1234567 1.2345 1234.1234 +1234567.1234
-123 -12345 -1234567 -1234.1234
.1234 ).each{|str| puts commafy( str ) }


=== output ===
123
12,345
123,456
1,234,567
1.2345
1,234.1234
+1,234,567.1234
-123
-12,345
-1,234,567
-1,234.1234
.1234

Alex McDonald

unread,
Mar 1, 2012, 3:46:59 PM3/1/12
to
RTFM.

John Passaniti

unread,
Mar 1, 2012, 8:22:54 PM3/1/12
to
Responding to this specific point:

On Mar 1, 3:57 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> What I have is not as powerful as OOP, but it is extremely
> fast executing. I don't have any of the housekeeping that
> is normally involved in OOP (especially polymorphism), but
> I have inheritance which is the important aspect of OOP. In
> my experience, most programs don't need polymorphism or any
> of that other stuff --- what I provide is adequate for even
> large programs. [...]

Back in the early 80's, most people will remember when OOP started to
go mainstream. C++ wasn't the first object-oriented language and
certainly wasn't the best, but for many it was the first practical
one. Regardless, for those who remember those days, you'll also
remember that they were inheritance happy. Every major class library
from that time took on the Smalltalk model of having a single mother
object that everything descended from. And why not? After all, it
worked well in Smalltalk, so why wouldn't it work well for C++?

A few years pass and people start to understand that inheritance is a
pretty blunt tool. For starters, you don't always want to inherit
*everything* in a base class. So you often had to do things like
create completely artificial classes that didn't represent anything
useful, but served only to serve as a base for when you didn't want to
include something. That sometimes led to goofy class hierarchies that
didn't feel natural. You could sometimes solve these problems with
multiple inheritance, but that brings it's own set of problems.

So what happened in C++ (and what has happened in a bunch of other
class-based object-oriented languages) is that inheritance isn't as
much a big deal as it once was. Obviously it solves some problems
very well and serves as a way to factor out both code and data
nicely. But it can lead to force-fitting a problem into an unnatural
class hierarchy. Far more often, other techniques like traits,
interfaces, delegates, are becoming more popular, because they are
finer-grained than inheritance.

As far as polymorphism, if you aren't using polymorphism much, then
you probably aren't doing OOP, or at least you aren't using it
effectively. The primary value of polymorphism is to treat members of
some hierarchy in a consistent way. So if as you say you are using
inheritance but aren't using polymorphism, then that suggests that
your use of inheritance is mostly limited to extending data
structures. That's a pretty low-level use of OOP, but hey, I know a C+
+ programmer who thinks he's doing OOP because instead of "struct"
he's using "class".

For most everyone else, polymorphism is perhaps the key feature of OOP
that people value. It's the feature that makes inheritance useful
beyond just simple aggregation of data. It's the feature that lets
you treat subtypes consistently and without having to resort to
control structures that dispatch based on type. It's pretty
fundamental. I can easily imagine object oriented programming without
(strict) encapsulation and without inheritance. I can't imagine
object-oriented programming without polymorphism in some form. If you
can, I'd really enjoy hearing how you define object-oriented because
it's completely outside any definition I'm aware of.

Paul Rubin

unread,
Mar 1, 2012, 9:00:41 PM3/1/12
to
John Passaniti <john.pa...@gmail.com> writes:
> I'd really enjoy hearing how you define object-oriented because
> it's completely outside any definition I'm aware of.

http://en.wikipedia.org/wiki/Object-oriented_programming#Criticism

has some nice descriptions too ;-).

Hugh Aguilar

unread,
Mar 2, 2012, 1:14:04 AM3/2/12
to
On Mar 1, 7:00 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
The primary feature of my Straight Forth that I am writing, will be
closures. For the most part, I am getting rid of all of the cruft in
ANS-Forth (DO loops, etc.). The primary new thing that I am adding is
closures.

I will not provide OOP beyond the level that I provided already in my
novice package. ALLOCATION will be standardized, but that is all.

John Passaniti

unread,
Mar 2, 2012, 8:53:59 AM3/2/12
to
On Mar 1, 9:00 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
I'm not sure what your point is. I'm not promoting or defending OOP.
I'm questioning Hugh's statement about polymorphism in OOP.

John Passaniti

unread,
Mar 2, 2012, 9:58:21 AM3/2/12
to
On Mar 2, 1:14 am, Hugh Aguilar <hughaguila...@yahoo.com> wrote:
> The primary feature of my Straight Forth that I am writing,
> will be closures. For the most part, I am getting rid of
> all of the cruft in ANS-Forth (DO loops, etc.). The primary
> new thing that I am adding is closures.

I hope you aren't confusing closures with anonymous functions. I'd
enjoy seeing the most common and useful form of closures (lexically
scoped, can be passed as first-class data, and existing with an
lifetime independent from their creation) in a Forth. Anything less
is likely going to be painful to use.

> I will not provide OOP beyond the level that I provided
> already in my novice package. ALLOCATION will be
> standardized, but that is all.

If you implement closures well, they can be used to create a different
form of objects.

Paul Rubin

unread,
Mar 2, 2012, 2:07:49 PM3/2/12
to
John Passaniti <john.pa...@gmail.com> writes:
> I hope you aren't confusing closures with anonymous functions. I'd
> enjoy seeing the most common and useful form of closures (lexically
> scoped, can be passed as first-class data, and existing with an
> lifetime independent from their creation) in a Forth. Anything less
> is likely going to be painful to use.

Having lexical closures with no garbage collection sounds painful in its
own right.

Andrew Haley

unread,
Mar 2, 2012, 2:13:58 PM3/2/12
to
Yes. As discussed recently at some length. :-)

Andrew.

John Passaniti

unread,
Mar 2, 2012, 2:25:55 PM3/2/12
to
On Mar 2, 2:07 pm, Paul Rubin <no.em...@nospam.invalid> wrote:
> Having lexical closures with no garbage collection sounds
> painful in its own right.

Yep. The moment you have the ability to create a lexically-scoped
closure and freely pass it around, you have something that can outlive
the activation it occurred in. Some form of garbage collection is
needed. When I've brought this up in comp.lang.forth in the past, the
usual knee-jerk reaction is "gosh, you can do that manually, it isn't
that hard." Well, yeah, and you can mix broken glass in your morning
breakfast too for added crunch.

Regardless, I look forward to seeing whatever it is Hugh thinks a
closure is.

Bernd Paysan

unread,
Mar 2, 2012, 7:49:15 PM3/2/12
to
John Passaniti wrote:
> For most everyone else, polymorphism is perhaps the key feature of OOP
> that people value. It's the feature that makes inheritance useful
> beyond just simple aggregation of data. It's the feature that lets
> you treat subtypes consistently and without having to resort to
> control structures that dispatch based on type. It's pretty
> fundamental. I can easily imagine object oriented programming without
> (strict) encapsulation and without inheritance. I can't imagine
> object-oriented programming without polymorphism in some form. If you
> can, I'd really enjoy hearing how you define object-oriented because
> it's completely outside any definition I'm aware of.

Well, it seems to be quite difficult to get that message through.
Stephen Pelc opened the discussion on last EuroForth, and it soon turned
out that quite a number of people in the Forth community think, OOP is
structures with some words attached in a private scope, and this weird
late binding/polymorphism/vtable concept is not necessary, and too
complicated, anyways (nonwithstanding that mini-oof, with its just 12
lines, implements that).

Strict encapsulation is something that is counter the philosophy of
Forth not to bury your tools, and to enforce sanity of the code through
the compiler. The code may be insane, but the compiler is certainly not
clever enoung to know if that's the case.

--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://bernd-paysan.de/

Ed

unread,
Mar 2, 2012, 8:47:44 PM3/2/12
to
Elizabeth D. Rather wrote:
> On 2/23/12 5:32 PM, Ed wrote:
> > Elizabeth D. Rather wrote:
> >> ...
> >> I truly don't understand why everyone is so allergic to declaring
> >> dependencies, as though it were a mark of shame.
> >
> > It is a mark of shame.
> >
> > ANS-Forth is God (and Bruce his prophet). Portability is
> > the holy grail of ANS-Forth. The more portable our code,
> > the closer we must be to God. Anything less indicates
> > failure on our part.
> >
> > What is not portable is sin. Sinning can be corrected with
> > punishment and flagellation on c.l.f. Bruce whips us until
> > we are pure and clean - worthy acolytes of the great God
> > ANS-Forth.
> >
> > :)
>
> Ok, have your joke, but I think Bruce is as practical as the next person
> when it comes to making a realistic assessment of what practical
> portability is needed.

I know of no one's complement machines that I realistically
need to support.



WJ

unread,
Mar 2, 2012, 10:45:24 PM3/2/12
to
hughag...@yahoo.com wrote:

> Writing a program that generates an ascii file containing numeric data
> seems like a pretty common and mundane job. In any other language it would
> be easy. In AMS-Forth, the programmer is required to write his own function
> to convert a float into a string. Writing a program in ANS-Forth is
> somewhat like building a cabin using only an axe, just like the pioneers
> did in the 1800s. You know, this might be the reason why ANS-Forth did not
> become popular for application programming --- do you think?
>
> But hey --- it is only 2012, so it is not too late for us to finally write
> some code to convert floats into strings (actually I wrote SCIENTIFIC and
> ENGINEERING in 2010, but nobody noticed so we are still dinking around with
> this stuff in 2012).

It is too late for the boneheads here. They desperately insist
on keeping Forth a very low-level language that is useful only
for programming an embedded controller that flushes a toilet.

BruceMcF

unread,
Mar 3, 2012, 1:26:11 AM3/3/12
to
On Mar 2, 8:47 pm, "Ed" <nos...@invalid.com> wrote:
> I know of no one's complement machines that I realistically
> need to support.

Not just one's complement machines ~ crippled one's complement
machines without a carry wraparound flag.

Given the ability to implement microprocessors on FPGA cores, someone
could very well implement a processor with crippled 2's complement
arithmetic that makes supporting the normal U< behavior expensive.

Now, specifying the common 1's complement and 2's complement
*treatment* of:
... ( +n1 -n2 ) U< ...

... as the standard behavior of U< would impose extra work on such
crippled 2's complement hardware or crippled 1's complement hardware.
And probably on any signed magnitude hardware. But:
(X work / implementation)*(0 implementations) = 0 extra work

... so I don't see anything wrong with it.

Albert van der Horst

unread,
Mar 3, 2012, 6:00:22 AM3/3/12
to
In article <be715108-58e0-4ea8...@l1g2000vbc.googlegroups.com>,
John Passaniti <john.pa...@gmail.com> wrote:
>On Mar 2, 2:07=A0pm, Paul Rubin <no.em...@nospam.invalid> wrote:
>> Having lexical closures with no garbage collection sounds
>> painful in its own right.
>
>Yep. The moment you have the ability to create a lexically-scoped
>closure and freely pass it around, you have something that can outlive
>the activation it occurred in. Some form of garbage collection is
>needed. When I've brought this up in comp.lang.forth in the past, the
>usual knee-jerk reaction is "gosh, you can do that manually, it isn't
>that hard." Well, yeah, and you can mix broken glass in your morning
>breakfast too for added crunch.

I don't agree. With 4Gbyte of internal memory in my Forth, a large
class of problems can be solved with closures, that ly around
indefinitely. Don't even try to collect them manually.

>
>Regardless, I look forward to seeing whatever it is Hugh thinks a
>closure is.

Me too. I hope he leaves the garbage collection out, as that diminishes
the chance we'll ever see something from it.

Groetjes Albert

--
--
Albert van der Horst, UTRECHT,THE NETHERLANDS
Economic growth -- being exponential -- ultimately falters.
albert@spe&ar&c.xs4all.nl &=n http://home.hccnet.nl/a.w.m.van.der.horst

Paul Rubin

unread,
Mar 3, 2012, 6:17:22 AM3/3/12
to
Albert van der Horst <alb...@spenarnc.xs4all.nl> writes:
> I don't agree. With 4Gbyte of internal memory in my Forth, a large
> class of problems can be solved with closures, that ly around
> indefinitely. Don't even try to collect them manually.

1) I think the typical system where Forth is used has nowhere near 4G of
memory.

2) If you program in a style that uses closures a lot, burning through
4G won't take very long anyway.

> Me too. I hope he leaves the garbage collection out, as that diminishes
> the chance we'll ever see something from it.

GC isn't that hard to implement, but I think it's not in the Forth
spirit to rely on it heavily. Forth as I see it is about very manual
control of almost everything, stingy use of memory, and deterministic
scheduling suitable for hard-real-time applications.

I'd say if you want a language with closures and GC, you actually want
Lisp rather than Forth, so it's better to just implement Lisp directly.

Anton Ertl

unread,
Mar 3, 2012, 7:30:23 AM3/3/12
to
Paul Rubin <no.e...@nospam.invalid> writes:
>2) If you program in a style that uses closures a lot, burning through
>4G won't take very long anyway.

You might be surprised. The S/K/ID paper [belinfante87] does
something like closures, but with combinators, and did not
garbage-collect unreachable combinators. I played around with it on a
C64, where I had maybe 30KB of free memory after the Forth system was
loaded. I expected to run out of memory very fast and was surprised
how far I got before that happened.

In a similar vein, the Gray parser generator generates sets in memory,
some of which are not needed later; I did not try to reclaim the
memory they use, but I measured the amount of memory used for sets for
a relativly large grammar (the Oberon grammar). The amount of space
used was 5719 bytes, and only a part of that was not needed. Trying
to reclaim the memory would have probably cost more memory than it
would have reclaimed.

@string(jfar="Journal of Forth Application and Research")
@Article{belinfante87,
author = "Johan G.F. Belinfante",
title = "S/K/ID: Combinators in Forth",
journal = jfar,
year = "1987",
volume = "4",
number = "4",
pages = "555--580"
}

- anton
--
M. Anton Ertl http://www.complang.tuwien.ac.at/anton/home.html
comp.lang.forth FAQs: http://www.complang.tuwien.ac.at/forth/faq/toc.html
New standard: http://www.forth200x.org/forth200x.html
EuroForth 2011: http://www.euroforth.org/ef11/

Jan Coombs

unread,
Mar 3, 2012, 9:32:13 AM3/3/12
to
On 03/03/12 06:26, BruceMcF wrote:
> On Mar 2, 8:47 pm, "Ed"<nos...@invalid.com> wrote:
>> I know of no one's complement machines that I realistically
>> need to support.
>
> Not just one's complement machines ~ crippled one's complement
> machines without a carry wraparound flag.
>
> Given the ability to implement microprocessors on FPGA cores, someone
> could very well implement a processor with crippled 2's complement
> arithmetic that makes supporting the normal U< behavior expensive.

Work in hand. The processor supports only a signed integer of
unconstrained size, so there is no wrap from maxint to minint or back.

Should anyone wish to experiment with more conventional stack
hardware, targeting FPGAs, I have both j1 and b16 just working in a
simple open and free simulation environment.

Jan Coombs.

Marcel Hendrix

unread,
Mar 3, 2012, 8:52:26 AM3/3/12
to
Paul Rubin <no.e...@nospam.invalid> wrote: Re: Adding thousands separators

> Albert van der Horst <alb...@spenarnc.xs4all.nl> writes:
>> I don't agree. With 4Gbyte of internal memory in my Forth, a large
>> class of problems can be solved with closures, that ly around
>> indefinitely. Don't even try to collect them manually.
[..]
> GC isn't that hard to implement, but I think it's not in the Forth
> spirit to rely on it heavily. Forth as I see it is about very manual
> control of almost everything, stingy use of memory, and deterministic
> scheduling suitable for hard-real-time applications.

> I'd say if you want a language with closures and GC, you actually want
> Lisp rather than Forth, so it's better to just implement Lisp directly.

What (more) do we need for a useful closure?

-marcel

-- ---------
0 [IF]
Python closure ( http://en.wikipedia.org/wiki/Closure_(computer_science)#Example )

def counter():
x = 0
def increment(y):
nonlocal x
x += y
print(x)
return increment

counter1_increment = counter()
counter2_increment = counter()

counter1_increment(1) # prints 1
counter1_increment(7) # prints 8
counter2_increment(1) # prints 1
counter1_increment(1) # prints 9
[THEN]

: closure:
CREATE ( "name" -- )
CELL ALLOCATE THROW ,
( \ ) FORGET> @ FREE ?ALLOCATE
DOES> ( y -- )
@ LOCALS| x |
x +!
CR ." x = " x @ . ;

closure: counter1_increment
closure: counter2_increment

1 counter1_increment \ prints 1
7 counter1_increment \ prints 8
1 counter2_increment \ prints 1
1 counter1_increment \ prints 9

Coos Haak

unread,
Mar 3, 2012, 10:23:47 AM3/3/12
to
Op Sat, 3 Mar 2012 15:52:26 +0200 schreef Marcel Hendrix:
After modifying the code, my FORGET> must be after DOES>, it works.
But after forgetting and reloading, the values of x are somewhat off.
ALLOCATE does not initialize its memory to zero by default.

--
Coos

CHForth, 16 bit DOS applications
http://home.hccnet.nl/j.j.haak/forth.html

Andrew Haley

unread,
Mar 3, 2012, 12:02:03 PM3/3/12
to
Paul Rubin <no.e...@nospam.invalid> wrote:
> Albert van der Horst <alb...@spenarnc.xs4all.nl> writes:
>> I don't agree. With 4Gbyte of internal memory in my Forth, a large
>> class of problems can be solved with closures, that ly around
>> indefinitely. Don't even try to collect them manually.
>
> 1) I think the typical system where Forth is used has nowhere near 4G of
> memory.
>
> 2) If you program in a style that uses closures a lot, burning through
> 4G won't take very long anyway.
>
>> Me too. I hope he leaves the garbage collection out, as that diminishes
>> the chance we'll ever see something from it.
>
> GC isn't that hard to implement, but I think it's not in the Forth
> spirit to rely on it heavily. Forth as I see it is about very manual
> control of almost everything, stingy use of memory, and deterministic
> scheduling suitable for hard-real-time applications.

True, but there's nothing to stop you from doing GC in a fairly low-
level way. I think it might be very nice fit if done well. I suppose
to do a nice job it'd help to make the virtual machine aware of the
GC, but it needn't be necessary. It depends on just how much of the
system you use GC for.

WRT deterministic scheduling, dynamic memory allocation doesn't have
to be on the critical path of the hard real-time part of the
application. When I did Forth full-time (mostly in industrial control
applications) I was terrified of GC and knew that it wasn't
appropriate. Now that I understand GC better I think that I was
mistaken, and it would have been useful. I might be wrong about that.
;-)

Andrew.

Anton Ertl

unread,
Mar 3, 2012, 12:25:09 PM3/3/12
to
Andrew Haley <andr...@littlepinkcloud.invalid> writes:
>True, but there's nothing to stop you from doing GC in a fairly low-
>level way. I think it might be very nice fit if done well. I suppose
>to do a nice job it'd help to make the virtual machine aware of the
>GC, but it needn't be necessary. It depends on just how much of the
>system you use GC for.

Hmm, maybe the problem with Forth and libraries is not that they don't
exist, but that the community ignores them. GC for Forth has existed
for at least 12 years.

http://www.complang.tuwien.ac.at/forth/garbage-collection.zip

Paul Rubin

unread,
Mar 3, 2012, 1:14:13 PM3/3/12
to
an...@mips.complang.tuwien.ac.at (Anton Ertl) writes:
> http://www.complang.tuwien.ac.at/forth/garbage-collection.zip

I remember looking at that and thinking it was really cool, but that its
limitation of not being able to scan the return and locals stacks made
it difficult to use. Maybe I'm wrong about that.

I remember seeing a mini-Scheme interpreter written in Forth, that
turned out to have no GC, so after it ran for a while it would just run
out of memory. I half-remember looking at it and deciding that the way
it was written, fixing that problem by plugging your GC into it would
have been difficult.

Paul Rubin

unread,
Mar 3, 2012, 1:19:28 PM3/3/12
to
m...@iae.nl (Marcel Hendrix) writes:
> What (more) do we need for a useful closure?
> : closure:
> CREATE ( "name" -- ) ...

I don't think that's a real closure, in that it absorbs a source token
and makes a dictionary entry. You have to be able to make them on the
fly, for example if you want an array of them. Closures have to be able
to create and return other closures, and so on.
It is loading more messages.
0 new messages