http://www.spacer.com/spacecast/news/mars-mco-99d.html
states that the Mars Climate Orbiter spacecraft hit the Martian
atmosphere because JPL was using metric units to describe the
retro rockets, while Lockheed used English units--and the discrepancy
slipped through the cracks.
I would note that a proper user interface should be immune to
such problems. Thus, the little program units.f given below
automatically converts to/from the internal units of your computer.
\ User interface for automatic unit conversion on
\ data entry and display
\ ---------------------------------------------------
\ (c) Copyright 1999 Julian V. Noble. \
\ Permission is granted by the author to \
\ use this software for any application pro- \
\ vided this copyright notice is preserved. \
\ ---------------------------------------------------
\ This is an ANS Forth program requiring the CORE and
\ CORE EXT wordsets
MARKER -units
HERE 1 CELLS ALLOT \ allocate hidden storage
: as TRUE [ DUP ] LITERAL ! ;
: ~as FALSE [ DUP ] LITERAL ! ; ~as
: units CREATE , , DOES> 2@ [ DUP ] LITERAL @
IF SWAP THEN */ ~as ;
DROP
\ With the definitions below the internal units are millimeters;
\ this works fine on 16-bit systems.
254 10 units inches
254 12 * 10 units feet
254 36 * 10 units yards
10 1 units centimeters
1000 1 units meters
\ For finer grain--say 0.1 mm (suitable for 32-bit systems)--
\ multiply by 10, as in 2540 10 units inches
FALSE [IF]
Usage:
10 FEET . <cr> 3048 ok
3 METERS . <cr> 3000 ok
.......................
etc.
10 FEET . <cr> 3048 ok
3048 AS FEET . <cr> 10 ok
[THEN]
However, this leads me to a question. In making the program ANS
compliant I used a VARIABLE <as> to hold a flag. It seems to me
that it would be better to hide the data space where the flag
is kept. So I did it this way:
HERE 1 CELLS ALLOT \ allocate hidden storage
: as TRUE [ DUP ] LITERAL ! ;
: ~as FALSE [ DUP ] LITERAL ! ; ~as
: units CREATE , , DOES> 2@ [ DUP ] LITERAL @
IF SWAP THEN */ ~as ;
DROP \ drop address of hidden storage
and this works under Win32Forth, but not under GForth 0.3 .
It seems to me that I am not changing the stack depth nor
messing with colon-sys. So is it me or GForth that is not
ANS compliant?
--
Julian V. Noble
j...@virginia.edu
"Elegance is for tailors!" -- Ludwig Boltzmann
j...@node5.unix.Virginia.EDU writes:
[ deleted ]
> \ For finer grain--say 0.1 mm (suitable for 32-bit systems)--
> \ multiply by 10, as in 2540 10 units inches
^^
100 ( blush )
>HERE 1 CELLS ALLOT \ allocate hidden storage
>: as TRUE [ DUP ] LITERAL ! ;
>: ~as FALSE [ DUP ] LITERAL ! ; ~as
>: units CREATE , , DOES> 2@ [ DUP ] LITERAL @
> IF SWAP THEN */ ~as ;
>DROP \ drop address of hidden storage
>and this works under Win32Forth, but not under GForth 0.3 .
>It seems to me that I am not changing the stack depth nor
>messing with colon-sys. So is it me or GForth that is not
>ANS compliant?
It's you. Here's the problem: : is allowed (but not required)
to leave some indeterminate amount of its own garbage on the
stack; if it does so then ; will of course clean that all up.
So you can't leave things on the data stack before : and then
expect to find them during compilation.
An approach that sometimes works is this:
>R : as TRUE [ R@ ] LITERAL ! ; R>
The reason this sometimes works is that some Forth interpreters
let you store things safely on the return stack provided the
return stack is clear before the end of the line. I think maybe
more of them accept that from source files than from the keyboard.
But it still isn't completely portable.
If you already have some other temporary variable you could store
the address in it.
HERE 1 CELLS ALLOT TEMP !
: as TRUE [ TEMP @ ] LITERAL ! ;
Provided you don't need TEMP for something else at the time. Ah.
HERE 1 CELLS ALLOT BASE ! \ allocate hidden storage
: as TRUE [ BASE @ ] LITERAL ! ;
: ~as FALSE [ BASE @ ] LITERAL ! ; ~as
: units CREATE , , DOES> 2@ [ BASE @ ] LITERAL @
IF SWAP THEN */ ~as ;
DECIMAL \ drop address of hidden storage
This one will give you a lot of trouble if you happen to change
your code so it parses a number. Maybe the easiest and safest
thing is to just break down and name your address.
It might seem like an imposition on programmers to let : use the
stack. This can make it cleaner and of course slightly smaller to
implement : but then everybody has to suffer for it later. However,
if you ever want to extend : to do your special stuff you'll find
it a bit easier this way too. And the same reasoning that led you
to want to hide the data for your code also applies to hiding the
data for : .
Thanks, Jonah. I knew there had to be something involving colon-sys.
Here's the solution: since I don't want to be able to access the
hidden storage accidentally, I put its location in a CONSTANT. Thus
HERE 1 CELLS ALLOT \ allocate hidden storage
CONSTANT <as> \ name its location
: as TRUE <as> ! ;
: ~as FALSE <as> ! ; ~as
: units CREATE ( SWAP) , , DOES> 2@ <as> @
IF SWAP THEN */ ~as ;
Perfect safety would be obtainable if there were an ANS beheading
mechanism. Or at least a hiding mechanism, to render <as> invisible
to subsequent definitions.
I often use a free user variable when I need "secret" storage when
compiling a word. I can even use some occupied ones by fetching before
colon, stuffing with data, and restoring after semicolon.
Jerry
--
Engineering is the art of making what you want from things you can get.
-----------------------------------------------------------------------
>j...@node5.unix.Virginia.EDU (Julian V. Noble) wrote:
>
>>HERE 1 CELLS ALLOT \ allocate hidden storage
>>: as TRUE [ DUP ] LITERAL ! ;
>>: ~as FALSE [ DUP ] LITERAL ! ; ~as
>>: units CREATE , , DOES> 2@ [ DUP ] LITERAL @
>> IF SWAP THEN */ ~as ;
>>DROP \ drop address of hidden storage
>
>>and this works under Win32Forth, but not under GForth 0.3 .
>>It seems to me that I am not changing the stack depth nor
>>messing with colon-sys. So is it me or GForth that is not
>>ANS compliant?
>
>It's you. Here's the problem: : is allowed (but not required)
>to leave some indeterminate amount of its own garbage on the
>stack; if it does so then ; will of course clean that all up.
>
<Non-ANS solution>
For non-ANS systems Julian's example works well in the given
simple case but gets a little nasty when getting the external stack
data within a IF THEN structure or other such which uses the data
stack at compile time for structure-controls. What works better are
words that know the stack position prior to the colon. In Fig Forth
the stack position is saved in the CSP variable when colon is executed
and words can be build that uses the CSP as a pointer to an array
from which any external stack item can be fetched. I use two words
]SP-LIT and ]SP, to fetch an external stack item and make it a literal
(the former word) or compile it (the latter word). Using Julian's
example it would look like the following:
HERE 1 CELLS ALLOT \ storage for flag
: as TRUE [ 0 ]SP-LIT ! ; \ store true flag
: ~as FALSE [ 0 ]SP-LIT ! ; \ store false flag
: as? [ 0 ]SP-LIT @ ; \ fetch flag
: units
CREATE ( n1 n2 "ccc" --)
, ,
DOES> \ n -- (n*n1)/n2 if f(as) is false
\ n -- (n*n2)/n1 and f(as) is reset if f(as) is true
2@
as? IF SWAP ~as THEN
*/
;
drop \ discard hidden address
~as \ init, store false flag
Not shown in the simple example is that these two words are impervious
to whatever the colon or any structure might add to the data stack
during compile time.
( KERNEL EXT: ]sp, ]sp-lit)
( compile n-th external data stack item)
: ]sp, ( compile: ni...n0 * i -- ni..n0 *)
( run: * -- *)
2* csp @ + @ ] [compile] , ;
( make literal n-th external data stack item)
: ]sp-lit ( compile: ni...n0 * i -- ni..n0 *)
( run: -- ni)
2* csp @ + @ ] [compile] literal ;
;s
re: ]sp, and ]sp-lit
1. are effectively compiling words
2. they use but do not consume an external data stack item
Wil Baden has a similar word to ]SP-LIT but uses a user defined
variable and redefines colon to set it. Perhaps it's standard, I don't
recall.
</non-ANS solution>
--
Tom Zegub tze...@dhc.net
WasteLand http://www.dhc.net/~tzegub
|_|_|_|_
| | | | http://www.dhc.net/~tzegub/fop.htm
There is. I added it above.
> Here's the solution: since I don't want to be able to access the
> hidden storage accidentally, I put its location in a CONSTANT. Thus
>
> HERE 1 CELLS ALLOT \ allocate hidden storage
> CONSTANT <as> \ name its location
This is NOT a good solution where you are going to save the compiled
code on an OS where the code will likely be loaded into a different
memory location next time.
In such environments, VARIABLE, USER, etc auto-correct for the different
base address by using the offset from the beginning of the data space
and adding that back to the new base address when computing the real
address of their data.
-- ward
> Here's the solution: since I don't want to be able to access the
> hidden storage accidentally, I put its location in a CONSTANT. Thus
>
> HERE 1 CELLS ALLOT \ allocate hidden storage
> CONSTANT <as> \ name its location
w> This is NOT a good solution where you are going to save the compiled
w> code on an OS where the code will likely be loaded into a different
w> memory location next time.
So it is not a solid saving mechanism.
w> In such environments, VARIABLE, USER, etc auto-correct for the
w> different base address by using the offset from the beginning of the
w> data space and adding that back to the new base address when
w> computing the real address of their data.
This should not be the problem of the one who applies HERE, that HERE
remains HERE wherever you put the code. Even if a Forth compiler per se
is trivial, it should though contain resolutions for the not-so-trivial
aspects which arrive through the combined use of interpretation /
compilation.
(This is not to stress plain theory - here I have an implementation for
simple messy-DOS with 32-bit linear addressing, which will reliably save
such use of HERE as above. Yes - this is not trivial ;) but you can
write Forth sources as you may expect you can write it, and run it,
that's what it is for).
[ zapped ]
> > Perfect safety would be obtainable if there were an ANS beheading
> > mechanism. Or at least a hiding mechanism, to render <as> invisible
> > to subsequent definitions.
>
> There is. I added it above.
>
> Jerry
Well, I have on occasion defined a VARIABLE or VALUE, used it to hold
the address of the temp storage, and then put something else in it--
usually the address of NOOP. But I was hoping for a more elegant
solution. That is, one has to define two pieces of memory to get
the use of one. Ugly. Beheading is neater.
I had another thought: where I want to define the hidden storage,
I put its address in PAD. That is, I say things like
HERE 1 CELLS ALLOT PAD ! \ allocate hidden storage
: as TRUE [ PAD @ ] LITERAL ! ;
This also does not work with GForth, however, presumably because PAD
is a moving target in that implementation. Works in Win32Forth, though.
Sigh.
>I had another thought: where I want to define the hidden storage,
>I put its address in PAD. That is, I say things like
> HERE 1 CELLS ALLOT PAD ! \ allocate hidden storage
> : as TRUE [ PAD @ ] LITERAL ! ;
>This also does not work with GForth, however, presumably because PAD
>is a moving target in that implementation. Works in Win32Forth, though.
>Sigh.
BASE is available. It isn't a moving target. You can store a cell's worth
in it provided you don't try to parse a number.
Excellent! Thanks, Jonah! I forgot all about BASE. Works a treat.
Here is the revised code, for anyone interested:
\ User interface for automatic unit conversion on
\ data entry and display
\ ---------------------------------------------------
\ (c) Copyright 1999 Julian V. Noble. \
\ Permission is granted by the author to \
\ use this software for any application pro- \
\ vided this copyright notice is preserved. \
\ ---------------------------------------------------
\ This is an ANS Forth program requiring the CORE and
\ CORE EXT wordsets
MARKER -units
BASE @
HERE 1 CELLS ALLOT BASE ! \ allocate hidden storage
: as TRUE [ BASE @ ] LITERAL ! ;
: ~as FALSE [ BASE @ ] LITERAL ! ; ~as
: units CREATE , , DOES> 2@ [ BASE @ ] LITERAL @
IF SWAP THEN */ ~as ;
BASE !
\ With the definitions below the internal units are millimeters;
\ this works fine on 16-bit systems.
254 10 units inches
254 12 * 10 units feet
254 36 * 10 units yards
10 1 units centimeters
1000 1 units meters
\ For finer grain--say 0.1 mm (suitable for 32-bit systems)--
\ multiply by 10, as in 2540 100 units inches
FALSE [IF]
Usage:
10 FEET . 3048 ok
3 METERS . 3000 ok
.......................
etc.
3048 AS FEET . 10 ok
10 YARDS AS FEET . 30 ok
[THEN]
I don't see that this gives you any advantage over
VARIABLE <as>
Why do you think it is more likely that you access <as> accidentially
with the latter implementation?
>This is NOT a good solution where you are going to save the compiled
>code on an OS where the code will likely be loaded into a different
>memory location next time.
In Gforth, if you create a relocatable image (which is slightly more
involved that a simple SAVESYSTEM), the address in the constant <as>
will be relocated as well (creating a relocatable image works by
comparing two non-relocatable images).
In Forth systems with run-time relocation (e.g., cforth and
Win32Forth) all addresses (including HERE above) are represented as
offsets from some base address, and therefore the CONSTANT-based
implementation works there as well.
>In such environments, VARIABLE, USER, etc auto-correct for the different
>base address by using the offset from the beginning of the data space
>and adding that back to the new base address when computing the real
>address of their data.
In Gforth, if you use a non-relocatable image and manage to get Gforth
to run it on a different address, variables indeed produce the correct
address (because it's computed as offset from the CFA of the
variable), but the system would crash on startup, because there are
lots of addresses in the system that are simply stored, not computed
at run-time.
- anton
--
M. Anton Ertl Some things have to be seen to be believed
an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
http://www.complang.tuwien.ac.at/anton/home.html
JT> BASE is available. It isn't a moving target. You can store a
JT> cell's worth in it provided you don't try to parse a number.
If you do this here, so you get a throw: 'invalid numeric argument' the
next time the interpreter continues parsing.
It isn't--it was a late-night aberration. Jonah's solution of using BASE
(which is non-migratory during colon-sys) as a temp storage is the
elegant answer to the perplexity. Me 'at's off to the Duke.
Well, I think Jonah meant you should not use this method in a word that
has to set the BASE internally. I do not see any ANS prohibition on
changing BASE during compilation (i.e. during colon-sys -- whatever that
is doing) so the locution
BASE @ \ save BASE
HERE 1 CELLS ALLOT BASE ! \ allocate hidden storage
\ using BASE as temp storage
: as TRUE [ BASE @ ] LITERAL ! ;
: ~as FALSE [ BASE @ ] LITERAL ! ; ~as
: units CREATE , ,
DOES> 2@ [ BASE @ ] LITERAL
@ IF SWAP THEN */ ~as ;
BASE ! \ restore BASE
should work on any ANS-compliant system.
Of course you are perfectly right--if you try this in a situation where
BASE has to change during compilation--for ex. you need to do HEX or
something--you could get into trouble. But I think even here it would
be possible to work around without arousing the ire of the compilation
process to the point of a "throw".
>JT> BASE is available. It isn't a moving target. You can store a
>JT> cell's worth in it provided you don't try to parse a number.
>If you do this here, so you get a throw: 'invalid numeric argument' the
>next time the interpreter continues parsing.
Ouch. You mean, it checks BASE for valid bases? And it does it not
just before it deconstructs a number but every time it parses a word?
Jeez, man, that's sick.
I guess it's legal for an ANS implementation to do it, though. That
means it isn't portable to store things in BASE regardless whether
you restore it before you parse a number.
>BASE @ \ save BASE
>HERE 1 CELLS ALLOT BASE ! \ allocate hidden storage
> \ using BASE as temp storage
>: as TRUE [ BASE @ ] LITERAL ! ;
>: ~as FALSE [ BASE @ ] LITERAL ! ; ~as
>: units CREATE , ,
> DOES> 2@ [ BASE @ ] LITERAL
> @ IF SWAP THEN */ ~as ;
>BASE ! \ restore BASE
>should work on any ANS-compliant system.
>Of course you are perfectly right--if you try this in a situation where
>BASE has to change during compilation--for ex. you need to do HEX or
>something--you could get into trouble. But I think even here it would
>be possible to work around without arousing the ire of the compilation
>process to the point of a "throw".
I'm afraid Ewald is right. Systems are allowed to check BASE and complain
about an invalid radix. It makes sense to me to do that at the start of
the routines that input or output numbers -- otherwise you shouldn't care,
and for a routine that does a lot of double-number divisions the overhead
wouldn't amount to much. But it might be cheaper (though less safe) to
check at the end of each line of input.
I thought BASE was an easy way around the problem but it might not be
completely portable.
> I'm afraid Ewald is right. Systems are allowed to check BASE and
> complain about an invalid radix.
I'm sure it is possible to write a Forth system that makes life a misery,
while still conforming to every sentence in the Standard. Is it allowed to
simply not use such atrocities or should we turn the other cheek(s)?
-marcel
I nominate Jonah to be "Tailor of the Week".
MH> Jonah wrote:
> I'm afraid Ewald is right. Systems are allowed to check BASE and
> complain about an invalid radix.
MH> I'm sure it is possible to write a Forth system that makes life a
MH> misery, while still conforming to every sentence in the Standard.
Is
MH> it allowed to simply not use such atrocities or should we turn the
MH> other cheek(s)?
I prefer a system which does not crash when inputting '1 BASE !'. Had no
standard in mind with this.
JT> I'm afraid Ewald is right. Systems are allowed to check BASE and
JT> complain about an invalid radix. It makes sense to me to do that
at
JT> the start of the routines that input or output numbers -- otherwise
JT> you shouldn't care, and for a routine that does a lot of
JT> double-number divisions the overhead wouldn't amount to much. But
JT> it might be cheaper (though less safe) to check at the end of each
JT> line of input.
Should be same expensive both ways (the check is the same [*]). But
run-time performance seems more valuable to me. And kind of stupid
problems arise more often during interpretation / compilation, so it
might be worth more to protect that stage.
I'd not have assumed that BASE might be used as a scratch-pad area - I'd
expected the more funny things instead to happen in compiled code (there
is no check - it survived already compilation so it should not be overly
stupid things inside; the rest is in the hands of the one who wrote the
stuff)...
[*] 'BASE @ 2 36 1+ WITHIN 0= IF DECIMAL -24 THROW THEN'
Regardless of whether there is a prohibition or not, it's VERY bad
programming practice to change ANYTHING that isn't either part of your
program or explicitly meant for the intended usage. Since there is no
transportable mechanism for the purpose of passing parameters into a word
under definition, the programmer should provide his own by defining a
variable (with an appropriate name!). If the application is a small
embedded system which can't afford to waste a few bytes of memory, I'm sure
that the variable can be put to some other purpose as well.
--
-GJC
-gcha...@shore.net
It's more sensible and efficient to declare a common use
temporary variable. For one thing you won't have to save and
restore it.
I like it as a 2VARIABLE, or better yet, as 2 successive USER
variables.
2VARIABLE TEMP
All of this misses the point that Ward McFarland made about
purloining the value of HERE.
> This is NOT a good solution where you are going to save the
> compiled code on an OS where the code will likely be loaded
> into a different memory location next time.
> In such environments, VARIABLE, USER, etc auto-correct for
> the different base address by using the offset from the
> beginning of the data space and adding that back to the new
> base address when computing the real address of their data.
HERE is the address of the next available location in data
space. You can save it as a constant or in a variable and
use it until you terminate the session. If you have saved
all your work so that you don't have to re-compile it,
everything may be at a different location any time you
load.
Among implementations that will do this are SwiftForth and
PowerMacForth. I'm sure there are many others.
In some implementations new word lists are based on the
relocatable value of HERE. I think it's a defect if they
do not, but it's not in the Standard. (PowerMacForth fails.)
In this situation, anonymous variables, constants, or
whatever can be defined.
Tools.
: IMPLEMENTATION ( -- )
GET-ORDER WORDLIST SWAP 1+ SET-ORDER ;
: INTERFACE ( -- )
GET-ORDER 2 PICK SET-CURRENT SET-ORDER ;
Example.
IMPLEMENTATION DEFINITIONS
\ REVERSE is true to reverse conversion.
VARIABLE REVERSE
INTERFACE
: as TRUE REVERSE ! ;
: ~as FALSE REVERSE ! ; ~as
: units CREATE , , DOES> 2@ REVERSE @
IF SWAP THEN */ ~as ;
PREVIOUS DEFINITIONS
INTERFACE can be used with vocabularies.
VOCABULARY SECRET
ALSO SECRET DEFINITIONS
...
INTERFACE
...
DEFINITIONS \ Back to SECRET
...
INTERFACE
...
PREVIOUS DEFINITIONS
(
--
Wil Baden Costa Mesa, California WilB...@Netcom.com
)
\ reverse has true to reverse conversion.
\ ~as resets direction of conversion.
VARIABLE reverse
: ~as FALSE reverse ! ; ~as
INTERFACE
: as TRUE reverse ! ;
: units CREATE , , DOES> 2@ reverse @
How is that a crash? If you mean you subsequently have trouble interpreting
numbers, you have only to use DECIMAL or HEX to recover.
Cheers,
Elizabeth
--
===============================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310-372-8493
111 N. Sepulveda Blvd. Fax: +1 310-318-7130
Manhattan Beach, CA 90266
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
===============================================
>Julian V. Noble <j...@node7.unix.Virginia.EDU> wrote:
>
>> Here's the solution: since I don't want to be able to access the
>> hidden storage accidentally, I put its location in a CONSTANT. Thus
>>
>> HERE 1 CELLS ALLOT \ allocate hidden storage
>> CONSTANT <as> \ name its location
>
>
>This is NOT a good solution where you are going to save the compiled
>code on an OS where the code will likely be loaded into a different
>memory location next time.
>
>In such environments, VARIABLE, USER, etc auto-correct for the different
>base address by using the offset from the beginning of the data space
>and adding that back to the new base address when computing the real
>address of their data.
>
Not ever faced with such a situation I have little feel for the
problem. But it seems to be the same problem that Wil Baden addressed
in his post on Damned Code which puzzled me. Here is my naive take on
the matter.
Relocatable code is commonplace and the relocation is typically
transparent to the code because the compiled addresses are task
relevant and not absolute. The problem you describe seems not to be
with the OS for relocating code but with the Forth system for
compiling absolute addresses. Is this necessary? Forcing applications
to deal with relocation concerns certainly is not desirable.
If such situations are truly unavoidable, it is interesting that they
are non-standard since nothing in the standard addresses relocation
concerns. Julian's code above is standard but would not work in the
environment you give.
If an OS can relocate a task without updating base pointers, then the
Forth system must do the job for it to be standard. Relocation matters
if left to Forth should be handled by the system and not the
application.
Win32Forth handles relocatability automatically, by using relative
addresses within the Forth image. Which works fine, as long as you
are writing ANS code, and NOT interfacing to the operating system.
As soon as you interface to the operating system, you HAVE to deal
with the fact that the OS uses absolute addresses, and Forth doesn't.
So the above example works fine in Win32Forth, but then it is entirely
internal to the Forth.
Many people disagree with my approach, as incurring too much overhead,
and still not completely eliminating all the rel to abs and abs to rel
conversions. Maybe they are right. But at least it focuses the problem on
the OS interface, and not at all the forth code you write.
Just my thoughts,
Tom Zimmer
>>This is NOT a good solution where you are going to save the compiled
>>code on an OS where the code will likely be loaded into a different
>>memory location next time.
>>In such environments, VARIABLE, USER, etc auto-correct for the different
>>base address by using the offset from the beginning of the data space
>>and adding that back to the new base address when computing the real
>>address of their data.
> Not ever faced with such a situation I have little feel for the
>problem. But it seems to be the same problem that Wil Baden addressed
>in his post on Damned Code which puzzled me. Here is my naive take on
>the matter.
I haven't had to deal with this "problem" either. I also have a
naive idea about this.
> If an OS can relocate a task without updating base pointers, then the
>Forth system must do the job for it to be standard. Relocation matters
>if left to Forth should be handled by the system and not the
>application.
Imagine that the OS can load the Forth system anywhere. Imagine that
for this particular processor (and OS) it's far more efficient for the
Forth system to use absolute addresses. So the Forth system adjusts
all its addresses when it's first loaded.
It's easy (in theory) to adjust named variables, things done with CREATE,
etc. And xts can be tokens or something else easy. But when you compile
something using HERE and save the address as a constant, how will the
Forth system know what you intend? It's asking for a whole lot of
intelligence from the system.
It seems to me like a giant imposition to expect people to keep track
of this. It's a traditional technique that so far as I know is ANS
Standard Forth, and systems that can't handle HERE when they're
relocated are not standard systems once they're relocated. But still it
might be that the performance is worth it. Maybe the thing to do is to
get a utility (which can probably be written in standard code) that
warns you when you try to use HERE in a way that won't run on these
systems. Then when you import code to one of them you can use that
utility to tell you whether you're likely to have a problem. And if
the utility is written in standard code then you can run the utility to
find out whether you're likely to have a problem on those systems even
when you don't use a system like that at all.
2 1 base ! .
If it doesn't crash your system, the # is doing some BASE sanity checks
(or just a 2 MAX).
--
Bernd Paysan
"If you want it done right, you have to do it yourself"
http://www.jwdt.com/~paysan/
SwiftForth:
2 1 base ! . Pictured numeric output string overflow
Irresponsible to crash, IMO.
An environment can use absolute addressing or relative
addressing.
If it uses relative addressing, then a variable is the
same as a constant. Referencing a variable puts a constant
value on top of the stack. Loading or storing requires
double indexing -- by the top of the stack and the pointer
to the data space. USER variables will need triple indexing.
Cooperating with external routines requires converting
between relative and absolute addresses.
If the environment uses absolute addressing, then a variable
or user variable does indexing to resolve the address. Loading
or storing, the value in the top of the stack does not need
adjusting.
Cooperating with external routines the addresses are already
absolute.
Since RISC machines must have an address in a register to
manipulate it, absolute addressing seems better.
--
Wil WilB...@Netcom.com
> I prefer a system which does not crash when inputting '1 BASE !'. Had
no
> standard in mind with this.
"DR> How is that a crash? If you mean you subsequently have trouble
"DR> interpreting numbers, you have only to use DECIMAL or HEX to
"DR> recover.
The crux is buried at least in '#S', which does division and continues
as long as the (double-) quotient is not zero. When dividing by 1 it
never gets zero.
I agree, in not-so-rudimentary implementations a throw should be met (as
overflow of pictured numeric conversion buffer). So as well for
'>NUMBER', which only accepts the digit '0' then. But the guess, how
such a throw is related to the contents of BASE, might not always be
obvious.
(Btw. maybe you want to check your new-reader as it generates, with your
latest postings, for each response additionally an empty response.)
>> I prefer a system which does not crash when inputting '1 BASE !'. Had
>> no standard in mind with this.
>"DR> How is that a crash? If you mean you subsequently have trouble
>"DR> interpreting numbers, you have only to use DECIMAL or HEX to
>"DR> recover.
>The crux is buried at least in '#S', which does division and continues
>as long as the (double-) quotient is not zero. When dividing by 1 it
>never gets zero.
It's possible to do that by using a DO loop that goes 32 or 64 cycles,
that does LEAVE or UNLOOP EXIT if the quotient gets to zero.
Then 1 BASE gives a wrong answer but it doesn't crash. That's a
pretty arcane reason to use a loop instead of BEGIN though.
JT> It's possible to do that by using a DO loop that goes 32 or 64
JT> cycles, that does LEAVE or UNLOOP EXIT if the quotient gets to
zero.
JT> Then 1 BASE gives a wrong answer but it doesn't crash. That's a
JT> pretty arcane reason to use a loop instead of BEGIN though.
For sure one could insert a DO..LOOP. But this is doubling information
(size of PAD should be tracked in HOLD only), unreliabe (because you
don't know what else has been put for HOLD), and overhead which is
better put into checking somewhere else. The better place for a check is
HOLD, so it throws for buffer overflow (assuming HOLD is the building
tool for '#', '#S' and SIGN).
BASE is relevant for conversion between digits and an accumulator
(number accu plus multiplication in >NUMBER, or string accu plus
division with '#'). So the range of BASE is coupled to a range of
meaningful characters. Now, an interpreter which cannot deal with
numbers somehow is broken more in general, this is why I put in an
additional check to the interpreter.
Btw. a less used variable which should be available with BLOCK EXT (if I
recall it right) is SCR - patching that one should hardly hurt (ok,
maybe a badly written editor will try to allocate some gigabytes after
bad use
... ;) ).
This appears to have started when I installed Netscape Communicator 4.7
(replacing 4.6). If anyone has any suggestions, I'd be delighted to hear them!
Thanks,
In the order of desirability (suggestion 4 is especially undesirable,
but still better than what you do now).
1) Use a real newsreader; to avoid problems when posting, look for a
newsreader satisfying the Good Net-Keeping Seal of Approval
criteria (http://www.xs4all.nl/%7Ejs/gnksa/gnksa-evaluations.html).
2) Install 4.6 and restore the old settings.
3) Post only to test groups until you have fixed the problem.
4) Cancel your empty postings right after posting them.
That's easy to fix. Uninstall Communicator and use Internet
Explorer.
--
-GJC
-gcha...@shore.net
>
>Imagine that the OS can load the Forth system anywhere. Imagine that
>for this particular processor (and OS) it's far more efficient for the
>Forth system to use absolute addresses.
Yes, no problem in assuming that to be a given.
>So the Forth system adjusts
>all its addresses when it's first loaded.
>
>It's easy (in theory) to adjust named variables, things done with CREATE,
>etc. And xts can be tokens or something else easy. But when you compile
>something using HERE and save the address as a constant, how will the
>Forth system know what you intend? It's asking for a whole lot of
>intelligence from the system.
>
I was thinking a tight bit of code that does address translation
on fetch and store might be reasonable enough for the general case.
I agree that without hardware any address translation in software
will be less efficient than using absolute addresses.
I don't mind the choice between having a non-standard system
optimized to give high performance for a particular environment or
having a standard-system with good but not optimal performance for
some special environments. That kind of tradeoff is typical.
>It seems to me like a giant imposition to expect people to keep track
>of this. It's a traditional technique that so far as I know is ANS
>Standard Forth, and systems that can't handle HERE when they're
>relocated are not standard systems once they're relocated. But still it
[snip]
Besides the imposition, often in Forth many good things can come from
something small. By the same token then, to give up something small
might mean closing the door on many good possibilities.
>
>Kindly check my reasoning -- I haven't chosen my
>dogmatism yet.
>
None of that logic is in question. But as good and close as it gets
to being 'the' solution, the use of absolute addresses will limit you
to running only application code that is kosher. This may be fine in
your own community but from a general point of view your system will
appear an oddball with special requirements. If your intentions are to
cater to the general public, you may not want to have that stigma.
>conversions. Maybe they are right. But at least it focuses the problem on
>the OS interface, and not at all the forth code you write.
>
That's my preference, contain the problem at the interface and not
infect the application code. Even at the cost of some overhead I would
prefer this as the general approach.
When complex calculations are performed there are rounding errors and
fractional parts get truncated. If different units are used for the
calculations the results will be different.
As an example if the low bit of an integer represents 1 cm and you shift
right one, you lose a cm. If the low bit represents 1 inch you lose an
inch.
There are two solutions; have enough bits so there is no truncation. The
minimum number is infinity; ( consider a 1/3). Or use the same units for
your calculations.
When converting the internationally accepted units to English units (
units the English relegated to history in the 70's) there are dangers.
The exception is data entry fields long enough to represent the exact
equivalent.
Consider for example weight. The rest of the world uses grams. The US
tends to use avoirdupois ounces.
avoirdupois ounces * 28.349 523 125 = grams
or 1 gram = 0.035 273 96 oz
Now if you are weighing things to about a gram accuracy; are you going to
display oz to 8 digits just so you can enter the equivalent of 1 gram
exactly.
The conversion error is simply another error that has to be included in
your error calculations when using a system running in grams to weigh in
ounces instead of grams.
( Take care when talking about gold; that industry tends to use troy
ounces; troy ounce * 31.103 476 8 = gram)
Also take care if talking about beer; a fluid oz is different again ( it
is a measure of volume).
There is only one solution to this problem; the use of a common set of
units; it would seem the MARS probe loss is just another cost the US
condemned themselves to when they rejected the metric system.
As a lot of US engineering work is now done in the metric system; I am
really surprised Lockheed did this.
The metric systems is a consistent set of units; if you multiply force by
mass you get acceleration in acceptable units without a conversion
factor. If you use the imperial system you have two choices; use non
standard units or apply a conversion factor. The application of the
conversion factor in itself is a another error if the fraction part can't
be represented.
The english system may be OK for buying your groceries; but for complex
calculations; never.
"Julian V. Noble" wrote:
> A news story I just saw
>
> http://www.spacer.com/spacecast/news/mars-mco-99d.html
>
> states that the Mars Climate Orbiter spacecraft hit the Martian
> atmosphere because JPL was using metric units to describe the
> retro rockets, while Lockheed used English units--and the discrepancy
> slipped through the cracks.
>
> I would note that a proper user interface should be immune to
> such problems.
Not in a million years.
> Thus, the little program units.f given below
> automatically converts to/from the internal units of your computer.
>
<snip>
The liter isn't mentioned in my "physical formulas and tables" book, so
I suppose it's no longer different from a cubic decimeter. The SI units
are well defined except the kilogramm (which is defined as the "mass of
the international kilogram prototype", and unfortunately has a derived
unit, force). Fuck, how do I get that as an alien? If they wrote "the
mass of 6.022043e26/12 C_12 atoms and 6.022043e26/2 electrons aggregated
as diamond at 0 degrees celcius") one could regenerate that. The other
SI basic units all reduce to numbers.
>Does a cubic centimeter still equal 0.99997 milliliter, or have they
>fixed that by now?
It's fixed. A litre is a cubic decimeter. (And 1 Bar is 100kPa)
This solves a display problem for volume - I can use the same words to
display metric prefixes for volume as I can length or load. Area is a
real bugger though, the only metric unit being the Are, which is
offensively large.
What the world needs is a unit of area equal to 1 square metre, with a
sensible symbol (Sq perhaps?) so that I can display mSq and uSq etc.
(The prefix for 10E-6 is hereby redefined as 'u'.)
Cheers
--
Keith Wootten
I usually write it as 'ต'. Does that come through your newsreader?
[..]
>> (The prefix for 10E-6 is hereby redefined as 'u'.)
[..]
>I usually write it as 'µ'. Does that come through your newsreader?
Double-barrel comment: I hope both of you realize that 'µ' = 1e-6 :-)
-marcel
Oops. It seems that my '^' must have come through as a 'E' on your
newsreader :-)
My point was that 'µ' is often tricky, and 'u' is a widely accepted
alternative, certainly in electronics.
Cheers
--
Keith Wootten
>
>
> Double-barrel comment: I hope both of you realize that 'ต' = 1e-6 :-)
>
>
Last time I checked, 1e-6 was 1. Or am I missing something?
Howard Shapiro
: Last time I checked, 1e-6 was 1. Or am I missing something?
Yes. (x)E(n) is shorthand for x * 10^n. As any fule no.
Andrew.
The mind's eye imagined a decimal point! (I've been amusing myself
with the notion of a cm² as a µare. is a mm² 10 nares?)
Jerry
Too often, I think. I've seen too many programs - expensive ones at
that - that make that substitution unnecessarily.