Send mail to the CREATE web master
Index
Date: 97 May 01 5:58:17 am
From: "Andreas Raab" <raab@isg.cs.uni-magdeburg.de>
To: squeak@create.ucsb.edu
Subject: [Windows] Changes files
Hello Squeakers,
I have finally found the reason for the problems with the changes
files on Windows systems. When starting Squeak you have generally two
choices:
a) Double click the image. This works fine.
b) Drag the image onto the Squeak application.
The latter method has a very strange behaviour. Rather than using
the full name (i.e. squeak-1.XX.image) the 8.3 dos file name is used,
resulting in names like squeak~1.ima. The 1.19 version of squeak
looks for those strange names and tries to find an appropriate
changes file (such as squeak~1.cha), however, this can easily fail
because the 8.3 file name is stored separately.
The following sequence of operations will show what happens:
Initally we may have
squeak1-19.image dos name squeak~1.ima
squeak1-19.changes dos name squeak~1.cha
Now, we're copying the changes to a new name, say squeak1-19d.image
We have
squeak1-19.image dos name squeak~1.ima
squeak1-19.changes dos name squeak~1.cha
squeak1-19d.changes dos name squeak~2.cha
If the image is now MOVED to reflect the new version this results in
squeak1-19d.image dos name squeak~1.ima
squeak1-19.changes dos name squeak~1.cha
squeak1-19d.changes dos name squeak~2.cha
and, after deleting the old changes
squeak1-19d.image dos name squeak~1.ima
squeak1-19d.changes dos name squeak~2.cha
I'm right now hacking a function detecting the long file name for a
given dos file name (it's strange enough that there is a win32
function giving the dos version of the long file name but not the
other way around). Until then, I strongly recommend starting the
image by double-clicking.
Andreas
--
Linear algebra is your friend - Trigonometry is your enemy.
+===== Andreas Raab ============= (raab@isg.cs.uni-magdeburg.de) =====+
I Department of Simulation and Graphics Phone: +49 391 671 8065 I
I University of Magdeburg, Germany Fax: +49 391 671 1164 I
+=============< http://simsrv.cs.uni-magdeburg.de/~raab >=============+
Date: 97 May 01 7:33:14 am
From: "Andreas Raab" <raab@isg.cs.uni-magdeburg.de>
To: squeak@create.ucsb.edu
Subject: 1.19d and Windows
Hello Squeakers,
the updated VM for Windows is now ready. New or updated features
include:
* 32 bit color support now works
* TCP support in the network primitives
* Reduced cpu load during idle times (from 100% to < 5%)
Thanks to Blair McGlashan for pointing me to MsgWaitForMultipleObjects!
* Improved crash debug handling
(If the VM crashes a log containing some information about the
system will be written)
* Fixed problems with changes and sources
(In addition to finding the correct names you will be warned
if either changes or sources can't be found during startup)
* The sources are now searched in the startup directory and
the image directory.
As usual, the files can be found at
http://simsrv.cs.uni-magdeburg.de/~raab/squeak
ftp://ftp.cs.uni-magdeburg.de/pub/Smalltalk/free/squeak/win32
A final note to VM recompilers: I've decided NOT to put a makefile on
the server anymore because of the problems with different versions of
VC++. The file README in the image/1.19d/ directory of the above
contains information relevant for this.
Hope you'll like it,
Andreas
--
Linear algebra is your friend - Trigonometry is your enemy.
+===== Andreas Raab ============= (raab@isg.cs.uni-magdeburg.de) =====+
I Department of Simulation and Graphics Phone: +49 391 671 8065 I
I University of Magdeburg, Germany Fax: +49 391 671 1164 I
+=============< http://simsrv.cs.uni-magdeburg.de/~raab >=============+
Date: 97 May 01 8:44:48 am
From: Ranjan Bagchi <ranjan.bagchi@pobox.com>
To: Squeak <squeak@create.ucsb.edu>
Subject: Question of encapsulation..
Hi squeakers--
I'm curious if anyone's considered encapsulating the
squeak VM into a struct (or class, if anyone wants to
compile it under C++). By this I'd mean moving the
symbols from a number of globals into potentially just
one.
This would open up the possibility of having two separate
VM's running within the same application -- I don't know the system
issues that'll bring up -- I'm not going to claim to understand how the
exception-handling of the memory portion works, for instance, but
they're likely
solvable -- I hope.
Curious about people's opinions..
-rj
Date: 97 May 01 9:22:48 am
From: Paul Fernhout <kfsoft@netins.net>
To: Squeak <squeak@create.ucsb.edu>
Subject: Re: Question of encapsulation..
Ranjan Bagchi wrote:
> I'm curious if anyone's considered encapsulating the
> squeak VM into a struct (or class, if anyone wants to
> compile it under C++). By this I'd mean moving the
> symbols from a number of globals into potentially just
> one.
>
> This would open up the possibility of having two separate
> VM's running within the same application -- I don't know the system
> issues that'll bring up -- I'm not going to claim to understand how the
> exception-handling of the memory portion works, for instance, but
> they're likely
> solvable -- I hope.
The port to the Newton is going to require this since from what I have
been told the Newton C++ compiler does not allow globals. I am in the
process of acquiring the Newton C++ compiler and I plan to do some work
on this issue starting in a few weeks (after another project winds
down). I'd be happy to build on someone else's work if they have already
built such a structure.
I like your idea in general too for other reasons; it would be a way to
provide "sandboxes" for running downloadable Squeak applets.
-Paul Fernhout
Kurtz-Fernhout Software
kfsoft@netins.net
========================================
Download a public beta release of our garden simulator at:
http://www.gardenwithinsight.com
Date: 97 May 01 9:25:32 am
From: James McCartney <james@clyde.as.utexas.edu>
To: <squeak@create.ucsb.edu>
In-Reply-To: <3368BFD3.4FECC113@pobox.com>
Subject: Re: Question of encapsulation..
At 9:07 AM -0700 5/1/97, Ranjan Bagchi wrote:
>Hi squeakers--
>
>I'm curious if anyone's considered encapsulating the
>squeak VM into a struct (or class, if anyone wants to
>compile it under C++). By this I'd mean moving the
>symbols from a number of globals into potentially just
>one.
>
>This would open up the possibility of having two separate
>VM's running within the same application -- I don't know the system
>issues that'll bring up -- I'm not going to claim to understand how the
>exception-handling of the memory portion works, for instance, but
>they're likely
>solvable -- I hope.
The virtual machine I'm writing (not Squeak) allows multiple VMs. This
requires passing a pointer to a VM's globals to any implementation
routines that need them.
I decided on multiple VMs to support multiprocessing rather than
making VM threads = OS threads. The latter would have required
getting into really experimental territory to support real time
operation. I've only found one non blocking, real time, incremental,
multithreadable GC algorithm and it requires copying an object every
time it is written to as well as traversing a list in order to
access an object. So, not too good for high performance.
The question this leaves is inter-VM communication, which I'm going
to do with flattening/unflattening deep copies of objects, unless someone
has a better idea.
--- james mccartney james@clyde.as.utexas.edu james@lcsaudio.com
If you have a PowerMac check out SuperCollider, a real time synth program:
ftp://mirror.apple.com//mirrors/Info-Mac.Archive/gst/snd/super-collider-demo.hqx
Date: 97 May 02 2:47:44 pm
From: Jecel Assumpcao Jr <jecel@lsi.usp.br>
To: Maloney <johnm@wdi.disney.com>
Cc: squeak@create.ucsb.edu
Subject: benchmarks and license (was: InterpreterSimulation)
Maloney wrote:
> Did you try translating our benchmark into Self and timing it
> on the same machines? It would be interesting to know how it
> really compares (on this one benchmark, at least).
Good idea - I'll try it on Monday. Too bad I can't just
cut and paste between Squeak and Self (they don't seem
to be very X Window clipboard friendly...) because Mario's
Smalltalk would probably handle the code with no loss
of performance. Since I'll have to retype it anyway, I
might as well rewrite it in Self style.
> >[tinySelf 2 - persistent object store]
>
> Glphic CodeWorks uses such a scheme.
Neat! I never saw any details on their web site.
(http://www.glyphic.com/glyphic/codeworks/intro.html)
> >BTW, it might be interesting to use this memory system and
> >other parts of tinySelf with Squeak as well. Does releasing
> >code for Squeak place any kind of restriction on using the
> >same code in a commercial product?
>
> Nope. The license says you have to publish the source code of bug
> fixes and ports of the Squeak system, but not new apps built
> on top of Squeak. And you can always use it in commercial
> products without paying any royalties.
But all these things I am doing are changes to the VM,
not applications. I will always release all the sources
to my system (as I have been doing) and it will be freely
distributed. It is a commercial system, however, as I will
charge for its use.
-- Jecel
Date: 97 May 02 4:43:35 pm
From: lnotarfr@dc.uba.ar (Luciano Esteban Notarfrancesco)
To: squeak@create.ucsb.edu
Subject: changes, questions and suggestions
Hi Squeakers!
The folowing are some changes (bug fixes?) I made, and some questions
and suggestions:
1) Cursor could be implemented as subclass of MaskedForm instead of
Form... if every plataform supports that.
2) Set implements #= in 1.19d but they forgot to implement #hash, and the
same happens with SequenceableCollection. The message category for #=
and #hash was wrong in a couple of clases... it was 'testing' when it
should be 'comparing'.
3) I changed Dictionary>>collect: to return a Bag, as the Purple Book says,
and not an OrderedCollection. If this is wrong please tell me.
I added Dictionary>>includesAssociation:.
4) Bags don't implement #= (nor #hash) in 1.19d, so I fixed that too.
5) I changed Bag>>add:withOccurrences: extending it to negative values
of occurrences; probably this is wrong, but it resulted useful to me.
Tell me what do you think.
6) Evaluate:
#hola = 'hola'
it answers false... and now evaluate:
'hola' = #hola
it anwers true!
I think #hola = 'hola' should answer true too... but in such case we
should change also the hash method (both #hola and 'hola' should have
the same hash code). What do you think?
--- Luciano
The folowing are the changes:
'From Squeak 1.19d of April 13, 1997 on 2 May 1997 at 12:05:25 pm'!
!Bag reorganize!
('accessing' at: at:put: size sortedCounts sortedElements)
('testing' includes: occurrencesOf:)
('converting' asBag asSet)
('comparing' = hash)
('adding' add: add:withOccurrences:)
('removing' remove:ifAbsent:)
('enumerating' do:)
('private' contents setDictionary)
!
!Bag methodsFor: 'converting'!
asBag
self class == Bag ifFalse: [^super asBag]!
asSet
^contents keys "I assume there are no 0 values in the contents dictionary."! !
!Bag methodsFor: 'comparing'!
= aBag
| otherContents |
(aBag isKindOf: Bag) ifFalse: [^false].
contents size = (otherContents _ aBag contents) size ifFalse: [^false].
contents associationsDo: [ :assoc |
(otherContents at: assoc key ifAbsent: [^false]) = assoc value ifFalse: [^false]
].
^true!
hash
^self contents hash! !
!Bag methodsFor: 'adding'!
add: anObject withOccurrences: anInteger
"Add the element anObject to the receiver. Do so as though the element
were added anInteger number of times. Answer newObject.
Note: if anInteger is negative, anObject is removed 0-anInteger times."
| newCount |
newCount _ (contents at: anObject ifAbsent: [0]) + anInteger.
newCount = 0 ifTrue: [
contents removeKey: anObject ifAbsent: []
] ifFalse: [
newCount < 0
ifTrue: [self errorNotFound]
ifFalse: [contents at: anObject put: newCount]
].
^anObject! !
!Bag methodsFor: 'private'!
contents
^contents
! !
!SequenceableCollection methodsFor: 'comparing'!
hash
^self inject: 0 into: [ :hashValue :each | hashValue + each hash]! !
!Set reorganize!
('testing' includes: occurrencesOf:)
('comparing' = hash)
('adding' add:)
('removing' remove:ifAbsent:)
('enumerating' collect: do: doWithIndex:)
('private' array atNewIndex:put: copy findElementOrNil: fixCollisionsFrom: fullCheck grow growSize init: keyAt: noCheckAdd: rehash scanFor: size swap:with: withArray:)
('accessing' asArray someElement)
('objects from disk' readDataFrom:size:)
!
!Set methodsFor: 'comparing'!
hash
"Answer the hash code for the members of the set. Since order is
unimportant, we use a commutative operator to compute the hash value."
^self inject: self size into: [ :hashValue :each | hashValue + each hash]! !
!Dictionary methodsFor: 'testing'!
includesAssociation: anAssociation
^anAssociation value = (self associationAt: anAssociation key ifAbsent: [^false]) value! !
!Dictionary methodsFor: 'enumerating'!
collect: aBlock
"Evaluate aBlock with each of my values as the argument. Collect the
resulting values into a collection that is like me. Answer with the new
collection."
| newCollection |
newCollection _ Bag new: self size.
self do: [:each | newCollection add: (aBlock value: each)].
^ newCollection! !
Date: 97 May 03 7:02:52 pm
From: dave <drs@cs.wisc.edu>
To: squeak@create.ucsb.edu
Subject: How do I regenerate the VM source code?
Greetings Squeak Gurus,
How do I regenerate the VM source code, and is it possible to do this
such that the result is not inlined? Ideally I'd like to end up with
a bunch of small pieces I could individually test-bed. Maybe someone
has already done this?
Thanks very much in advance,
dave
[please mail replies, as I am not currently on the list]
drs@cs.wisc.edu
Date: 97 May 03 7:32:13 pm
From: Maloney <johnm@wdi.disney.com>
To: drs@cs.wisc.edu
Cc: squeak@create.ucsb.edu
In-Reply-To: <336BF3DC.75BB@cs.wisc.edu>
Subject: Re: How do I regenerate the VM source code?
>Greetings Squeak Gurus,
>
>How do I regenerate the VM source code, and is it possible to do this
>such that the result is not inlined? Ideally I'd like to end up with
>a bunch of small pieces I could individually test-bed. Maybe someone
>has already done this?
In a Squeak workspace, evaluate the following:
Interpreter translate: 'Interp.c' doInlining: false
If you look at the implementation of this method, you can also
figure out how to translate, say, just the object memory or
BitBlt or the interpreter.
-- John
Date: 97 May 04 7:46:24 am
From: Ranjan Bagchi <ranjan.bagchi@pobox.com>
To: squeak@create.ucsb.edu
Subject: Re: How do I regenerate the VM source code?
Maloney wrote:
> >Greetings Squeak Gurus,
> >
> >How do I regenerate the VM source code, and is it possible to do
> this
> >such that the result is not inlined? Ideally I'd like to end up
> with
> >a bunch of small pieces I could individually test-bed. Maybe
> someone
> >has already done this?
>
> In a Squeak workspace, evaluate the following:
>
> Interpreter translate: 'Interp.c' doInlining: false
>
> If you look at the implementation of this method, you can also
> figure out how to translate, say, just the object memory or
> BitBlt or the interpreter.
>
> -- John
I just did this for the first time yesterday (with inlining
on). Some notes:
*) It takes a long time to run.. on my P120/16M laptop it
ran for several hours. I'm not sure if its because it built up some
mongo data structures and the PC was paging,
or not, but it was surprising.. gave me plenty of time to
read old posting to the squeak mailing list, though.. :-)
*) The code that it produces doesn't have linefeeds.. this matters only
if you're running on a Windows box, I guess..
I'm going to stick my FilteringStream object in there so I don't have to
convert the source after the fact.
*) The produced code is identical (or at least was with
the inlined run I did yesterday) to that which produced squeak. Which
is the way it's supposed to be, but I still think it's cool that the
only thing that's different is the
timestamp and the lack of linefeeds.
*) The thing I'm playing with now -- The code it produces will utterly
fail to compile under C++. Mainly because K&R C doesn't have a problem
with the int-declared functions not returning anything -- I think the
default return is 0, but I need to check. I'm curious what people think
the issues would be in modifying the C-Generating classes to generate
good C++. The 'right thing' might be to have a bunch of the functions
which don't return anything declare themselves as void, but I suppose a
kludge would be to have them stick a 'return 0' line at the end of every
int-declared function. I'm not sure how this would effect code
generation -- certainly compiler-dependent, I'd guess.
By the way, what test-objects do people who've worked with the code
generator use to verify correctness? It'd certainly be useful if I only
needed to check a few pages of code and a run would take a few seconds
as opposed to
the time needed to regenerate the system.
Anyway.. thanks,
-rj
Date: 97 May 04 9:40:01 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: ranjan.bagchi@pobox.com, squeak@create.ucsb.edu
Subject: Re: How do I regenerate the VM source code?
> *) It takes a long time to run.. on my P120/16M laptop it
> ran for several hours.
It shouldn't take that long. On my 133MHz pentium laptop it takes less than
ten minutes.
Ian
Date: 97 May 04 10:07:20 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Ranjan Bagchi <ranjan.bagchi@pobox.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <336CA694.6934DAB0@pobox.com>
Subject: Re: How do I regenerate the VM source code?
>> In a Squeak workspace, evaluate the following:
>>
>> Interpreter translate: 'Interp.c' doInlining: false
>
>*) It takes a long time to run.. on my P120/16M laptop it
>ran for several hours. I'm not sure if its because it built up some
>mongo data structures and the PC was paging,
>or not, but it was surprising.. gave me plenty of time to
>read old posting to the squeak mailing list, though.. :-)
There's something really wrong with this. It runs on my Mac (8500/180) in=
56 seconds. With inlining it takes about 4 times as long. It does make up=
some data structures, but nothing truly mongo -- I think it will run to=
completion with only 2M of free space to begin with.
Date: 97 May 05 2:28:11 am
From: "Andreas Raab" <raab@isg.cs.uni-magdeburg.de>
To: Ranjan Bagchi <ranjan.bagchi@pobox.com>
Cc: squeak@create.ucsb.edu
Subject: Re: How do I regenerate the VM source code?
> I just did this for the first time yesterday (with inlining
> on). Some notes:
>
> *) It takes a long time to run.. on my P120/16M laptop it
> ran for several hours. I'm not sure if its because it built up some
> mongo data structures and the PC was paging,
> or not, but it was surprising.. gave me plenty of time to
> read old posting to the squeak mailing list, though.. :-)
It must not take that long. Even on my 486DX2/66 :-( at work it takes
not more than an hour. Perhaps you have a very low priority for
background processes. I've found that these settings are not very
suited for running active apps in the background.
> *) The code that it produces doesn't have linefeeds.. this matters only
> if you're running on a Windows box, I guess..
> I'm going to stick my FilteringStream object in there so I don't have to
> convert the source after the fact.
I've always used Ians cr2lf converter for this.
> *) The thing I'm playing with now -- The code it produces will utterly
> fail to compile under C++. Mainly because K&R C doesn't have a problem
> with the int-declared functions not returning anything -- I think the
Depends on your compiler. MS VC++ accepts this issuing a warning
about it (I've explicitly turned this off in the sq.h file).
> default return is 0, but I need to check. I'm curious what people think
> the issues would be in modifying the C-Generating classes to generate
> good C++.
What is "good C++" ? The idea - as far as I understand it - is to
have the complete VM written in Smalltalk and the generated C code to
be fast. Creating C++ classes (what I suspect you mean with good C++)
would probably introduce a significant overhead. However, I would
like the idea of merging the globals into a structure - this would
allow me to put the whole VM into a DLL and let several images being
run by the same VM.
Andreas
--
Linear algebra is your friend - Trigonometry is your enemy.
+===== Andreas Raab ============= (raab@isg.cs.uni-magdeburg.de) =====+
I Department of Simulation and Graphics Phone: +49 391 671 8065 I
I University of Magdeburg, Germany Fax: +49 391 671 1164 I
+=============< http://simsrv.cs.uni-magdeburg.de/~raab >=============+
Date: 97 May 05 2:52:21 am
From: Hans-Martin Mosner <hm.mosner@cww.de>
To: Squeak Mailing List <squeak@create.ucsb.edu>
Subject: Block Closures - state of affairs
Hi Squeakers,
my Block closure efforts are getting somewhere. I've succeeded to
compile blocks with closure semantics and execute them. The compiler
changes are not complete yet, but the initial ideas work out quite well.
I did not yet do anything on the debugger and decompiler, and I'm not
absolutely sure whether the C translator will work with the compiler
changes (but I think it should).
Here's how my code currently works:
A new class 'Block' represents block closures. Blocks have 2 instance
variables:
method <CompiledMethod> the method executed by the block
home <MethodContext> the context in which the block is defined, may
be nil for clean blocks
Block temporaries are possible, and block args are handles just like
method args now. The interpreter changes are very moderate: only the
#primitiveValue and #primitivaValueWithArguments methods are
significantly modified, and there are 2 additional class vars for the
inst var indices of the 2 Block variables.
Like the VisualWorks BlockClosure, a Block is the receiver in the
context of its method. Accesses to self, inst vars and outer temporaries
or arguments are done with messages sent to the Block. (At the moment,
accesses to outer temps are not yet implemented).
The #blockCopy: mechanism is not used for creation, instead a message
#newBlock: is sent to the block's method, with the containing context as
parameter (#newBlock without a parameter is sent for clean blocks).
Similarly, the block return is replaced by a normal message return.
Method returns from blocks are not yet implemented, but will be done
using messages sent to the Block.
The class BlockContext will be completely obsoleted, as the block
method's activations are normal MethodContexts.
I did not yet look where in the bytecode set instructions to access
outer temps etc. could fit. My gut feeling is that this should be
decided really late, when the whole mechanism works nicely with message
sends.
My current transition plan is as follows:
1. Create a VM which can handle old blocks as well as new blocks (mostly
done)
2. Change the image to use only new blocks.
3. Create a VM that can handle only new blocks (cleaning up any residues
of the old BlockContext stuff)
4. Clean up the image to remove any references to old block stuff.
5. Streamline image and VM with bytecodes for outer variable access etc.
and change the SpecialObjects and SpecialSelectors to account for the
removal of old blocks.
It will take quite some weeks as I can only do it in scarce free time...
If someone is willing to invest some work into the debugger and/or
decompiler to understand new blocks I would be very grateful.
I have not yet decided whether I should make the current
work-in-progress available to other developers, as it is quite
incomplete. Maybe at the end of this week...
So long,
Hans-Martin
Date: 97 May 05 2:51:46 am
From: Hans-Martin Mosner <hm.mosner@cww.de>
To: Squeak Mailing List <squeak@create.ucsb.edu>
Subject: Block Closures - state of affairs
Hi Squeakers,
my Block closure efforts are getting somewhere. I've succeeded to
compile blocks with closure semantics and execute them. The compiler
changes are not complete yet, but the initial ideas work out quite well.
I did not yet do anything on the debugger and decompiler, and I'm not
absolutely sure whether the C translator will work with the compiler
changes (but I think it should).
Here's how my code currently works:
A new class 'Block' represents block closures. Blocks have 2 instance
variables:
method <CompiledMethod> the method executed by the block
home <MethodContext> the context in which the block is defined, may
be nil for clean blocks
Block temporaries are possible, and block args are handles just like
method args now. The interpreter changes are very moderate: only the
#primitiveValue and #primitivaValueWithArguments methods are
significantly modified, and there are 2 additional class vars for the
inst var indices of the 2 Block variables.
Like the VisualWorks BlockClosure, a Block is the receiver in the
context of its method. Accesses to self, inst vars and outer temporaries
or arguments are done with messages sent to the Block. (At the moment,
accesses to outer temps are not yet implemented).
The #blockCopy: mechanism is not used for creation, instead a message
#newBlock: is sent to the block's method, with the containing context as
parameter (#newBlock without a parameter is sent for clean blocks).
Similarly, the block return is replaced by a normal message return.
Method returns from blocks are not yet implemented, but will be done
using messages sent to the Block.
The class BlockContext will be completely obsoleted, as the block
method's activations are normal MethodContexts.
I did not yet look where in the bytecode set instructions to access
outer temps etc. could fit. My gut feeling is that this should be
decided really late, when the whole mechanism works nicely with message
sends.
My current transition plan is as follows:
1. Create a VM which can handle old blocks as well as new blocks (mostly
done)
2. Change the image to use only new blocks.
3. Create a VM that can handle only new blocks (cleaning up any residues
of the old BlockContext stuff)
4. Clean up the image to remove any references to old block stuff.
5. Streamline image and VM with bytecodes for outer variable access etc.
and change the SpecialObjects and SpecialSelectors to account for the
removal of old blocks.
It will take quite some weeks as I can only do it in scarce free time...
If someone is willing to invest some work into the debugger and/or
decompiler to understand new blocks I would be very grateful.
I have not yet decided whether I should make the current
work-in-progress available to other developers, as it is quite
incomplete. Maybe at the end of this week...
So long,
Hans-Martin
Date: 97 May 05 7:15:10 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Dan Ingalls <DanI@wdi.disney.com>
Cc: Ranjan Bagchi <ranjan.bagchi@pobox.com>, Squeak@create.ucsb.edu
In-Reply-To: <v03007803af9286bc47fa@[206.16.10.79]>
Subject: Re: How do I regenerate the VM source code?
At 14:38 -0400 5/4/97, Dan Ingalls wrote:
>>> In a Squeak workspace, evaluate the following:
>>>
>>> Interpreter translate: 'Interp.c' doInlining: false
>>
>>*) It takes a long time to run.. on my P120/16M laptop it
>>ran for several hours. I'm not sure if its because it built up some
>>mongo data structures and the PC was paging,
>>or not, but it was surprising.. gave me plenty of time to
>>read old posting to the squeak mailing list, though.. :-)
>
>There's something really wrong with this. It runs on my Mac (8500/180) in
>56 seconds. With inlining it takes about 4 times as long. It does make
>up some data structures, but nothing truly mongo -- I think it will run to
>completion with only 2M of free space to begin with.
On my 9500/200 using 1.19d it takes about the same:
Time millisecondsToRun: [
Interpreter translate: 'Interp.c' doInlining: false ]
48333
I give Squeak 15Megs though.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 05 8:43:56 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: lnotarfr@dc.uba.ar (Luciano Esteban Notarfrancesco)
Cc: squeak@create.ucsb.edu
In-Reply-To: <m0wNHP7-000j1fC@milagro.dc.uba.ar>
Subject: Re: changes, questions and suggestions
At 8:25 -0400 5/2/97, Luciano Esteban Notarfrancesco wrote:
>Hi Squeakers!
>
>The folowing are some changes (bug fixes?) I made, and some questions
>and suggestions:
>
>...SNIP...
>
>!Bag methodsFor: 'converting'!
>asBag
> self class == Bag ifFalse: [^super asBag]!
Hi:
I just skimmed your post but did note one thing. (I hope I'm not missing
something obvious here :-).
One doesn't typically test for class equality and this particular test is
present just to force Bag to answer self, but let any potential future
subclasses have access to the Bag superclass method of the same name. Since
there are no Bag subclasses, it seems odd to assume that they will be ill
designed and require such coding to work properly.
asBag in Bag should simply be (but see below):
asBag
^ self
If potential future subclasses need to invoke the asBag in Bags parent,
then they are ill designed (ie, in the wrong place).
I admit that a similar situation does exist with Set, but then the
subclasses of Set may well not belong where they are.
Another issue, often ignored in other implementations, is whether an asZot
method should sometimes answer the receiver and sometimes answer a
different collection, making it hard to know if a copy is needed to get a
fresh copy or if one already has a fresh copy.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 05 10:14:39 am
From: Ranjan Bagchi <ranjan.bagchi@pobox.com>
To: Ian Piumarta <piumarta@prof.inria.fr>, Dan Ingalls <DanI@wdi.disney.com>,
"\"David N. Smith\"" <dnsmith@watson.ibm.com>,
Andreas Raab <raab@isgnw.cs.Uni-Magdeburg.DE>
Cc: Squeak <squeak@create.ucsb.edu>
Subject: Performance numbers
Hi --
As everyone's pointed off, my report of several hours to generate an
inlined source file is way out of line with everyone's experiences.. I
ran it again, this time with
only Squeak running, and I came across numbers roughly in line with
others -- about 4 and a half minutes to produced noninlined source, and
about 4x that for inlining.
I'm not sure what caused the slowdown I reported.. I was running a debug
build of 1-19d in VC++ which could do it, and I was running it in the
background under windows with Netscape's mail reader in the foreground..
I only have 16 megs in here, so it certainly could have been paging
wildly..
Hopefully I didn't cause anyone trouble with that report..
-rj
Date: 97 May 05 11:29:02 am
From: gregory@eng.adaptec.com (Greg Gritton x2386)
To: squeak@create.ucsb.edu
Cc: gregory@eng.adaptec.com
Subject: Accessing source code in 1.18
Hi,
I am running the Suqeak version 1.18, using the distribution in
ftp://ftp.create.ucsb.edu/pub/Smalltalk/Squeak/unix/
using the image and source files from the Squeak-1.18 subdirectory
and the precompiled VM from precompiled/SqueakVM-1.18-i581-linux1.2
and precompiled/SqueakVM-1.18-sparc-sunos4.1. I have not modified
any of the files.
I placed all of the files in the same directory. My directory
listing looks like:
InterpTest.c Squeak1.18.changes.txt sq.h
InterpTestInline.c SqueakV1.sources sqFilePrims.c
Makefile SqueakV1.sources.txt sqSoundPrims.c
Makefile.dec SqueakVM-1.18-i586-linux1.2 sqUnixConfig.h
Makefile.linux SqueakVM-1.18-sparc-sunos4.1* sqUnixDirectory.c
Makefile.orig clone.image sqUnixJoystick.c
Makefile.sun cr2lf* sqUnixSound.c
Squeak1.18.changes lf2cr* sqXWindow.c
Unfortunately, when I am looking at the source code in the class
browser, the correct source for many of the methods, such as
"Squeak Interpreter / ObjectMemory / interpreter access / fetchClassOf:"
is not found. Instead it regenerates the source, using argument
and temporary names such as t1 and t2.
On the other hands, it does find the source for many methods, such as:
"Collections-Sequenceable / OrderedCollection / accessing / after:"
The source for the methods does exist. I can find it manually
in the Squeak1.18.changes.txt (.txt is after running cr2lf) file.
Has anyone else experienced this problem or know of the solution?
Greg Gritton
Date: 97 May 05 12:50:04 pm
From: Tim Rowledge <rowledge@interval.com>
To: Squeak mailinglist <squeak@create.ucsb.edu>
Subject: 32bpp Forms problem on PC
I've read of some problems with using 32bpp Forms on the PC, where the form comes out all-black. There is no problem on the Mac or Acorn. Andreas suggested explicitly checking for pixeldepth == 32, and indeed it seems to work. I was puzzl
ed though, since it looked like his fix code was redundant.
It turns out that the culprit is a piece of C code that reads
mask = (1 << pixeldepth) -1;
which in the case of pixeldepth == 32, we would reasonably expect to
result in mask == -1 . Sadly, on an x86, the shift of 1 by 32 places
results in >1< not 0! Thus our mask is set to 0 and the form is
displayed in black.
Wrapping the fix in a suitable macro might be worth doing, since
other machines would only be wasting time on the check. If anyone
feels like changing the code, it would probably be worth altering the
sourcePixMask _ (1 bitShift: .....
to
sourcePixMask _ (1 << ....
and avoid a bit more wasted work.
tim
--
Tim Rowledge: rowledge@interval.com (w) +1 (415) 856-7230 (w)
tim@sumeru.stanford.edu (h) <http://sumeru.stanford.edu/tim>
Date: 97 May 06 9:55:01 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Jean Francois Veillette <jfv@hasc.com>
Cc: Squeak@create.ucsb.edu
Subject: Port to NeXTSTEP 3.3 / OPENSTEP 4.1, 4.2 / RHAPSODY
M. Veillette -
At this time, the core Squeak team is not working on a NextStep port. =
However a number of other people are developing Squeak, and I will post=
this reply to the more active Squeak mailing list so that others with a=
similar interest may contact you. Glad to hear you are enjoying Squeak.
- Dan Ingalls
-----------------------------------------
>From: Jean Francois Veillette <jfv@hasc.com>
>Date: Mon, 5 May 1997 17:59:36 -0400
>To: squeak@research.apple.com
>Subject: Port to NeXTSTEP 3.3 / OPENSTEP 4.1, 4.2 / RHAPSODY
>
>
>As a NEXTSTEP/OPENSTEP user, I would like to know if your team plan to port
>Squeak on NEXTSTEP/OPENSTEP/RHAPSODY (all of them, or just one of them). =
If not your team
>,
>do you know some porting efforts on thoses platform, and how to contact=
them ?
>
>I currently use the Linux port and I'm very happy with it ! Except the=
fact that I would prefer it to run on my NeXTSTation.
>
>You made a verry great job ! Continue you good work !
>
>Thank's !
>
>- jfv
>Jean-Francois Veillette
>Sherbrooke, Quebec, Canada
>jfv@hasc.com
Date: 97 May 06 9:31:57 pm
From: dave <drs@cs.wisc.edu>
To: squeak@create.ucsb.edu
Subject: Some Undeclared ID's in the Non-inlined Output of the Code Generator
Greetings fellow Squeaks,
With Inlining turned off, the C Code Generator outputs code
for the Interpreter that contains a few undeclared variables,
and this prevents recompilation. The other two portions (
the ObjectMemory and the BitBlitter) compile like champs.
This is a partial list of the pseudo-code ids:
SmallContextSize
LargeContextSize
ClassString
ClassBlockContext
ClassMethodContext
SpecialSelectors
Some of them seem to be fairly straightforward substitutions:
contextEnd = newContext + SmallContextSize;
becomes:
contextEnd = newContext + 76;
Others are more complex, and this is where my problem lies, e.g.,
success((rcvrClass == (splObj(ClassBlockContext)))
|| (rcvrClass == (splObj(ClassMethodContext))));
this appears to expand to:
l25:
/* begin success: */
t4 = (t2 == (longAt((specialObjectsOop + 4) +
(11 * 4)))) || (t2 == (longAt((specialObjectsOop + 4) +
(10 * 4))));
"specialObjectsOop" is an integer that appears only in the Inlined
version. "t2" and "t4" are internal variables in the inlined
interpret() function.
Anyway, my question is how to safely substitute these identifiers in
the non-inlined code with something that works. Hopefully it's
fairly trivial... ;-) But of course it probably isn't.
Best Regards,
dave
Date: 97 May 07 9:49:10 am
From: Maloney <johnm@wdi.disney.com>
To: drs@cs.wisc.edu
Cc: squeak@create.ucsb.edu
In-Reply-To: <33700B3A.450D@cs.wisc.edu>
Subject: Re: Some Undeclared ID's in the Non-inlined Output of the Code
Generator
--============_-1349093429==_============
Content-Type: text/plain; charset="us-ascii"
Dave,
Re:
With Inlining turned off, the C Code Generator outputs code
for the Interpreter that contains a few undeclared variables,
and this prevents recompilation. The other two portions (
the ObjectMemory and the BitBlitter) compile like champs.
Note: This is really a problem with translating the code for the
modules of the VM separately, not with generating non-inlined code.
The problem is just that the Interpreter depends on some of the
constants (represented as class variables in Smalltalk)
defined in the ObjectMemory. I'm enclosing two methods that
allow you to file out just the interpreter.
You'll also need to make up a header file with all the function
prototypes included in the full translation plus the following
imported variable declarations:
/*** Imported Variables ***/
extern int endOfMemory;
extern int falseObj;
extern int freeBlock;
extern int freeLargeContexts;
extern int freeSmallContexts;
extern int interruptCheckCounter;
extern int lastHash;
extern int lowSpaceThreshold;
extern unsigned char *memory;
extern int memoryLimit;
extern int nilObj;
extern int remapBuffer[26];
extern int remapBufferCount;
extern int signalLowSpace;
extern int specialObjectsOop;
extern int trueObj;
extern int youngStart;
By doing this, I was able to get a clean compile of the Interpreter as
a separate module.
Good luck!
-- John
--============_-1349093429==_============
Content-Type: multipart/appledouble; boundary="============_-1349093429==_D============"
--============_-1349093429==_D============
Content-Transfer-Encoding: base64
Content-Type: application/applefile; name="%SeparateInterpTranslation.cs"
Content-Disposition: attachment; filename="%SeparateInterpTranslation.cs"
AAUWBwACAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAADAAAAMgAAABwAAAAJAAAATgAAACBT
ZXBhcmF0ZUludGVycFRyYW5zbGF0aW9uLmNzVEVYVFIqY2gBAAEMA0iAEAAAAAAAAAAA
AAAAAAAAAAA=
--============_-1349093429==_D============
Content-Type: text/plain; name="SeparateInterpTranslation.cs"; charset="us-ascii"
Content-Disposition: attachment; filename="SeparateInterpTranslation.cs"
'From Squeak 1.19d of April 13, 1997 on 7 May 1997 at 10:07:02 am'!
!CCodeGenerator methodsFor: 'public'!
addConstantsOfClass: aClass
"Add the constants variables of the given class to the code base."
self checkClassForNameConflicts: aClass.
aClass classPool associationsDo: [ :assoc |
constants at: assoc key put: (TConstantNode new setValue: assoc value)].
! !
!Interpreter class methodsFor: 'translation'!
translateInterpreterOnly: fileName doInlining: inlineFlag
"Time millisecondsToRun: [
Interpreter translateInterpreterOnly: 'InterpTest.c' doInlining: false.
Smalltalk beep]"
| cg |
BitBltSimulation initialize.
Interpreter initialize.
ObjectMemory initialize.
cg _ CCodeGenerator new initialize.
cg addClass: Interpreter.
Interpreter declareCVarsIn: cg.
cg addConstantsOfClass: BitBltSimulation.
cg addConstantsOfClass: ObjectMemory.
cg storeCodeOnFile: fileName doInlining: inlineFlag.
! !
--============_-1349093429==_D============--
--============_-1349093429==_============--
Date: 97 May 07 10:56:27 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Float bug in Squeak
All float fans:
On my PPC I get these strange results; the first two are OK, but then
things get very odd, with various bizare values of zero:
13r0.0e0 0.0
14r0.0e0 0.0
15r0.0e0 0.0622222222222223
16r0.0e0 0.0546875
17r0.0e0 0.0484429065743945
These don't work too well either:
16r1.0e0 1.0546875
16r1.0e1 1.054931640625
16r1.0e2 1.05517578125
16r1.0e3 1.055419921875
and even odder, these seem to work:
13r1.0e0 1.0
13r1.0e1 13.0
13r1.0e10 1.37858491849e11
"1.0 * (13 raisedToInteger: 10) = 1.37858491849e11"
10r1.0e10 9.99999999999997e9
It turns out that Squeak neither supports exponents in floats with a radix
specification greater than 14 (oddly that's the digit value of $e) nor does
it seem to issue an error message in these cases.
But, note that in
Float>>printOn: aStream base: base
there is the code:
digitCount := 2r1.0e52
2r1.0e52 evaluates to: 4.50359962737047e15
and:
2r1.0e52 printHex evaluates to:'1.0000000000000e34'
which is correct since the 34 is in hex and is 50 in decimal. (printHex is
not a part of the Squeak image.) Thus it is intended to work and is not
accidental that it does.
So, we have a sometimes it works, sometimes it doesn't situation.
The code in question is Number>>readFrom:, and its friends in Number and
Integer (and maybe other Number classes).
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 07 11:18:41 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: asFraction is cute but broken (LONG MESSAGE)
All floating point fans:
The asFraction method in Squeak tries to answer a 'cute' answer rather than
a 'correct' one. It is slow and relatively useless.
Float pi asFraction
answers:
(355/113)
and:
(355/113) asFloat
answers:
3.14159292035398
BUT:
Float pi
answers:
3.14159265358979
which differs from the fractional version after the 5th digit. Not too cute.
Now try:
0.12345678901234567890e-100 asFraction
Go get coffee.
After a while, on my PPC where Squeak has 15 megs, it runs out of memory.
I find these kinds of answers (wrong and none) to be completely
unsatisfactory. I suggest that asFraction be dropped (or renamed
asApproximateFraction) and that a proper asFraction method be substituted.
It is hard to do one in Smalltalk using portable floating point operations.
Here is one that makes an assumption about byte ordering and that runs on
my PPC. To run it on other platforms it may be necessary to reorder the
bytes in shifty; the rest should work.
asTrueFraction
" Answer a fraction that EXACTLY represents self,
a double precision IEEE floating point number.
(It tears an IEEE float into its components; it
assumes 'correct' byte ordering; runs on PPC.) "
| shifty sign exp fraction |
shifty := ((self at: 1) bitShift: 32) bitOr: (self at: 2).
sign := (shifty bitShift: -63) = 0 ifTrue: [1] ifFalse: [-1].
exp := (shifty >> 52) bitAnd: 16r7FF.
fraction := shifty bitAnd: 16r000FFFFFFFFFFFFF.
(exp = 0) & (fraction = 0) ifTrue: [ ^ 0 ].
fraction := fraction bitOr: 16r0010000000000000.
exp := exp - 16r3FF.
" Validate that the dismemberment was correct "
(sign * fraction / (2 raisedToInteger: 52 - exp)) asFloat = self
ifFalse: [self error: 'asFraction validation failed' ].
^ sign * fraction / (2 raisedToInteger: 52 - exp)
It basically tears apart an IEEE float (and rebuilds it as a validation
test), and then (last line) answers a fraction which exactly represents the
float. The validation test can be removed with a non-trivial improvement in
performance.
The code should either test for endiness and reverse the bytes, or it
should be implemented as a primitive. The later solution would allow ports
to non-IEEE hardware without breaking (though there are other places in
Float that make an assumption of IEEEness.)
Float pi asTrueFraction
answers:
(884279719003555/281474976710656)
That, converted using asFloat, answers:
3.14159265358979
which is exactly the answer from Float pi.
Then:
0.12345678901234567890e-100 asTrueFraction
does not run out of memory, but answers:
(7783112265042257/63043209914231166739646464160229782088...snip...)
with a very long denominator; the result, converted with asFloat, answers:
1.23456789012349e-101
Note that:
0.12345678901234567890e-100
evaluates to the same result:
1.23456789012349e-101
========================================================================
Here are two longer tests, with their results:
" A test using all digits in a double float "
| x n |
x := 0.1234567890123456789e11.
n := 10.
30 timesRepeat: [
Transcript cr; show: n printString, ' ', x printString, ' ',
x asTrueFraction printString, ' ', x asTrueFraction asFloat
printString.
x := x / 10.
n := n - 1. ].
10 1.23456789012345e10 (6472691299770469/524288) 1.23456789012345e10
9 1.23456789012345e9 (5178153039816375/4194304) 1.23456789012345e9
8 1.23456789012345e8 (1035630607963275/8388608) 1.23456789012345e8
7 1.23456789012346e7 (207126121592655/16777216) 1.23456789012346e7
6 1.23456789012346e6 (41425224318531/33554432) 1.23456789012346e6
5 123456.789012345 (8483885940435149/68719476736) 123456.789012345
4 12345.6789012346 (6787108752348119/549755813888) 12345.6789012346
3 1234.56789012346 (5429687001878495/4398046511104) 1234.56789012346
2 123.456789012346 (1085937400375699/8796093022208) 123.456789012346
1 12.3456789012346 (3474999681202237/281474976710656) 12.3456789012346
0 1.23456789012346 (5559999489923579/4503599627370496) 1.23456789012346
-1 0.123456789012346 (4447999591938863/36028797018963968) 0.123456789012346
-2 0.0123456789012346 (7116799347102181/576460752303423488) 0.0123456789012346
-3 0.00123456789012346 (5693439477681745/4611686018427387904)
0.00123456789012346
-4 1.23456789012346e-4 (1138687895536349/9223372036854775808)
1.23456789012346e-4
-5 1.23456789012346e-5 (3643801265716317/295147905179352825856)
1.23456789012346e-5
-6 1.23456789012346e-6 (5830082025146107/4722366482869645213696)
1.23456789012346e-6
-7 1.23456789012346e-7 (2332032810058443/18889465931478580854784)
1.23456789012346e-7
-8 1.23456789012346e-8 (3731252496093509/302231454903657293676544)
1.23456789012346e-8
-9 1.23456789012346e-9 (2985001996874807/2417851639229258349412352)
1.23456789012346e-9
-10 1.23456789012346e-10 (4776003194999691/38685626227668133590597632)
1.23456789012346e-10
-11 1.23456789012346e-11 (3820802555999753/309485009821345068724781056)
1.23456789012346e-11
-12 1.23456789012346e-12 (6113284089599605/4951760157141521099596496896)
1.23456789012346e-12
-13 1.23456789012346e-13 (1222656817919921/9903520314283042199192993792)
1.23456789012346e-13
-14 1.23456789012346e-14 (3912501817343747/316912650057057350374175801344)
1.23456789012346e-14
-15 1.23456789012346e-15 (6260002907749995/5070602400912917605986812821504)
1.23456789012346e-15
-16 1.23456789012346e-16
(1252000581549999/10141204801825835211973625643008) 1.23456789012346e-16
-17 1.23456789012346e-17
(4006401860959997/324518553658426726783156020576256) 1.23456789012346e-17
-18 1.23456789012346e-18
(6410242977535995/5192296858534827628530496329220096) 1.23456789012346e-18
-19 1.23456789012346e-19
(1282048595507199/10384593717069655257060992658440192) 1.23456789012346e-19
" a test of '1' to various exponents "
| x n |
x := 0.1e11.
n := 10.
30 timesRepeat: [
Transcript cr; show: n printString, ' ', x printString, ' ', x
asTrueFraction printString,
' ', x asTrueFraction asFloat printString.
x := x / 10.
n := n - 1. ].
10 9.99999999999997e9 10000000000 9.99999999999997e9
9 9.99999999999998e8 1000000000 9.99999999999998e8
8 1.0e8 100000000 1.0e8
7 9.99999999999999e6 10000000 9.99999999999999e6
6 999999.999999998 1000000 999999.999999998
5 99999.9999999999 100000 99999.9999999999
4 10000.0 10000 10000.0
3 1000.0 1000 1000.0
2 100.0 100 100.0
1 10.0 10 10.0
0 1.0 1 1.0
-1 0.1 (3602879701896397/36028797018963968) 0.1
-2 0.01 (5764607523034235/576460752303423488) 0.01
-3 0.001 (1152921504606847/1152921504606846976) 0.001
-4 1.0e-4 (7378697629483821/73786976294838206464) 1.0e-4
-5 1.0e-5 (5902958103587057/590295810358705651712) 1.0e-5
-6 1.0e-6 (2361183241434823/2361183241434822606848) 1.0e-6
-7 1.0e-7 (3777893186295717/37778931862957161709568) 1.0e-7
-8 1.0e-8 (6044629098073147/604462909807314587353088) 1.0e-8
-9 1.0e-9 (2417851639229259/2417851639229258349412352) 1.0e-9
-10 1.0e-10 (7737125245533629/77371252455336267181195264) 1.0e-10
-11 1.0e-11 (6189700196426903/618970019642690137449562112) 1.0e-11
-12 1.0e-12 (2475880078570761/2475880078570760549798248448) 1.0e-12
-13 1.0e-13 (7922816251426435/79228162514264337593543950336) 1.0e-13
-14 1.0e-14 (1584563250285287/158456325028528675187087900672) 1.0e-14
-15 1.0e-15 (2535301200456459/2535301200456458802993406410752) 1.0e-15
-16 1.0e-16 (8112963841460669/81129638414606681695789005144064) 1.0e-16
-17 1.0e-17 (6490371073168535/649037107316853453566312041152512) 1.0e-17
-18 1.00000000000001e-18
(1298074214633707/1298074214633706907132624082305024) 1.00000000000001e-18
-19 1.0e-19 (8307674973655725/83076749736557242056487941267521536) 1.0e-19
=== END ===
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 07 4:18:34 pm
From: tim <tim@apple.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>, <squeak@create.ucsb.edu>
Subject: Re: Float bug in Squeak
David N. Smith wrote:
>It turns out that Squeak neither supports exponents in floats with a radix
>specification greater than 14 (oddly that's the digit value of $e) nor does
>it seem to issue an error message in these cases.
Allowing both an exponent specification (signified with 'e') and radices
that can use 'e' as a digit leads to ambiguous literal numbers (e.g.
15r1a.10e06 -> 15r [1a.10e06] -> 25.07082
-> 15r [1a.10] e06 -> 25.06 x 15^6 = 285449062.50
The problem is isolated in:
!Number class methodsFor: 'instance creation'!
readRemainderOf: integerPart from: aStream base: base
"Read optional fractional part and exponent, and return the final result"
| value fraction fracpos |
value _ integerPart.
(aStream peekFor: $.)
ifTrue:
["<integer>.<fraction>"
(aStream atEnd not and:
[aStream peek digitValue between: 0 and: base - 1])
"*** ^^^^^^^^ this could be
'e'"
ifTrue:
[fracpos _ aStream position.
fraction _ Integer readFrom: aStream base: base.
fraction _
fraction asFloat / (base raisedTo: aStream position - fracpos).
value _ value asFloat + (value < 0
ifTrue: [fraction negated]
ifFalse: [fraction])]
ifFalse:
["oops - just <integer>."
aStream skip: -1. "un-gobble the period"
^ value
"Number readFrom: '3r-22.2'"]].
(aStream peekFor: $e)
"*** ^^ also comparing for 'e'"
ifTrue:
["<integer>e<exponent>"
^ value * (base raisedTo: (Integer readFrom: aStream))].
^ value! !
Ada is the only other language I know of that supports literal numbers in
scientific notation with arbitrary radices; it does so by requiring that
the significand be *enclosed* in special characters (in this case, the
'#' character), rather than just prefixed by one (as in Squeak):
10 -- an integer literal
10.0 -- a real literal
1E3 -- an integer literal of value 1000
1.5E2 -- a real literal of value 150.0
2#1111_1111# -- an integer literal of value 255
2#1#E8 -- an integer literal of value 256
2#1.1111_1111_111#E11 -- a real literal of value 4095.0
This forces a separation of the significand from the exponent, to allow
unambiguous parsing.
Unfortunately we cannot reuse Squeak's 'r' (used to separate the radix
from the significand) to separate the significand from the exponent, as
'r' is a legal digit for radices > 27.
-- tim
Date: 97 May 08 10:13:25 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: tim <tim@apple.com>
Cc: <squeak@create.ucsb.edu>
In-Reply-To: <199705072345.QAA15134@scv1.apple.com>
Subject: Re: Float bug in Squeak
At 19:43 -0400 5/7/97, tim wrote:
>David N. Smith wrote:
>
>>It turns out that Squeak neither supports exponents in floats with a radix
>>specification greater than 14 (oddly that's the digit value of $e) nor does
>>it seem to issue an error message in these cases.
>
>Allowing both an exponent specification (signified with 'e') and radices
>that can use 'e' as a digit leads to ambiguous literal numbers (e.g.
>
> 15r1a.10e06 -> 15r [1a.10e06] -> 25.07082
> -> 15r [1a.10] e06 -> 25.06 x 15^6 = 285449062.50
> -- tim
Tim:
IBM Smalltalk almost gets it right:
16r1.0e2 -> 100.0
16r1.0E2 -> 1.05517578125
The rule is that all hex digits are uppercase and the 'r' and 'e' are
always lower. However, all exponents are always decimal and one cannot
write:
16r1.0e16r10
to get around that. Bummer. But at least it doesn't try to have it both ways!
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 08 3:50:43 pm
From: Ian Piumarta <piumarta@prof.inria.fr>
To: ranjan.bagchi@pobox.com, squeak@create.ucsb.edu
Subject: Re: How do I regenerate the VM source code?
A note for Unix Squeak users: in the 1.17 VM there was an "undocumented"
option "-lazy" which put Squeak "to sleep" when the window was unmapped
(iconified, on an undisplayed workspace, etc...). In 1.18 I somewhat
rashly made it the default, so beware of unmapping the window while
Squeak is busy doing something interesting. In the 1.19 VM I've put the
option back and made the default be "run all the time". (And now I find
I almost always kill Squeak moments after starting it, because I forgot
to use the option. ;-)
If you want to disable this in your 1.18 VM, find the case in the event
loop for "StructureNotify" (which sits in a loop calling XNextEvent until
a "MapNotify" arrives). Commenting out this case, and then recompiling,
will disable the "feature".
Just in case anyone has managed this long without discovering them, there
are two other options too:
-display <dpy> - does the obvious thing
-memory <num>[mk] - allocate num mega/kilobytes of object memory
Regards,
Ian
------------------------------- projet SOR -------------------------------
Ian Piumarta, INRIA Rocquencourt, Internet: Ian.Piumarta@inria.fr
BP105, 78153 Le Chesnay Cedex, FRANCE Voice: +33 1 39 63 52 87
----------------------- Systemes a Objets Repartis -----------------------
Date: 97 May 09 9:26:48 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: gregory@eng.adaptec.com
Cc: squeak@create.ucsb.edu
Subject: Re: Accessing source code in 1.18
Greg,
> I placed all of the files in the same directory. My directory
> listing looks like:
>
> InterpTest.c Squeak1.18.changes.txt sq.h
> InterpTestInline.c SqueakV1.sources sqFilePrims.c
> Makefile SqueakV1.sources.txt sqSoundPrims.c
> Makefile.dec SqueakVM-1.18-i586-linux1.2 sqUnixConfig.h
> Makefile.linux SqueakVM-1.18-sparc-sunos4.1* sqUnixDirectory.c
> Makefile.orig clone.image sqUnixJoystick.c
> Makefile.sun cr2lf* sqUnixSound.c
> Squeak1.18.changes lf2cr* sqXWindow.c
The changes file is for an image called "Squeak1.18", but the only image in
this directory is called "clone". You should be using an image and changes
file for an image with the *same* name.
By default the VM will look for an image called "clone.image" and
a changes file called "clone.changes", so not finding clone.changes is
probably the cause of your problem.
I suggest you fetch the Squeak1.19d.image and .changes files and try with
them. (They should work fine with the 1.18 VM.)
You need to put (a link to) the SqueakV1.sources file in the same directory
as the image/changes file, and run the VM (which doesn't have to be in the
same directory -- it can be anywhere in your PATH, or use a relative/absolute
path name, or a link, to get to it) from this directory.
Regards,
Ian
------------------------------- projet SOR -------------------------------
Ian Piumarta, INRIA Rocquencourt, Internet: Ian.Piumarta@inria.fr
BP105, 78153 Le Chesnay Cedex, FRANCE Voice: +33 1 39 63 52 87
----------------------- Systemes a Objets Repartis -----------------------
Date: 97 May 09 4:47:58 pm
From: Dan Ingalls <DanI@wdi.disney.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v0310280aaf966abf5bfc@[129.34.225.178]>
Subject: Re: Float bug in Squeak
--============_-1348895324==_============
Content-Type: text/plain; charset="us-ascii"
I attach herewith a redefinition of Character digitValue which causes the Float read problems to go away. As pointed out by tim, these were the result of allowing lowercase letters as digits, thus introducing an ambiguity in, eg, 15r1a.10e06.
>All float fans:
>
>On my PPC I get these strange results; the first two are OK, but then
>things get very odd, with various bizare values of zero:
> 13r0.0e0 0.0
> 14r0.0e0 0.0
> 15r0.0e0 0.0622222222222223
> 16r0.0e0 0.0546875
> 17r0.0e0 0.0484429065743945
With the fix, the results are now, as desired:
13r0.0e0 0.0
14r0.0e0 0.0
15r0.0e0 0.0
16r0.0e0 0.0
17r0.0e0 0.0
>These don't work too well either:
> 16r1.0e0 1.0546875
> 16r1.0e1 1.054931640625
> 16r1.0e2 1.05517578125
> 16r1.0e3 1.055419921875
With the fix, the results are now, as desired:
16r1.0e0 1.0
16r1.0e1 16.0
16r1.0e2 256.0
16r1.0e3 4096.0
[and from a later message]
>IBM Smalltalk almost gets it right:
>
> 16r1.0e2 100.0
> 16r1.0E2 1.05517578125
>
>The rule is that all hex digits are uppercase and the 'r' and 'e' are
>always lower.
With the fix, these are both right, as
16r1.0e2 256.0
16r1.0E2 1.05517578125
Many thanks, David, for checkin' them details!
- Dan
--============_-1348895324==_============
Content-Type: text/plain; name="Character-digitValue.st"; charset="us-ascii"
Content-Disposition: attachment; filename="Character-digitValue.st"
'From Squeak 1.19d of April 13, 1997 on 9 May 1997 at 5:03:45 pm'!
!Character methodsFor: 'accessing'!
digitValue
"Answer 0-9 if the receiver is $0-$9, 10-35 if it is $A-$Z, and < 0
otherwise. This is used to parse literal numbers of radix 2-36."
value <= $9 asciiValue
ifTrue: [^value - $0 asciiValue].
value >= $A asciiValue
ifTrue: [value <= $Z asciiValue ifTrue: [^value - $A asciiValue + 10]].
^ -1! !
--============_-1348895324==_============--
Date: 97 May 09 7:23:10 pm
From: lnotarfr@dc.uba.ar (Luciano Esteban Notarfrancesco)
To: squeak@create.ucsb.edu
Subject: hashing
Hello squeakers!
I'd like to point out some things about hashing in Squeak:
1) Some classes that implement #= forgot to implement #hash. Some of
them inherited a #hash that still makes sense with the reimplemented #=.
I searched the system for that classes doing
| aCollection |
aCollection _ SortedCollection new.
Smalltalk allBehaviorsDo:
[:class |
((class includesSelector: #=) and: [(class includesSelector: #hash) not])
ifTrue: [aCollection add: class name, ' ', #=]].
Smalltalk browseMessageList: aCollection name: 'unimplemented hash'
and I implemented #hash for that classes that needed it.
2) In a previous mail, I suggested some changes, and now I know some of
them were just bad ideas:
o. Extending Bag>>add:withOccurrences: for negative occurrences
was just stupid (sorry);
o. Implementing aClass>>asAClass (Bag>>asBag, for instance) to
return self is not a good thing, since the ANSI Smalltalk will
return always a copy of the receiver in such cases (and then the
inherited #asSomething will suffice). Also I was wrong when
checking the type of the receiver in Bad>>asBag (thanks for
noticing me about this, Dave!);
o. I reported a bug in comparisions between Symbols (#hola) and
Strings ('hola'). I suggested to answer true when comparing
#hola = 'hola'... and it was certainly wrong (thanks Douglas!). Both
#hola = 'hola' and 'hola' = #hola should be false.
3) In a previous mail I post implementations of Set>>hash and
SequenceableCollection>>hash. They were something like
^self inject: 0 into: [ :hashValue :each | hashValue + each hash].
But this could be very slow when hashing big collections. For speed,
Set>>hash could be implemented like
^self size
and SequenceableCollection>>hash like
^self size + (self at: 1 ifAbsent: [0]) hash.
What is better? A faster hash function or a more disperse hash function?
(an efficient hash function or an effective one?)
4) I think Squeak have some problem with IdentityDictionary>>includes:
and IdentityDictionary>>occurrencesOf:. I don't have Squeak here, so
I'll check it later.
Best regards,
--- Luciano.
'From Squeak 1.19d of April 13, 1997 on 9 May 1997 at 1:31:13 am'!
!CharacterBlock methodsFor: 'comparing'!
hash
^stringIndex hash! !
!Text methodsFor: 'comparing'!
hash
^string hash + runs hash! !
!TextColor methodsFor: 'as yet unclassified'!
hash
^color hash! !
!TextEmphasis methodsFor: 'as yet unclassified'!
hash
^emphasisCode hash! !
!TextFontChange methodsFor: 'as yet unclassified'!
hash
^fontNumber hash! !
Date: 97 May 11 8:25:44 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: Squeak@create.ucsb.edu
Subject: process fun
For many years I've had this recurring worry about non-local returns,
where it's not enforced that the process that created the block is the
same as the process that eventually invokes the non-local return. The
return can end up crossing a process boundary without the VM being aware
of it.
Enjoy! ;-)
Ian
'From Squeak 1.19d of April 13, 1997 on 11 May 1997 at 5:26:15 pm'!
Object subclass: #Prank
instanceVariableNames: 'pid1 pid2 block1 '
classVariableNames: ''
poolDictionaries: ''
category: 'Squeak Interpreter'!
!Prank methodsFor: 'as yet unclassified'!
doit
"Prank new doit"
pid1 _ Processor activeProcess.
pid2 _ [
Processor activeProcess == pid2 ifFalse: [self error: 'process 2 is wrong'].
Transcript cr; show: 'about to activate process 1 block'.
block1 value.
] newProcess.
pid2 priority: Processor userInterruptPriority.
pid1 == pid2 ifTrue: [self error: 'process identity crisis'].
self initBlock. "pid2 runs when resumed during this send"
pid1 == Processor activeProcess ifFalse: [self error: 'process screwed'].
Transcript cr; show: 'prank over'.!
initBlock
block1 _
[Transcript cr; show: 'about to return into process 1 stack'.
^42].
Transcript cr; show: 'about to resume process 2...'.
pid2 resume! !
Date: 97 May 11 8:41:11 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Float #hash method LONG and DULL
All float fans:
The Float hash method seems left over from olden days where small integers
were 16K or so. It uses only one part of the float, possibly giving quite
different answers depending on byte ordering.
The suggested new one answers the same results on Big Endian and Small
Endian machines (at least it does on my Pentium and PPC).
Both words of the double float are used; 8 bits are removed from each end
to clear most of the exponent regardless of the byte ordering. While it is
a bit slower than the original version, it is slower only in the ratios
12:5 to 2:1 depending on values.
The last (outermost) #bitAnd: can be removed; it is there to guarantee that
the result is always 16 bits, bit it doesn't seem to matter. The hash is
different, but doesn't seem worse.
I tried a number of other hash algorithms and found lots of bad ones. This
one seems to work better than the existing one in cases I've tried, and it
works far better than at least one commercial implementation which answers
the integer part of a float, ignoring the fraction entirely! However, there
may be better ones; I make no guarantees. In particular, it would be nice
if values had more than a 64K range but my attempts to do that always ended
up with bad test results. Clearly more work is needed...
The method is:
--------------------------------------------------------------------
hashDNS
"Hash is reimplemented because = is implemented.
Both words of the double float are used; 8 bits are
removed from each end to clear most of the exponent
regardless of the byte ordering. (Three bitAnd:s are
utilized to assure the intermediate results do not
become a large integer.) Slower than the original
version in the ratios 12:5 to 2:1 depending on values.
Answers the same result on Big Endian and Small Endian
IEEE machines.(DNS, 11May197) "
^ (
(
((self basicAt: 1) bitAnd: 16r00FFFF00) +
((self basicAt: 2) bitAnd: 16r00FFFF00)
) bitAnd: 16r00FFFF00
) >> 8
--------------------------------------------------------------------
Tests
-----
Each test is the same except for the range in #to:by:do:. Each test tries a
set of floats with each hash method, testing the distribution with a 100
element bucket test. The tests shown were run with 1.19d on an Apple PPC
9500/200. They were repeated on an IBM ThinkPad 760e (a recent Pentium)
using 1.16 and the new hash algorithm answered the same values.
(1) Test of wide range of floats, -100000 to 100000 by 10. Note the bad
clustering in the first set of values from the existing hash method. The
second set shows some variation but each bucket is hit with mo more than
double the entries of any other.
| bucket bucketd t |
bucket := Array new: 100.
bucket atAllPut: 0.
bucketd := Array new: 100.
bucketd atAllPut: 0.
-100000.0 to: 100000.0 by: 10.0 do: [ :f |
t := (f hash \\ bucket size) + 1.
bucket at: t put: (bucket at: t) + 1.
t := (f hashDNS \\ bucketd size) + 1.
bucketd at: t put: (bucketd at: t) + 1 ].
Array with: bucket with: bucketd
((1021 0 0 0 774 0 0 0 672 0 0 0 812 0 0 0 800 0 0 0 814 0 0 0 840 0 0 0
756 0 0 0 748 0 0 0 852 0 0 0 800 0 0 0 800 0 0 0 768 0 0 0 748 0 0 0 840 0
0 0 840 0 0 0 814 0 0 0 720 0 0 0 812 0 0 0 748 0 0 0 774 0 0 0 748 0 0 0
756 0 0 0 904 0 0 0 840 0 0 0 )
(253 206 166 124 332 166 206 166 166 248 248 206 188 124 248 166 218 166
124 248 252 206 166 124 332 166 206 166 166 248 248 206 188 124 248 166 218
166 124 248 256 206 170 124 334 170 208 168 166 252 252 206 190 126 252 170
218 170 126 252 258 208 170 126 338 170 208 170 168 252 252 208 192 126 252
170 218 170 126 252 258 208 170 126 336 170 208 170 170 252 252 208 190 126
250 166 216 166 124 248 ) )
(2) Same as (1) but the by: value is 8.9 versus 10. Note that the bad
clustering of the old hash disappears but that values still range from
about 176 to 277 but with groups of two low value followed by groups of two
high values.
The new hash values range from 188 to 268, but doesn't show the (mild)
clustering.
| bucket bucketd t |
bucket := Array new: 100.
bucket atAllPut: 0.
bucketd := Array new: 100.
bucketd atAllPut: 0.
-100000.0 to: 100000.0 by: 8.9 do: [ :f |
t := (f hash \\ bucket size) + 1.
bucket at: t put: (bucket at: t) + 1.
t := (f hashDNS \\ bucketd size) + 1.
bucketd at: t put: (bucketd at: t) + 1 ].
Array with: bucket with: bucketd
((277 178 181 260 276 177 179 282 266 183 174 276 266 180 184 267 269 180
179 267 274 179 182 265 266 191 182 267 271 179 188 267 270 183 183 270 269
171 189 269 273 176 173 276 266 183 171 272 268 184 179 266 275 189 175 276
269 187 179 272 261 176 180 275 270 181 178 267 276 177 182 268 273 176 180
268 273 182 177 276 261 182 184 275 264 174 180 263 267 176 179 266 276 173
175 269 265 178 180 264 )
(188 230 223 195 249 203 218 282 214 204 252 190 218 244 186 244 213 216
272 228 201 252 197 205 242 197 236 228 199 278 233 196 257 205 197 245 203
228 238 215 258 245 189 268 194 209 243 208 210 253 211 251 263 181 259 204
210 238 213 205 252 218 237 274 178 270 198 206 244 213 196 252 218 222 284
185 242 219 200 237 206 206 250 212 217 291 186 241 227 187 241 220 190 250
209 219 280 203 214 245 ) )
(3) A test of small numbers, from -1.0 to 1.0 with an uneven increment. The
results are similar.
| bucket bucketd t |
bucket := Array new: 100.
bucket atAllPut: 0.
bucketd := Array new: 100.
bucketd atAllPut: 0.
-1.0 to: 1.0 by: 0.000084 do: [ :f |
t := (f hash \\ bucket size) + 1.
bucket at: t put: (bucket at: t) + 1.
t := (f hashDNS \\ bucketd size) + 1.
bucketd at: t put: (bucketd at: t) + 1 ].
Array with: bucket with: bucketd
((241 245 244 231 231 220 243 246 240 236 247 251 236 227 228 235 247 246
244 250 243 240 225 222 227 246 243 250 237 245 240 227 215 236 239 245 247
248 242 244 227 226 237 244 244 251 245 245 235 225 229 229 243 247 244 238
245 240 231 220 231 240 243 237 243 252 247 233 226 223 239 249 244 249 237
243 232 221 225 237 247 253 236 244 246 230 218 223 240 239 241 252 248 240
232 219 233 231 247 246 )
(233 248 244 219 241 239 230 250 228 260 240 242 226 245 234 238 243 231
250 226 246 221 249 216 250 237 239 235 248 240 227 241 230 260 234 236 249
241 226 239 245 227 248 235 235 243 237 227 233 238 229 246 253 225 239 235
252 224 248 235 248 238 239 232 246 241 228 245 229 246 220 256 228 244 230
249 220 241 237 239 238 231 253 233 247 237 242 234 243 238 235 246 240 232
235 237 224 244 247 233 ) )
(4) Same as (3) but with an even smaller range. Note the old values range
from 119 to 356, indicating a less than perfect distribution. The new hash
has a much better distribution.
| bucket bucketd t |
bucket := Array new: 100.
bucket atAllPut: 0.
bucketd := Array new: 100.
bucketd atAllPut: 0.
-0.001 to: 0.001 by: 0.000000084 do: [ :f |
t := (f hash \\ bucket size) + 1.
bucket at: t put: (bucket at: t) + 1.
t := (f hashDNS \\ bucketd size) + 1.
bucketd at: t put: (bucketd at: t) + 1 ].
Array with: bucket with: bucketd
((195 273 204 273 208 257 230 248 234 237 239 225 257 213 272 199 276 191
294 176 308 164 315 149 331 146 344 135 344 120 365 119 354 120 356 120 357
123 343 139 336 146 335 146 319 163 307 179 290 189 282 197 277 213 262 224
243 235 242 239 230 252 211 270 206 275 199 289 181 304 171 307 159 323 148
335 136 341 128 356 129 355 121 349 121 357 125 344 131 334 135 335 153 324
155 306 170 304 175 289 )
(228 234 239 242 240 245 249 230 245 244 254 218 221 229 241 231 252 233
251 236 246 242 253 237 222 220 233 236 252 235 245 243 246 237 244 251 234
217 224 240 238 244 238 252 229 250 233 258 234 231 216 229 233 244 235 258
239 238 246 239 248 231 235 217 228 233 248 230 256 240 245 237 252 241 226
227 228 227 236 255 243 244 238 248 234 252 227 230 222 232 234 240 245 249
233 251 239 245 240 221 ) )
(5) A test with very large numbers. Similar results. (Also similar results
with an increment of 1.1e45.)
| bucket bucketd t |
bucket := Array new: 100.
bucket atAllPut: 0.
bucketd := Array new: 100.
bucketd atAllPut: 0.
-1.0e50 to: 1.0e50 by: 1.0e45 do: [ :f |
t := (f hash \\ bucket size) + 1.
bucket at: t put: (bucket at: t) + 1.
t := (f hashDNS \\ bucketd size) + 1.
bucketd at: t put: (bucketd at: t) + 1 ].
Array with: bucket with: bucketd
((1990 1984 1970 2029 2042 2002 1962 2018 2010 2004 2046 2020 1948 2010
2036 1992 2006 2008 1982 1980 2008 2002 2022 1998 1984 1994 2000 2008 2018
1980 1962 2006 2014 2006 2030 1982 1978 2042 1996 1996 2004 1992 2020 1998
2006 2018 2016 1962 2052 2028 1932 2026 2026 1982 2042 1968 1970 2004 2008
2040 1972 1964 2004 2026 1992 2008 1986 1970 1982 2030 2030 1986 2004 1984
1984 2026 2062 1980 1982 2002 1996 2046 2026 1996 1982 1952 2004 2032 1970
1992 1982 1972 1990 2022 1974 1972 1976 1988 2004 1992 )
(2070 2021 1935 1999 2073 2018 1946 1997 2068 2009 1972 1968 2078 2021 1929
1987 2063 2018 1948 1980 2077 2021 1943 1992 2067 2002 1964 1987 2090 2019
1948 1998 2062 2040 1942 1985 2077 2012 1951 1960 2084 2012 1940 1983 2074
2000 1922 1990 2060 1999 1951 1982 2072 2007 1933 1985 2070 2018 1907 1987
2079 2020 1914 1978 2079 1983 1946 1966 2078 1988 1921 1989 2051 2008 1911
1988 2058 1991 1922 1975 2058 2002 1924 1974 2081 1998 1938 1981 2074 2011
1917 1989 2046 1990 1960 1973 2092 2006 1944 1985 ) )
---END---
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 11 9:13:54 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Ian Piumarta <piumarta@prof.inria.fr>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <199705111552.RAA02028@prof.inria.fr>
Subject: Re: process fun
Ian:
Just for fun I tried this on IBM Smalltalk V3 and it detected the an
attempt to return twice from a method. It wasn't no fun at all! (Neither
was the Error 11 and the hang of the MacOS when I tried in on Squeak 1.19d.
Your sense of humor is significantly worse than mine. :-)
IBM Smalltalk version:
Object subclass: #Prank
instanceVariableNames: 'pid1 pid2 block1 '
classVariableNames: ''
poolDictionaries: ''!
!Prank publicMethods!
doit
"Prank new doit"
pid1 := Processor activeProcess.
pid2 := [
Processor activeProcess == pid2 ifFalse: [self error:
'process 2 is wrong'].
Transcript cr; show: 'about to activate process 1 block'.
block1 value.
] newProcess.
pid2 priority: Processor userInterruptPriority.
pid1 == pid2 ifTrue: [self error: 'process identity crisis'].
self initBlock. "pid2 runs when resumed during this send"
pid1 == Processor activeProcess ifFalse: [self error: 'process
screwed'].
Transcript cr; show: 'prank over'.!
initBlock
block1 :=
[Transcript cr; show: 'about to return into process 1 stack'.
^42].
Transcript cr; show: 'about to resume process 2...'.
pid2 resume! !
Prank new doit
--------------------------------------------
The transcript shows:
about to resume process 2...
prank over
about to activate process 1 block
about to return into process 1 stack
--------------------------------------------
The debugger opens with a message about trying to return twice from a
method. This is a copy of the debuggers stack trace report. See the 7th
line from the bottom.
Debugger Stack Trace Report: 5/11/97
VM = 3.0, 6/6/95
Stack Trace for: Process:6253{suspended,4}
[optimized] in ProcessorScheduler>>#yield
BlockContextTemplate(Block)>>#critical
ProcessorScheduler>>#yield
ProcessorScheduler>>#enableProcessSwitches
[optimized] in EtWindowSystemStartUp class>>#reportError:resumable:startBP:
BlockContextTemplate(Block)>>#when:do:exitWith:retryReturn:
arg1 = an ExceptionalEventCollection
arg2 = [] in EtWindowSystemStartUp class>>#reportError:resumable:startBP:
arg3 = [] in Block>>#when:do:
arg4 = an Object
temp1 = [] in Block>>#when:do:exitWith:retryReturn:
temp2 = [] in Block>>#when:do:exitWith:retryReturn:
temp3 = nil
BlockContextTemplate(Block)>>#when:do:
arg1 = an ExceptionalEventCollection
arg2 = [] in EtWindowSystemStartUp class>>#reportError:resumable:startBP:
temp1 = an Object
temp2 = nil
EtWindowSystemStartUp class>>#reportError:resumable:startBP:
arg1 = 'attempt to return twice from method'
arg2 = false
arg3 = 89
temp1 = Process:6253{suspended,4}
Process>>#reportError:resumable:
arg1 = 'attempt to return twice from method'
arg2 = false
temp1 = 89
[optimized] in UndefinedObject(ExceptionalEvent
class)>>#initializeSystemExceptions
blockarg1 = Signal on Exception: (ExError) An error has occurred.
Signal>>#evaluate:
arg1 = [] in ExceptionalEvent class>>#initializeSystemExceptions
ExceptionalEvent>>#applyDefaultHandler:
arg1 = Signal on Exception: (ExError) An error has occurred.
temp1 = Exception: (ExError) An error has occurred.
ExceptionalEvent>>#signalWithArguments:
arg1 = ('attempt to return twice from method')
temp1 = Signal on Exception: (ExError) An error has occurred.
temp2 = nil
ExceptionalEvent>>#signalWith:
arg1 = 'attempt to return twice from method'
BlockContextTemplate(Object)>>#error:
arg1 = 'attempt to return twice from method'
BlockContextTemplate>>#cannotReturn
[optimized] in Prank>>#initBlock
[optimized] in Prank>>#doit
Process>>#newProcessOn:stackSize:
arg1 = [] in Prank>>#doit
arg2 = 1024
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 11 10:00:29 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: dnsmith@watson.ibm.com
Cc: Squeak@create.ucsb.edu
Subject: Re: process fun
David,
> about to resume process 2...
> prank over
> about to activate process 1 block
> about to return into process 1 stack
This doesn't look right. I suspect the #resume isn't pre-empting pid1,
and that pid1 is returning from #initBlock and printing 'prank over'
before pid2 starts to run (since the first thing that pid2 should do is
to print 'about to activate process 1 block'). In which case the
behaviour is correct: the activation of #initBlock in pid1 has already
exited when block1, activated by pid2, tries to return from it a second
time. pid2 is never reaching pid1's stack.
Try inserting a "(Delay forSeconds: 1) wait" just after the #resume in
#initBlock, to be *absolutely* sure that pid1 is still suspended in that
context when pid2 tries to return into its stack.
> Your sense of humor is significantly worse than mine. :-)
That was a very carefully calculated "winky" after the word "Enjoy!". ;)
Regards,
Ian
PS: Does Java have closures? (Maybe it's possible to turn Prank into an
applet... ;)
------------------------------- projet SOR -------------------------------
Ian Piumarta, INRIA Rocquencourt, Internet: Ian.Piumarta@inria.fr
BP105, 78153 Le Chesnay Cedex, FRANCE Voice: +33 1 39 63 52 87
----------------------- Systemes a Objets Repartis -----------------------
Date: 97 May 11 10:21:25 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: dnsmith@watson.ibm.com
Cc: Squeak@create.ucsb.edu
Subject: Re: process fun
It just occurred to me...
> the Error 11 and the hang of the MacOS when I tried in on Squeak 1.19d.
Look at this:
clotho$ fgrep SEGV /usr/include/signal.h
/usr/include/signal.h:#define SIGSEGV 11
Is this just a coincidence? (I can verify that it *is* a segmentation
fault that you get under Squeak when you run the prank [I keep a debugger
in my extensions folder at all times ;)].)
Ian
Date: 97 May 12 1:04:01 am
From: Hans-Martin Mosner <hmm@heeg.de>
To: squeak@create.ucsb.edu
Subject: Re: Newcomer, Persistent Store and Constraints
John Maloney wrote:
>
> Thierry:
>
> Welcome to Squeak!
>
> Re: transactions
>
> I have no great ideas except that you modify Squeak ObjectMemory to
> set a "dirty" bit on modified objects. There is a bit available in
> the object header, although there's no guarantee that we won't
> use that bit for something ourselves some day.
>
I'd suggest not a "dirty" bit but a "clean/readonly" bit that causes the
VM
to trap write accesses to the object (send it a message such as
#trapWrite: newValue slot: slotNumber)
This could be used to implement 2 desirable features:
1. Immutable objects
I and every other Smalltalker that I know have always wanted immutable
literals. This is the chance to have them in Squeak!
2. Persistent objects
Although I see little probability for a GemStone-Squeak interface, some
other persistent storage mechanisms might be ported to Squeak.
How can it be done?
My idea is that an object is either immutable (because it's a literal)
or has a persistent storage manager. In the first case, writes are never
allowed. In the second case, the storage manager decides whether a write
is allowed, and can remember the object as dirty.
A possible implementation looks like this:
trapWrite: newValue slot: slotNumber
| manager fixedSlots |
manager := self persistentStorageManager.
(manager == nil or: [manager isImmutable: self])
ifTrue: [self error: 'Write attempt to immutable object!'].
manager markDirty: self.
self primBeImmutable: false.
fixedSlots := self class instSize.
^slotNumber <= fixedSlots
ifTrue: [self instVarAt: slotNumber put: newValue]
ifFalse: [self basicAt: slotNumber - fixedSlots put: newValue]
!
persistentStorageManager
^PersistentStores
detect: [:each | each managesObject: self]
ifNone: [nil]
!
beImmutable: aBoolean
self isImmutable
ifTrue: [self error: 'Immutable status can not be changed!'].
self primBeImmutable: aBoolean
!
The methods #isImmutable and #primBeImmutable: would be primitives
accessing the clean/readonly bit.
How the managers implement the messages #managesObject:, #isImmutable:
and #markDirty: is their business, but should be straightforward.
How could it be implemented efficiently in the VM?
There is already a check to detect writes into old objects, so that
the table of old objects referencing new ones can be maintained.
The VM only looks at header bits if the object is in the address
range of old objects. Since most writes are into young objects, it would
be a significant performance hit to check the clean/readonly bit
on every write.
Therefore I propose that making an object immutable (which is a
not-too-common operation) should move the old/young object boundary
if the object is currently young. There are 2 possible alternatives:
1. Make all objects old.
Simple but somewhat stupid since too many innocent new objects
may be affected. However, it avoids updating the RootTable.
2. Make objects up to and including the newly immutable object old.
More complicated since all intermediate objects need to be checked
whether they need to be put into the RootTable.
Overall, I think that the basic mechanism would not be too complicated
to implement. There are a number of places in the VM where assumptions
about the writability of objects are made, such as Context objects etc.
These places need to be revisited.
For performance reasons, such objects should probably be exempt from the
clean/readonly mechanism (the primBeImmutable: primitive could just
fail).
Other objects, such as Floats, could be created by the VM with the
clean/readonly bit already on, avoiding any messing around.
Hans-Martin
Date: 97 May 12 2:39:28 am
From: wimb@bart.nl (Wim Boot)
To: squeak@create.ucsb.edu
In-Reply-To: <v03102805af9b9e000ef8@[129.34.225.178]>
Subject: Re: Float #hash method LONG and DULL
David N. Smith wrote:
>All float fans:
>
>The Float hash method seems left over from olden days where small =
integers
>were 16K or so. It uses only one part of the float, possibly giving =
quite
>different answers depending on byte ordering.
Indeed. There are worse (very ancient) problems however.
Try "1 hash =3D 1.0 hash" or "(3/2) hash =3D 1.5 hash". False in
both cases, though "1 =3D 1.0" and "(3/2) =3D 1.5" both yield true.
Your hashDNS method doesn't address this problem either.
Wim Boot
Date: 97 May 12 5:13:09 am
From: Thierry Goubier <Thierry.Goubier@enst-bretagne.fr>
To: Hans-Martin Mosner <hmm@heeg.de>
Cc: squeak@create.ucsb.edu
In-Reply-To: <3376D4F6.2781E494@heeg.de>
Subject: Re: Newcomer, Persistent Store and Constraints
On Mon, 12 May 1997, Hans-Martin Mosner wrote:
> John Maloney wrote:
> > I have no great ideas except that you modify Squeak ObjectMemory to
> > set a "dirty" bit on modified objects. There is a bit available in
> > the object header, although there's no guarantee that we won't
> > use that bit for something ourselves some day.
The problem is that the hard job for the persistent store is to determine
when an object is modified, not to record the fact it has been modified (I
may be mistaken here, but the cost of scanning throught all object headers
to determine which has been modified is high).
> I'd suggest not a "dirty" bit but a "clean/readonly" bit that causes the
> VM to trap write accesses to the object (send it a message such as
> #trapWrite: newValue slot: slotNumber)
I second this. That's a great idea for a persistent store.
> This could be used to implement 2 desirable features:
> 1. Immutable objects
> I and every other Smalltalker that I know have always wanted immutable
> literals. This is the chance to have them in Squeak!
> 2. Persistent objects
> Although I see little probability for a GemStone-Squeak interface, some
> other persistent storage mechanisms might be ported to Squeak.
I'll port my own little thing. But it won't be Gemstone-the return, don't
hold your breath. It may be usefull, however, to save morphs and the
like, or to try new things (schema management, cooperative software).
I'll suggest another thing
3. Read-only duplication of distributed objects
Thierry.
___________________Thierry.Goubier@enst-bretagne.fr__________________
But to look for heaven is to live here in hell [Sting]
http://www-info.enst-bretagne.fr/~goubier/
Date: 97 May 12 5:26:49 am
From: Anthony Lander <anthony@objectPeople.com>
To: squeak@create.ucsb.edu
Subject: Re: Newcomer, Persistent Store and Constraints
At 10:29 AM 5/12/97 +0200, you wrote:
>2. Persistent objects
>Although I see little probability for a GemStone-Squeak interface, some
>other persistent storage mechanisms might be ported to Squeak.
In theory, at least, I could port TOPLink to run under Squeak. The only
"tricky" part would be writing an ODBC interface.
-Anthony Lander
The Object People
-----------------------------------------------------------------
"it's pretty scary when u look at the colon/semicolon key on your
keyboard and you just see 4 faceless eyes staring at you" --Mark
Date: 97 May 12 6:40:12 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Cc: squeak@create.ucsb.edu
In-Reply-To: <3377e88a.11392902@mail.gld.bart.nl>
Subject: Re: Float #hash method LONG and DULL
At 6:01 -0400 5/12/97, Wim Boot wrote:
>David N. Smith wrote:
>
>>All float fans:
>>
>>The Float hash method seems left over from olden days where small integers
>>were 16K or so. It uses only one part of the float, possibly giving quite
>>different answers depending on byte ordering.
>
>Indeed. There are worse (very ancient) problems however.
>
>Try "1 hash = 1.0 hash" or "(3/2) hash = 1.5 hash". False in
>both cases, though "1 = 1.0" and "(3/2) = 1.5" both yield true.
>
>Your hashDNS method doesn't address this problem either.
>
>Wim Boot
Wim:
Maybe I'm missing something, but I wouldn't expect two different objects to
have the same hash just because they have the same 'value'. (3/2) is a
completely different object than 1.5
How about:
'abc' = #abc
true
'abc' hash = #abc hash
false
Should the hash of a string always be the hash of a symbol containing the
same characters? Symbols are typically guaranteed to have different hashes
for different values; strings are not because of the expense in many
implementations.
dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 6:55:05 am
From: tim <tim@apple.com>
To: "Dan Ingalls" <DanI@wdi.disney.com>,
"David N. Smith" <dnsmith@watson.ibm.com>
Cc: <Squeak@create.ucsb.edu>
Subject: Re: Float bug in Squeak
Dan Ingalls wrote:
>I attach herewith a redefinition of Character digitValue which causes the
>Float read problems to go away. As pointed out by tim, these were the
>result of allowing lowercase letters as digits, thus introducing an
>ambiguity in, eg, 15r1a.10e06.
InputSensor>>joystickButtons
InputSensor>>joystickXY:
look to be the only existing sources that rely upon lower-case hex digits
for literals; they should be changed to match the new digitValue method.
-- tim
Date: 97 May 12 7:18:28 am
From: johnson@cs.uiuc.edu (Ralph E. Johnson)
To: "David N. Smith" <dnsmith@watson.ibm.com>, squeak@create.ucsb.edu
Cc: squeak@create.ucsb.edu
Subject: Re: Float #hash method LONG and DULL
At 10:08 AM 5/12/97, David N. Smith wrote:
>Maybe I'm missing something, but I wouldn't expect two different objects to
>have the same hash just because they have the same 'value'. (3/2) is a
>completely different object than 1.5
Sets and dictionaries assume that equal objects hash equally. Suppose
x and y are two objects that are equal but have different hashes. If
you put x in a set and ask whether the set includes y, the answer will
be false unless x and y just happened to hash into the same location, in
which the answer is true. So, if you redefine = then you should redefine
hash.
-Ralph
Date: 97 May 12 7:22:36 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Ian Piumarta <piumarta@prof.inria.fr>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <199705111727.TAA07507@prof.inria.fr>
Subject: Re: process fun (in IBM Smalltalk too)
At 13:27 -0400 5/11/97, Ian Piumarta wrote:
>David,
>
>> about to resume process 2...
>> prank over
>> about to activate process 1 block
>> about to return into process 1 stack
>
>This doesn't look right. I suspect the #resume isn't pre-empting pid1,
>and that pid1 is returning from #initBlock and printing 'prank over'
>before pid2 starts to run (since the first thing that pid2 should do is
>to print 'about to activate process 1 block'). In which case the
>behaviour is correct: the activation of #initBlock in pid1 has already
>exited when block1, activated by pid2, tries to return from it a second
>time. pid2 is never reaching pid1's stack.
>
>Try inserting a "(Delay forSeconds: 1) wait" just after the #resume in
>#initBlock, to be *absolutely* sure that pid1 is still suspended in that
>context when pid2 tries to return into its stack.
>
>> Your sense of humor is significantly worse than mine. :-)
>
>That was a very carefully calculated "winky" after the word "Enjoy!". ;)
>
>Regards,
>
>Ian
>
>PS: Does Java have closures? (Maybe it's possible to turn Prank into an
> applet... ;)
>
>-------------------------------
Ian:
(Java friends claim that Java 1.1 has closures. I haven't seen them.)
Adding a Delay made no difference, as didn't an explicit 'Processor yield'
after the #resume. However, if I run pid1 by forking it (and thus it
doesn't run as the user interface process) then I get:
about to resume process 2...
about to activate process 1 block
about to return into process 1 stack
prank over
and the debugger gives me a 'illegal implicit process switch' message
pointing at the '^42'. User interface processes are a bit odd and I should
have tried this yesterday.
The code is (note the change in the commented expression in #doit):
---------------------------
Object subclass: #Prank
instanceVariableNames: 'pid1 pid2 block1 '
classVariableNames: ''
poolDictionaries: ''!
!Prank publicMethods!
doit
"[Prank new doit] fork"
pid1 := Processor activeProcess.
pid2 := [
Processor activeProcess == pid2 ifFalse: [self error:
'process 2 is wrong'].
Transcript cr; show: 'about to activate process 1 block'.
block1 value.
] newProcess.
pid2 priority: Processor userInterruptPriority.
pid1 == pid2 ifTrue: [self error: 'process identity crisis'].
self initBlock. "pid2 runs when resumed during this send"
pid1 == Processor activeProcess ifFalse: [self error: 'process
screwed'].
Transcript cr; show: 'prank over'.!
initBlock
block1 :=
[Transcript cr; show: 'about to return into process 1 stack'.
^42].
Transcript cr; show: 'about to resume process 2...'.
pid2 resume.
(Delay forSeconds: 2) wait! !
---------------------------
Debugger Stack Trace Report: 5/12/97
VM = 3.0, 6/6/95
...snip...
BlockContextTemplate(Object)>>#error:
arg1 = 'illegal implicit process switch'
BlockContextTemplate>>#cannotReturn
[optimized] in Prank>>#initBlock
[optimized] in Prank>>#doit
Process>>#newProcessOn:stackSize:
arg1 = [] in Prank>>#doit
arg2 = 1024
---------------------------
HOWEVER, if I remove the Delay then I get:
-----------------
about to resume process 2...
about to activate process 1 block
prank overabout to return into process 1 stack
-----------------
and the debugger says 'attempt to return twice from method'. A Processor
yield makes no difference, but invoking the code this way does:
"[Prank new doit] forkAt: 2"
(where process priorities are as in the Blue Book). This makes it run with
the same results as with the code above.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 7:34:55 am
From: Hans-Martin Mosner <hmm@heeg.de>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: squeak@create.ucsb.edu
Subject: Re: Float #hash method LONG and DULL
David N. Smith wrote:
>
> Wim:
>
> Maybe I'm missing something, but I wouldn't expect two different objects to
> have the same hash just because they have the same 'value'. (3/2) is a
> completely different object than 1.5
Hasn't this topic been hashed to death already? (pardon the pun)
If two objects compare equal, their hash values should be equal as well.
I know that this has strange implications for numeric classes, but this
is a matter of definition...
If I put 3/2 and 1.5 in a Set, do I expect the Set to have size 1 or 2?
By definition, for each a,b element of a Set, a ~= b.
Since (3/2) = 1.5, the Set must have one element only (whichever came
first).
To make this really happen, 3/2 must have the same hash as 1.5.
Perhaps a good time now to think about the implications and reimplement
#hash in all the number classes.
> How about:
>
> 'abc' = #abc
> true
Should not be. Someone on this list acknowleged that it's a bug, because
#abc ~= 'abc'. Equality should work both ways.
>
> 'abc' hash = #abc hash
> false
>
> Should the hash of a string always be the hash of a symbol containing the
> same characters?
No, because that would be impossible. Symbols just have arbitrary hash
values
that are not related to their constituent characters.
(Which is probably bad for object migration. Setting the hash value of
a Symbol from the CRC of its characters might be better)
> Symbols are typically guaranteed to have different hashes
> for different values;
No, Symbols are just guaranteed to be unique, that is, two
Symbols are the same object if and only if they have the same
characters.
Symbols (like other Objects) are guaranteed to have same hashes
for same values, though.
> strings are not because of the expense in many
> implementations.
For Symbols, hash is synonymous to identity hash (which is logical,
since
equality for Symbols is synonymous to identity)
For Strings, hash is a fast (and some say, bad) function of
the characters in the string.
Hans-Martin
Date: 97 May 12 8:11:54 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Squeak@create.ucsb.edu
Subject: Three fileIns
--============_-1348667088==_============
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
NumberFixes-di.cs
Three fixes to Float, suggested or requested by David Smith. Eliminates=
amgiguity of non-decimal constants by requiring letter-digits to be=
uppercase, and fixes two methods that used lowercase hex digits (thanks=
tim). Renames the old asFraction code to be asApproximateFraction, and=
installs David's asTrueFraction as well. Finally includes David's=
improvement to Float>>hash. Takes a while at the end to rehash all=
existing sets, and also fixes a bug in the progress bar which is used in=
the process.
VMfixes-di.cs
Sundry fixes and improvements to the VM. Speeds up BitBlt 'paint' mode when=
the source is zero.
=46ixes a problem reported by Paul McCullough and Don Charnley, so that the=
VM now checks for recursive evaluation of blocks (currently crashes). =
Fixes two problems reported by Carl Watts: perform now checks that its=
selector is not an immediate object (currently crashes), and perform also=
adjusts its argument count at the correct time so that the=
doesNotUnderstand facility works properly. Also includes minor=
improvements to related error messages.
ChangeSetCommentFix.st
ChangeSets have not been filing out class comments since a change that=
merged class and metaclass access to comments months ago. This restores=
the fileOut of changed class comments from changeSorters.
--============_-1348667088==_============
Content-Type: text/plain; name="NumberFixes-di.cs"; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="NumberFixes-di.cs"
'From Squeak 1.19d of April 13, 1997 on 12 May 1997 at 8:29:02 am'!
"Change Set: NumberFixes
Date: 11 May 1997
Author: Your Name
Three fixes to Float, suggested or requested by David Smith. Eliminates=
amgiguity of non-decimal constants by requiring letter-digits to be=
uppercase. Renames the old asFraction code to be asApproximateFraction,=
and installs David's asTrueFraction as well. Finally includes David's=
improvement to Float>>hash.
Takes a while at the end to rehash all existing sets, and also fixes a bug=
in the progress bar code which is used in the process.
"!
!Character methodsFor: 'accessing'!
digitValue
"Answer 0-9 if the receiver is $0-$9, 10-35 if it is $A-$Z, and < 0=20
otherwise. This is used to parse literal numbers of radix 2-36."
value <=3D $9 asciiValue=20
ifTrue: [^value - $0 asciiValue].
value >=3D $A asciiValue=20
ifTrue: [value <=3D $Z asciiValue ifTrue: [^value - $A asciiValue + 10]].
^ -1! !
!Float methodsFor: 'comparing'!
hash
"Hash is reimplemented because =3D is implemented.
Both words of the double float are used; 8 bits are
removed from each end to clear most of the exponent
regardless of the byte ordering. (Three bitAnd:s are
utilized to assure the intermediate results do not
become a large integer.) Slower than the original
version in the ratios 12:5 to 2:1 depending on values.
Answers the same result on Big Endian and Small Endian
IEEE machines.(DNS, 11 May, 1997) "
^ (
(
((self basicAt: 1) bitAnd: 16r00FFFF00) +
((self basicAt: 2) bitAnd: 16r00FFFF00)
) bitAnd: 16r00FFFF00
) >> 8
! !
!Float methodsFor: 'converting'!
asApproximateFraction
"Answer a Fraction approximating the receiver. This conversion uses the=20
continued fraction method to approximate a floating point number."
| num1 denom1 num2 denom2 int frac newD temp |
num1 _ self asInteger. "The first of two alternating numerators"
denom1 _ 1. "The first of two alternating denominators"
num2 _ 1. "The second numerator"
denom2 _ 0. "The second denominator--will update"
int _ num1. "The integer part of self"
frac _ self fractionPart. "The fractional part of self"
[frac =3D 0]
whileFalse:=20
["repeat while the fractional part is not zero"
newD _ 1.0 / frac. "Take reciprocal of the fractional part"
int _ newD asInteger. "get the integer part of this"
frac _ newD fractionPart. "and save the fractional part for next time"
temp _ num2. "Get old numerator and save it"
num2 _ num1. "Set second numerator to first"
num1 _ num1 * int + temp. "Update first numerator"
temp _ denom2. "Get old denominator and save it"
denom2 _ denom1. "Set second denominator to first"
denom1 _ int * denom1 + temp. "Update first denominator"
10000000000.0 < denom1
ifTrue:=20
["Is ratio past float precision? If so, pick which=20
of the two ratios to use"
num2 =3D 0.0=20
ifTrue: ["Is second denominator 0?"
^ Fraction numerator: num1 denominator: denom1].
^ Fraction numerator: num2 denominator: denom2]].
"If fractional part is zero, return the first ratio"
denom1 =3D 1
ifTrue: ["Am I really an Integer?"
^ num1 "Yes, return Integer result"]
ifFalse: ["Otherwise return Fraction result"
^ Fraction numerator: num1 denominator: denom1]!
asFraction
^ self asApproximateFraction !
asTrueFraction
" Answer a fraction that EXACTLY represents self,
a double precision IEEE floating point number.
(It tears an IEEE float into its components; it
assumes 'correct' byte ordering; runs on PPC.)=20
Thanks to David N. Smith"
| shifty sign exp fraction |
shifty :=3D ((self at: 1) bitShift: 32) bitOr: (self at: 2).
sign :=3D (shifty bitShift: -63) =3D 0 ifTrue: [1] ifFalse: [-1].
exp :=3D (shifty >> 52) bitAnd: 16r7FF.
fraction :=3D shifty bitAnd: 16r000FFFFFFFFFFFFF.
(exp =3D 0) & (fraction =3D 0) ifTrue: [ ^ 0 ].
fraction :=3D fraction bitOr: 16r0010000000000000.
exp :=3D exp - 16r3FF.
" Validate that the dismemberment was correct "
(sign * fraction / (2 raisedToInteger: 52 - exp)) asFloat =3D self
ifFalse: [self error: 'asFraction validation failed' ].
^ sign * fraction / (2 raisedToInteger: 52 - exp)! !
!InputSensor methodsFor: 'joystick'!
joystickButtons: index
^ ((self primReadJoystick: index) bitShift: -22) bitAnd: 16r71F
!
joystickXY: index
| inputWord x y |
inputWord _ self primReadJoystick: index.
x _ (inputWord bitAnd: 16r7FF) - 16r400.
y _ ((inputWord bitShift: -11) bitAnd: 16r7FF) - 16r400.
^ x@y
! !
!Set class methodsFor: 'initialization'!
rehashAllSets "Set rehashAllSets"
| insts |
self withAllSubclassesDo:
[:c | insts _ c allInstances.
insts isEmpty ifFalse:
['Rehashing instances of ' , c name
displayProgressAt: Sensor cursorPoint
from: 1 to: insts size
during: [:bar |
1 to: insts size do:
[:x | bar value: x.
(insts at: x) rehash]]]]! !
!String methodsFor: 'displaying'!
displayProgressAt: aPoint from: minVal to: maxVal during: workBlock=20
"Display this string as a caption over a progress bar while workBlock is ev=
aluated.
EXAMPLE (Select next 6 lines and Do It)
'Now here''s some Real Progress'
displayProgressAt: Sensor cursorPoint
from: 0 to: 10
during: [:bar |
1 to: 10 do: [:x | bar value: x.
(Delay forMilliseconds: 500) wait]].
HOW IT WORKS (Try this in any other language :-)
Since your code (the last 2 lines in the above example) is in a block,
this method gets control to display its heading before, and clean up=20
the screen after, its execution.
The key, though, is that the block is supplied with an argument,
named 'bar' in the example, which will update the bar image every=20
it is sent the message value: x, where x is in the from:to: range.
"
| delta savedArea captionText textFrame barFrame outerFrame result range |
barFrame _ aPoint - (75@10) corner: aPoint + (75@10).
captionText _ DisplayText text: self asText allBold.
textFrame _ captionText boundingBox insetBy: -4.
textFrame _ textFrame align: textFrame bottomCenter
with: barFrame topCenter + (0@2).
outerFrame _ barFrame merge: textFrame.
delta _ outerFrame amountToTranslateWithin: Display boundingBox.
barFrame _ barFrame translateBy: delta.
textFrame _ textFrame translateBy: delta.
outerFrame _ outerFrame translateBy: delta.
savedArea _ Form fromDisplay: outerFrame.
Display fillBlack: barFrame; fillWhite: (barFrame insetBy: 2).
Display fillBlack: textFrame; fillWhite: (textFrame insetBy: 2).
captionText displayOn: Display at: textFrame topLeft + (4@4).
range _ maxVal =3D minVal ifTrue: [1] ifFalse: [maxVal - minVal]. "Avoid=
div by 0"
result _ workBlock value: "Supply the bar-update block for evaluation in=
the work block"
[:barVal | Display fillGray: (barFrame topLeft + (2@2) extent:
(((barFrame width-4) * (barVal-minVal) / range)@16))].
savedArea displayOn: Display at: outerFrame topLeft.
^ result! !
Set rehashAllSets!
--============_-1348667088==_============
Content-Type: text/plain; name="VMfixes-di.cs"; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="VMfixes-di.cs"
'From Squeak 1.19d of April 13, 1997 on 11 May 1997 at 3:19:25 pm'!
"Change Set: VMchanges
Date: 11 May 1997
Author: Dan Ingalls
Sundry fixes and improvements to the VM. Speeds up BitBlt 'paint' mode when=
the source is zero.
=46ixes a problem reported by Paul McCullough and Don Charnley, so that the=
VM now checks for recursive evaluation of blocks. Fixes two problems=
reported by Carl Watts: perform now checks that its selector is not an=
immediate object (had caused crashes), and perform also adjusts its=
argument count at the correct time so that the doesNotUnderstand facility=
works properly.
Also includes minor improvements to related error messages.
"!
!Object methodsFor: 'message handling'!
perform: selector withArguments: anArray=20
"Primitive. Send the receiver the keyword message indicated by the=20
arguments. The argument, selector, is the selector of the message. The=20
arguments of the message are the elements of anArray. Invoke=20
messageNotUnderstood: if the number of arguments expected by the=20
selector is not the same as the length of anArray. Essential. See Object=20
documentation whatIsAPrimitive."
<primitive: 84>
(selector isMemberOf: Symbol)
ifFalse: [^ self error: 'selector argument must be a Symbol'].
self primitiveFailed! !
!BitBltSimulation methodsFor: 'combination rules'!
merge: sourceWord with: destinationWord
"
^ self dispatchOn: combinationRule
with: sourceWord with: destinationWord
in: RuleTable.
"
self inline: true.
"These are the combination rules..."
combinationRule < 16 ifTrue:
[combinationRule < 8 ifTrue:
[combinationRule < 4 ifTrue:
[combinationRule < 2 ifTrue:
[combinationRule < 1 ifTrue:
["0" ^ 0]
ifFalse:
["1" ^ sourceWord bitAnd: destinationWord]]
ifFalse:
[combinationRule < 3 ifTrue:
["2" ^ sourceWord bitAnd: destinationWord bitInvert32]
ifFalse:
["3" ^ sourceWord]]]
ifFalse:
[combinationRule < 6 ifTrue:
[combinationRule < 5 ifTrue:
["4" ^ sourceWord bitInvert32 bitAnd: destinationWord]
ifFalse:
["5" ^ destinationWord]]
ifFalse:
[combinationRule < 7 ifTrue:
["6" ^ sourceWord bitXor: destinationWord]
ifFalse:
["7" ^ sourceWord bitOr: destinationWord]]]]
ifFalse:
[combinationRule < 12 ifTrue:
[combinationRule < 10 ifTrue:
[combinationRule < 9 ifTrue:
["8" ^ sourceWord bitInvert32 bitAnd: destinationWord bitInvert32]
ifFalse:
["9" ^ sourceWord bitInvert32 bitXor: destinationWord]]
ifFalse:
[combinationRule < 11 ifTrue:
["10" ^ destinationWord bitInvert32]
ifFalse:
["11" ^ sourceWord bitOr: destinationWord bitInvert32]]]
ifFalse:
[combinationRule < 14 ifTrue:
[combinationRule < 13 ifTrue:
["12" ^ sourceWord bitInvert32]
ifFalse:
["13" ^ sourceWord bitInvert32 bitOr: destinationWord]]
ifFalse:
[combinationRule < 15 ifTrue:
["14" ^ sourceWord bitInvert32 bitOr: destinationWord bitInvert32]
ifFalse:
["15" ^ destinationWord]]]]]
ifFalse:
[combinationRule < 24 ifTrue:
[combinationRule < 20 ifTrue:
[combinationRule < 18 ifTrue:
[combinationRule < 17 ifTrue:
["16" ^ destinationWord "no op"]
ifFalse:
["17" ^ destinationWord "no op"]]
ifFalse:
[combinationRule < 19 ifTrue:
["18" ^ sourceWord + destinationWord]
ifFalse:
["19" ^ sourceWord - destinationWord]]]
ifFalse:
[combinationRule < 22 ifTrue:
[combinationRule < 21 ifTrue:
["20" ^ self rgbAdd: sourceWord with: destinationWord]
ifFalse:
["21" ^ self rgbSub: sourceWord with: destinationWord]]
ifFalse:
[combinationRule < 23 ifTrue:
["22" ^ self rgbDiff: sourceWord with: destinationWord]
ifFalse:
["23" ^ self tallyIntoMap: destinationWord]]]]
ifFalse:
[combinationRule < 28 ifTrue:
[combinationRule < 26 ifTrue:
[combinationRule < 25 ifTrue:
["24" ^ self alphaBlend: sourceWord with: destinationWord]
ifFalse:
["25" sourceWord =3D 0 ifTrue: [^ destinationWord].
^ self pixPaint: sourceWord with: destinationWord]]
ifFalse:
[combinationRule < 27 ifTrue:
["26" ^ self pixMask: sourceWord with: destinationWord]
ifFalse:
["27" ^ self rgbMax: sourceWord with: destinationWord]]]
ifFalse:
[combinationRule < 30 ifTrue:
[combinationRule < 29 ifTrue:
["28" ^ self rgbMin: sourceWord with: destinationWord]
ifFalse:
["29" ^ self rgbMin: sourceWord bitInvert32 with: destinationWord]]
ifFalse:
[combinationRule < 31 ifTrue:
["30" ^ destinationWord "no op"]
ifFalse:
["31" ^ destinationWord "no op"]]]]]! !
!BlockContext methodsFor: 'evaluating'!
valueWithArguments: anArray=20
"Primitive. Evaluate the block represented by the receiver. The argument=20
is an Array whose elements are the arguments for the block. Fail if the=20
length of the Array is not the same as the the number of arguments that=20
the block was expecting. Fail if the block is already being executed.=20
Essential. See Object documentation whatIsAPrimitive."
<primitive: 82>
self numArgs =3D anArray size
ifTrue: [self error: 'Attempt to evaluate a block that is already being ev=
aluated.']
ifFalse: [self error: 'This block requires ' , self numArgs printString ,=
' arguments.']! !
!BlockContext methodsFor: 'private'!
cannotReturn: arg
self error: 'This block cannot return (it has already done so).'.
"Kill off this process"
Processor terminateActive! !
!Interpreter methodsFor: 'contexts'!
caller
^self fetchPointer: CallerIndex
ofObject: activeContext! !
!Interpreter methodsFor: 'control primitives'!
primitivePerform
| performSelector newReceiver selectorIndex |
performSelector _ messageSelector.
messageSelector _ self stackValue: argumentCount - 1.
(self isIntegerObject: self stackTop) ifTrue: [self primitiveFail. ^ 0].
newReceiver _ self stackValue: argumentCount.
"NOTE: the following lookup may fail and be converted to #doesNotUnderstand=
:,
so we must adjust argument count now, so that would work."
argumentCount _ argumentCount - 1.
self lookupMethodInClass: (self fetchClassOf: newReceiver).
self success: (self argumentCountOf: newMethod) =3D argumentCount.
successFlag
ifTrue: [selectorIndex _ self stackPointerIndex - argumentCount.
self transfer: argumentCount
fromIndex: selectorIndex + 1
ofObject: activeContext
toIndex: selectorIndex
ofObject: activeContext.
self pop: 1.
self executeNewMethod. "Recursive xeq affects successFlag"
successFlag _ true]
ifFalse: [argumentCount _ argumentCount + 1.
messageSelector _ performSelector]!
primitivePerformWithArgs
| thisReceiver performSelector argumentArray arraySize index cntxSize |
argumentArray _ self popStack.
arraySize _ self fetchWordLengthOf: argumentArray.
cntxSize _ self fetchWordLengthOf: activeContext.
self success: (self stackPointerIndex + arraySize) < cntxSize.
self success: (self isIntegerObject: self stackTop) not.
self assertClassOf: argumentArray is: (self splObj: ClassArray).
successFlag
ifTrue: [performSelector _ messageSelector.
messageSelector _ self popStack.
thisReceiver _ self stackTop.
argumentCount _ arraySize.
index _ 1.
[index <=3D argumentCount]
whileTrue:
[self push: (self fetchPointer: index - 1 ofObject: argumentArray).
index _ index + 1].
self lookupMethodInClass: (self fetchClassOf: thisReceiver).
self success: (self argumentCountOf: newMethod) =3D argumentCount.
successFlag
ifTrue: [self executeNewMethod. "Recursive xeq affects successFlag"
successFlag _ true]
ifFalse: [self unPop: argumentCount.
self push: messageSelector.
self push: argumentArray.
argumentCount _ 2.
messageSelector _ performSelector]]
ifFalse: [self unPop: 1]!
primitiveValue
| blockContext blockArgumentCount initialIP |
blockContext _ self stackValue: argumentCount.
blockArgumentCount _ self argumentCountOfBlock: blockContext.
self success: (argumentCount =3D blockArgumentCount
and: [(self fetchPointer: CallerIndex ofObject: blockContext) =3D nilObj]=
).
successFlag
ifTrue: [self transfer: argumentCount
fromIndex: self stackPointerIndex - argumentCount + 1
ofObject: activeContext
toIndex: TempFrameStart
ofObject: blockContext.
"Assume: The call to transfer:... makes blockContext a root if necessary,
allowing use to use unchecked stored in the following code."
self pop: argumentCount + 1.
initialIP _ self fetchPointer: InitialIPIndex ofObject: blockContext.
self storePointerUnchecked: InstructionPointerIndex ofObject: blockContex=
t
withValue: initialIP.
self storeStackPointerValue: argumentCount inContext: blockContext.
self storePointerUnchecked: CallerIndex ofObject: blockContext
withValue: activeContext.
self newActiveContext: blockContext]!
primitiveValueWithArgs
| argumentArray blockContext blockArgumentCount arrayArgumentCount=
initialIP |
argumentArray _ self popStack.
blockContext _ self popStack.
blockArgumentCount _ self argumentCountOfBlock: blockContext.
self assertClassOf: argumentArray is: (self splObj: ClassArray).
successFlag ifTrue: [
arrayArgumentCount _ self fetchWordLengthOf: argumentArray.
self success: (arrayArgumentCount =3D blockArgumentCount
and: [(self fetchPointer: CallerIndex ofObject: blockContext) =3D nilObj]=
)].
successFlag ifTrue: [
self transfer: arrayArgumentCount
fromIndex: 0
ofObject: argumentArray
toIndex: TempFrameStart
ofObject: blockContext.
"Assume: The call to transfer:... makes blockContext a root if necessary,
allowing use to use unchecked stored in the following code."
initialIP _ self fetchPointer: InitialIPIndex ofObject: blockContext.
self storePointerUnchecked: InstructionPointerIndex ofObject: blockContext
withValue: initialIP.
self storeStackPointerValue: arrayArgumentCount inContext: blockContext.
self storePointerUnchecked: CallerIndex ofObject: blockContext
withValue: activeContext.
self newActiveContext: blockContext.
] ifFalse: [self unPop: 2].! !
--============_-1348667088==_============
Content-Type: text/plain; name="ChangeSetCommentFix.st"; charset="us-ascii"
Content-Disposition: attachment; filename="ChangeSetCommentFix.st"
'From Squeak 1.19d of April 13, 1997 on 11 May 1997 at 4:46:17 pm'!
!ChangeSet methodsFor: 'private'!
fileOutClassModifications: class on: stream
"Write out class mod-- rename, comment, reorg, remove, on the given stream. Differs from the superseded fileOutClassChanges:on: in that it does not deal with class definitions, and does not file out entire added classes. 5/15/96 sw
10/28/96 sw: put out a rename indicator that won't halt if class of old name not there."
(self atClass: class includes: #rename) ifTrue:
[stream nextChunkPut: 'Smalltalk renameClassNamed: #', (self oldNameFor: class), ' as: #', class name; cr].
(self atClass: class includes: #comment) ifTrue:
[class theNonMetaClass organization putCommentOnFile: stream
numbered: nil moveSource: false.
stream cr].
(self atClass: class includes: #reorganize) ifTrue:
[class fileOutOrganizationOn: stream.
stream cr]! !
--============_-1348667088==_============--
Date: 97 May 12 8:35:47 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Squeak@create.ucsb.edu
Subject: Pure Rectangles and Points
I have another, larger, fileIn with which I shall not burden everyone, but I thought I'd announce its availability in case anyone wants it.
This fileIn removes some 40 methods that cause side-effects to points and rectangles, and redefines about 50 methods so that they replace with copies instead of using side-effects. This was very satisfying to do.
My feeling (and my experience) is that this more functional coding style is less prone to errors, and I intend to include these changes in the next release of Squeak. Let me know if you would like an advanced copy now.
- Dan
P.S. I'm also interested in a Squeak variant that *always* uses side-effects for change (for high performance), but I don't think it makes such a good general purpose programming language.
Date: 97 May 12 8:46:31 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
In-Reply-To: <v03102800af9cd0d6b708@[129.34.225.178]>
Subject: Re: Float #hash method LONG and DULL
At 10:08 -0400 5/12/97, David N. Smith wrote:
>At 6:01 -0400 5/12/97, Wim Boot wrote:
>>David N. Smith wrote:
>>
>>>All float fans:
>>>
>>>The Float hash method seems left over from olden days where small integers
>>>were 16K or so. It uses only one part of the float, possibly giving quite
>>>different answers depending on byte ordering.
>>
>>Indeed. There are worse (very ancient) problems however.
>>
>>Try "1 hash = 1.0 hash" or "(3/2) hash = 1.5 hash". False in
>>both cases, though "1 = 1.0" and "(3/2) = 1.5" both yield true.
>>
>>Your hashDNS method doesn't address this problem either.
>>
>>Wim Boot
>
>Wim:
>
>Maybe I'm missing something, but I wouldn't expect two different objects to
>have the same hash just because they have the same 'value'. (3/2) is a
>completely different object than 1.5
>
>How about:
>
> 'abc' = #abc
> true
>
> 'abc' hash = #abc hash
> false
>
>Should the hash of a string always be the hash of a symbol containing the
>same characters? Symbols are typically guaranteed to have different hashes
>for different values; strings are not because of the expense in many
>implementations.
>
>dave
Sorry, it was before coffee. I know better.
However, I only tested it in Squeak and that's what it answers!
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 9:27:32 am
From: Maloney <johnm@wdi.disney.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: squeak@create.ucsb.edu
In-Reply-To: <v03102805af9b9e000ef8@[129.34.225.178]>
Subject: Float Byte Ordering
Re:
>The Float hash method seems left over from olden days where small integers
>were 16K or so. It uses only one part of the float, possibly giving quite
>different answers depending on byte ordering.
Just so everyone knows, in the 1.18 Squeak release we made Squeak Floats
keep the same byte ordering (IEEE standard) on all platforms. On machines
whose hardware floats have a different byte ordering, the bytes are swapped
just before doing a float operation. (This turned out to not take significant
additional time because we had to deal with the possibility of misaligned
floats so had to move the float into a temporary variable before operating
on it anyway.)
So, the the byte ordering of Squeak Floats is the same on all platforms; it
is safe to depend on it.
-- John
P.S. Thanks for your ongoing contributions to improving Squeak's number
classes, Dave!
Date: 97 May 12 9:32:43 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: johnson@cs.uiuc.edu (Ralph E. Johnson)
Cc: squeak@create.ucsb.edu
In-Reply-To: <v01540b0daf9c885e9858@[130.126.27.213]>
Subject: Re: Float #hash method LONGer and DULLer
At 10:44 -0400 5/12/97, Ralph E. Johnson wrote:
>At 10:08 AM 5/12/97, David N. Smith wrote:
>>Maybe I'm missing something, but I wouldn't expect two different objects to
>>have the same hash just because they have the same 'value'. (3/2) is a
>>completely different object than 1.5
>
>Sets and dictionaries assume that equal objects hash equally. Suppose
>x and y are two objects that are equal but have different hashes. If
>you put x in a set and ask whether the set includes y, the answer will
>be false unless x and y just happened to hash into the same location, in
>which the answer is true. So, if you redefine = then you should redefine
>hash.
>
>-Ralph
Ralph:
OK, I forgot. It is true that any two objects that answer true to #= should
answer the same #hash value so that certain collections work. Duh! I knew
that; I even have the T-Shirt!
But, now that I've been caught, I'd like to argue that this is a poor rule.
First, some rubber on the road...
I just ran these two tests. Booleans in comments are the results to that point.
------------------------------------
First, Squeak 1.19 (using the original hash):
| s |
s := Set new.
s add: 1.5.
s includes: (3/2). "false"
s add: (3/2).
s includes: (3/2). "true"
s inject: OrderedCollection new into: [ :inj :elem | inj add: elem. inj ]
OrderedCollection (1.5 (3/2) )
| b |
b := Bag new.
b add: 1.5.
b includes: (3/2). "false"
b add: (3/2).
b includes: (3/2). "true "
b inject: OrderedCollection new into: [ :inj :elem | inj add: elem. inj ]
OrderedCollection (1.5 (3/2) )
These act like I think they should act, even if it is due to broken #hash
methods. Both the Set and the Bag have two elements of two different
classes.
------------------------------------
Then VW 2.5 and IBM Smalltalk V3::
| s |
s := Set new.
s add: 1.5.
s includes: (3/2). "true"
s add: (3/2).
s includes: (3/2). "true"
s inject: OrderedCollection new into: [ :inj :elem | inj add: elem. inj ]
OrderedCollection (1.5)
| b |
b := Bag new.
b add: 1.5.
b includes: (3/2). "true"
b add: (3/2).
b includes: (3/2). "true "
b inject: OrderedCollection new into: [ :inj :elem | inj add: elem. inj ]
OrderedCollection (1.5 1.5)
I find this bizare in the extreme: I add a Fraction and it goes away!
But notice what happens if I add the elements in the other order (VW 2.5):
| s |
s := Set new.
s add: (3/2).
s includes: 1.5. "true"
s add: 1.5.
s includes: 1.5. "true"
s inject: OrderedCollection new into: [ :inj :elem | inj add: elem. inj ]
OrderedCollection ((3/2))
Now the float goes away! (I assume IBM/ST does the same thing.)
------------------------------------
However, change the data a little and one gets (on VW 2.5):
| s |
s := Set new.
s add: 0.12499999886094d.
s includes: (13717421/109739369). " false"
s add: (13717421/109739369).
s includes: (13717421/109739369). "true"
s inject: OrderedCollection new into: [ :inj :elem | inj add: elem. inj ]
OrderedCollection (0.12499999886094d (13717421/109739369))
Yet, converting the fraction to a Double (with asDouble) answers the
floating point number. (It's probably off just in the last bit, but try to
explain to a newby why one sometimes gets two elements and sometimes one.)
-------------------------------------
There is no way to get it right with floating point numbers. One can always
find some situation where computing a float provides a different result
than an 'equivalent' literal.
While it might be traditional to define hash and equality as they are, it
leads to counterintuitive results (adding two different objects to a Set
should always result in a set with either one or two objects and not a
capricious sometimes it has two but maybe not), and it leads to horrible
hash values. IBM Smalltalk achieves its equality of hashes by ignoring
fractional parts. Float hash answers self truncated. Blah.
I once ran a test of a Dictionary and the 'new' LookupTable class in IBM
Smalltalk V3 to see if LookupTable was truly faster, as claimed. I
generated a large number of random numbers in the default range [0.0-1.0)
and threw them at instances of each class. The results were horrible. Both
went out to lunch, or I did anyhow, as I waited for the tests to finish.
Since hash for floats was defined as 'self truncated', EVERY key was 0.0.
Both instances were doing lots of sequential lookups.
Is some rule that two different objects have the same hash when some idea
of value equality is met worth ruining the quality of hashes for their
intended purpose as keys in collections?
There is no way to get it right. Large integers, and fractions made up of
large integers are really different objects than their floating point
'equivalents'. So are scaled decimal values and float values that 'look the
same'.
-------------------
So, what to do? Keep with tradition and live with the bizare results (and
bad collection performance?) Or fix this mess? Can it be fixed?
Is it reaonable to add an 'equal' fraction and float to a Set and usually
get one element but not always?
Can hash and #= be decoupled without wrecking some basic assumptions (other
than in hashed collections?) IE, what else am I missing?
Could we add a trueEquality: method in Object and require all users of hash
to use it to compare two objects for equality?
trueEquality: anObject
^ self class == anObject class
and: [ self = anObject ]
or, better, something like:
trueEquality: anObject
^ (self classesAreEquivalent: anObject)
and: [ self = anObject ]
classesAreEquivalent: anObject
^ self class == anObject class
which lets subclasses redefine class equivalence if and as needed.
Hashing is too important to let the equality rule force bad hashes;
esoteric rules should not compromise day-to-day performance.
The current situation is ugly, if traditional, and maybe should be properly
fixed in Squeak rather than just keeping the traditional solution. Hashing
is clearly broken in Squeak in its current state.
Or am I still missing something?
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 9:39:32 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Hans-Martin Mosner <hmm@heeg.de>
Cc: squeak@create.ucsb.edu
In-Reply-To: <3377309D.31DFF4F5@heeg.de>
Subject: Re: Float #hash method LONG and DULL
At 11:00 -0400 5/12/97, Hans-Martin Mosner wrote:
>David N. Smith wrote:
>>
> ...snip...
>
>> How about:
>>
>> 'abc' = #abc
>> true
>Should not be. Someone on this list acknowleged that it's a bug, because
>#abc ~= 'abc'. Equality should work both ways.
>>
>> 'abc' hash = #abc hash
>> false
>>
>> Should the hash of a string always be the hash of a symbol containing the
>> same characters?
>No, because that would be impossible. Symbols just have arbitrary hash
>values
>that are not related to their constituent characters.
That's what I was trying to say...
>(Which is probably bad for object migration. Setting the hash value of
>a Symbol from the CRC of its characters might be better)
>
>> Symbols are typically guaranteed to have different hashes
>> for different values;
>No, Symbols are just guaranteed to be unique, that is, two
>Symbols are the same object if and only if they have the same
>characters.
>Symbols (like other Objects) are guaranteed to have same hashes
>for same values, though.
Again, that's what I was trying to say...
>
>> strings are not because of the expense in many
>> implementations.
>For Symbols, hash is synonymous to identity hash (which is logical,
>since
>equality for Symbols is synonymous to identity)
>For Strings, hash is a fast (and some say, bad) function of
>the characters in the string.
>
>Hans-Martin
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 9:44:57 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Dan Ingalls <DanI@wdi.disney.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v03007800af9cf60e73e8@[206.16.10.79]>
Subject: Re: Three fileIns
At 12:43 -0400 5/12/97, Dan Ingalls wrote:
>NumberFixes-di.cs
>Three fixes to Float, suggested or requested by David Smith. Eliminates
>amgiguity of non-decimal constants by requiring letter-digits to be
>uppercase, and fixes two methods that used lowercase hex digits (thanks
>tim). Renames the old asFraction code to be asApproximateFraction, and
>installs David's asTrueFraction as well. Finally includes David's
>improvement to Float>>hash.
If there is a list somewhere of platform dependencies in Smalltalk code, it
should note that #asTrueFraction is Endian sensitive...
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 9:50:21 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Maloney <johnm@wdi.disney.com>
Cc: squeak@create.ucsb.edu
In-Reply-To: <v03007801af9cff1a63f1@[206.16.10.208]>
Subject: Re: Float Byte Ordering
At 13:17 -0400 5/12/97, Maloney wrote:
>Re:
>>The Float hash method seems left over from olden days where small integers
>>were 16K or so. It uses only one part of the float, possibly giving quite
>>different answers depending on byte ordering.
>
>Just so everyone knows, in the 1.18 Squeak release we made Squeak Floats
>keep the same byte ordering (IEEE standard) on all platforms. On machines
>whose hardware floats have a different byte ordering, the bytes are swapped
>just before doing a float operation. (This turned out to not take significant
>additional time because we had to deal with the possibility of misaligned
>floats so had to move the float into a temporary variable before operating
>on it anyway.)
>
>So, the the byte ordering of Squeak Floats is the same on all platforms; it
>is safe to depend on it.
>
> -- John
>
>P.S. Thanks for your ongoing contributions to improving Squeak's number
>classes, Dave!
John:
Neat! Dan can then safely ignore my post of 2 minutes ago, but the comment
in #trueFraction should be changed.
asTrueFraction
" Answer a fraction that EXACTLY represents self,
a double precision IEEE floating point number.
(It tears an IEEE float into its components;
since Squeak always stores Floats in the same
order, this should work on all IEEE platforms.)
Thanks to David N. Smith"
| shifty sign exp fraction |
shifty := ((self at: 1) bitShift: 32) bitOr: (self at: 2).
sign := (shifty bitShift: -63) = 0 ifTrue: [1] ifFalse: [-1].
exp := (shifty >> 52) bitAnd: 16r7FF.
fraction := shifty bitAnd: 16r000FFFFFFFFFFFFF.
(exp = 0) & (fraction = 0) ifTrue: [ ^ 0 ].
fraction := fraction bitOr: 16r0010000000000000.
exp := exp - 16r3FF.
" Validate that the dismemberment was correct "
(sign * fraction / (2 raisedToInteger: 52 - exp)) asFloat = self
ifFalse: [self error: 'asFraction validation failed' ].
^ sign * fraction / (2 raisedToInteger: 52 - exp)! !
Dave
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 12 10:32:49 am
From: johnson@cs.uiuc.edu (Ralph E. Johnson)
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: squeak@create.ucsb.edu
Subject: Re: Float #hash method LONGer and DULLer
At 1:00 PM 5/12/97, David N. Smith wrote:
>There is no way to get it right. Large integers, and fractions made up of
>large integers are really different objects than their floating point
>'equivalents'. So are scaled decimal values and float values that 'look the
>same'.
>So, what to do? Keep with tradition and live with the bizare results (and
>bad collection performance?) Or fix this mess? Can it be fixed?
What to do? You should write an OOPSLA paper!
>Is it reaonable to add an 'equal' fraction and float to a Set and usually
>get one element but not always?
No. Either always one, or never one, but "usually but not always" is
horrendous!
>Can hash and #= be decoupled without wrecking some basic assumptions (other
>than in hashed collections?) IE, what else am I missing?
I think hashed collections are the only place that makes that assumption.
That is a pretty big "only", however.
-Ralph
Date: 97 May 13 9:45:59 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Squeak@create.ucsb.edu
Subject: Two other tidbits
--============_-1348575084==_============
Content-Type: text/plain; charset="us-ascii"
NewLabels gives our windows a new look -- not Mac-like, not Windows-like. A very simple change.
BBFix32 is Andreas Raab's fix for 32-bit color on machines that wrap shifts greater than 31. It should have been included in my last VMchanges file.
--============_-1348575084==_============
Content-Type: text/plain; name="NewLabels-di.cs"; charset="us-ascii"
Content-Disposition: attachment; filename="NewLabels-di.cs"
'From Squeak 1.19d of April 13, 1997 on 2 May 1997 at 4:07:16 pm'!
!StandardSystemView methodsFor: 'label access'!
setLabelRegion
"Always follows view width"
labelFrame region: (0 @ 0 extent: self displayBox width @ self labelHeight).
! !
!StandardSystemView methodsFor: 'displaying'!
deEmphasizeLabel
"Un-Highlight the label."
self displayLabelBackground: false.
self displayLabelText.!
displayLabelBackground: emphasized
"Clear or emphasize the inner region of the label"
| r1 r2 r3 c3 c2 c1 |
emphasized ifFalse:
["Just clear the label if not emphasized"
^ Display fill: (self labelDisplayBox insetBy: 2) fillColor: self labelColor].
r1 _ self labelDisplayBox insetBy: 2.
r2 _ r1 insetBy: 0@2.
r3 _ r2 insetBy: 0@3.
c3 _ self labelColor.
c2 _ c3 darker.
c1 _ c2 darker darker.
Display fill: r1 fillColor: c1.
Display fill: r2 fillColor: c2.
Display fill: r3 fillColor: c3.
" Here is the Mac racing stripe code
stripes _ Bitmap with: (self labelColor pixelWordForDepth: Display depth)
with: (Form black pixelWordForDepth: Display depth).
self windowOrigin y even ifTrue: [stripes swap: 1 with: 2].
Display fill: (self labelDisplayBox insetBy: 3) fillColor: stripes.
"!
displayLabelText
"The label goes in the center of the window"
| labelRect |
labelText foregroundColor: self foregroundColor
backgroundColor: self labelColor.
labelRect _ self labelTextRegion.
Display fill: (labelRect expandBy: 3@0) fillColor: self labelColor.
labelText displayOn: Display at: labelRect topLeft clippingBox: labelRect
rule: labelText rule fillColor: labelText fillColor!
emphasizeLabel
"Highlight the label."
self displayLabelBackground: true.
self displayLabelBoxes.
self displayLabelText.! !
StandardSystemView removeSelector: #displayRacingStripes!
--============_-1348575084==_============
Content-Type: text/plain; name="BBFix32.cs"; charset="us-ascii"
Content-Disposition: attachment; filename="BBFix32.cs"
'From Squeak 1.19d of April 13, 1997 on 13 May 1997 at 8:22:05 am'!
!BitBltSimulation methodsFor: 'inner loop'!
copyLoopPixMap
"This version of the inner loop maps source pixels
to a destination form with different depth. Because it is already
unweildy, the loop is not unrolled as in the other versions.
Preload, skew and skewMask are all overlooked, since pickSourcePixels
delivers its destination word already properly aligned.
Note that pickSourcePixels could be copied in-line at the top of
the horizontal loop, and some of its inits moved out of the loop."
| skewWord halftoneWord mergeWord destMask srcPixPerWord scrStartBits nSourceIncs startBits endBits sourcePixMask destPixMask nullMap |
self inline: false.
"Additional inits peculiar to unequal source and dest pix size..."
srcPixPerWord _ 32//sourcePixSize.
"Check for degenerate shift values 4/28/97 ar"
sourcePixSize = 32
ifTrue: [ sourcePixMask _ -1]
ifFalse: [ sourcePixMask _ (1 << sourcePixSize) - 1].
destPixSize = 32
ifTrue: [ destPixMask _ -1]
ifFalse: [ destPixMask _ (1 << destPixSize) - 1].
nullMap _ colorMap = interpreterProxy nilObject.
sourceIndex _ (sourceBits + 4) +
(sy * sourceRaster + (sx // srcPixPerWord) *4).
scrStartBits _ srcPixPerWord - (sx bitAnd: srcPixPerWord-1).
bbW < scrStartBits
ifTrue: [nSourceIncs _ 0]
ifFalse: [nSourceIncs _ (bbW - scrStartBits)//srcPixPerWord + 1].
sourceDelta _ (sourceRaster - nSourceIncs) * 4.
"Note following two items were already calculated in destmask setup!!"
startBits _ pixPerWord - (dx bitAnd: pixPerWord-1).
endBits _ ((dx + bbW - 1) bitAnd: pixPerWord-1) + 1.
1 to: bbH do: "here is the vertical loop"
[ :i |
noHalftone
ifTrue: [halftoneWord _ AllOnes]
ifFalse: [halftoneWord _ interpreterProxy longAt: (halftoneBase + (dy+i-1 \\ halftoneHeight * 4))].
srcBitIndex _ (sx bitAnd: srcPixPerWord - 1)*sourcePixSize.
destMask _ mask1.
"pick up first word"
bbW < startBits
ifTrue: [skewWord _ self pickSourcePixels: bbW nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask.
skewWord _ skewWord
bitShift: (startBits - bbW)*destPixSize]
ifFalse: [skewWord _ self pickSourcePixels: startBits nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask].
"Here is the horizontal loop..."
1 to: nWords do: "here is the inner horizontal loop"
[ :word |
mergeWord _ self merge: (skewWord bitAnd: halftoneWord)
with: ((interpreterProxy longAt: destIndex) bitAnd: destMask).
interpreterProxy longAt: destIndex
put: ((destMask bitAnd: mergeWord)
bitOr:
(destMask bitInvert32 bitAnd: (interpreterProxy longAt: destIndex))).
destIndex _ destIndex + 4.
word >= (nWords - 1) ifTrue:
[word = nWords ifFalse:
["set mask for last word in this row"
destMask _ mask2.
skewWord _ self pickSourcePixels: endBits nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask.
skewWord _ skewWord
bitShift: (pixPerWord-endBits)*destPixSize]]
ifFalse:
["use fullword mask for inner loop"
destMask _ AllOnes.
skewWord _ self pickSourcePixels: pixPerWord nullMap: nullMap srcMask: sourcePixMask destMask: destPixMask]].
sourceIndex _ sourceIndex + sourceDelta.
destIndex _ destIndex + destDelta]! !
!BitBltSimulation methodsFor: 'pixel mapping'!
warpSourcePixels: nPix xDeltah: xDeltah yDeltah: yDeltah
xDeltav: xDeltav yDeltav: yDeltav
smoothing: n sourceMap: sourceMapOop
"Pick nPix pixels using these x- and y-incs, and map color if necess."
| destWord sourcePix sourcePixMask destPixMask srcPixPerWord destPix |
"Fix degenerate shift values 4/28/97 ar"
sourcePixSize = 32
ifTrue: [ sourcePixMask _ -1]
ifFalse: [ sourcePixMask _ (1 << sourcePixSize) - 1].
destPixSize = 32
ifTrue: [ destPixMask _ -1]
ifFalse: [ destPixMask _ (1 << destPixSize) - 1].
srcPixPerWord _ 32 // sourcePixSize.
destWord _ 0.
1 to: nPix do:
[:i |
n > 1
ifTrue:
["Average n pixels and compute dest pixel from color map"
destPix _ (self smoothPix: n atXf: sx yf: sy
dxh: xDeltah//n dyh: yDeltah//n dxv: xDeltav//n dyv: yDeltav//n
pixPerWord: srcPixPerWord pixelMask: sourcePixMask
sourceMap: sourceMapOop)
bitAnd: destPixMask]
ifFalse:
["No smoothing -- just pick pixel and map if difft depths or color map supplied"
sourcePix _ (self sourcePixAtX: sx >> BinaryPoint
y: sy >> BinaryPoint
pixPerWord: srcPixPerWord)
bitAnd: sourcePixMask.
colorMap = interpreterProxy nilObject
ifTrue:
[destPixSize = sourcePixSize
ifTrue:
[destPix _ sourcePix]
ifFalse:
[sourcePixSize >= 16 ifTrue:
["Map between RGB pixels"
sourcePixSize = 16
ifTrue: [destPix _ self rgbMap: sourcePix from: 5 to: 8]
ifFalse: [destPix _ self rgbMap: sourcePix from: 8 to: 5]]
ifFalse: [destPix _ sourcePix bitAnd: destPixMask]]]
ifFalse:
[sourcePixSize >= 16 ifTrue:
["RGB pixels first get reduced to cmBitsPerColor"
sourcePixSize = 16
ifTrue: [sourcePix _ self rgbMap: sourcePix from: 5 to: cmBitsPerColor]
ifFalse: [sourcePix _ self rgbMap: sourcePix from: 8 to: cmBitsPerColor]].
"Then look up sourcePix in colorMap"
destPix _ (interpreterProxy fetchWord: sourcePix ofObject: colorMap) bitAnd: destPixMask]].
destWord _ (destWord << destPixSize) bitOr: destPix.
sx _ sx + xDeltah.
sy _ sy + yDeltah.
].
^ destWord! !
--============_-1348575084==_============--
Date: 97 May 13 11:36:18 pm
From: "Ted K." <tedk@wdi.disney.com>
To: squeak@create.ucsb.edu
Subject: Squeak collaboration
(AgentBase is Michael Korns' very large lisp-based database integrator. A neat system. -tk)
>From: "Michael Korns" <mkorns@ix.netcom.com>
>To: "Ted Kaehler" <kaehler2@webpage.com>
>Subject: Squeak collaboration
>Date: Tue, 13 May 1997 10:13:34 -0700
>
>Ted,
>
>There is an internet interest group forming to discuss the construction of
>a Universal Virtual Machine which would run Java, Lisp, Smalltalk, Prolog,
>etc. agents across the net.
>
>AgentBase is participating in these initial discussions, and would like to
>be able to provide persistence and server execution for agents developed in
>the above languages (as well as SmartLisp).
>
>I'm wondering if you could send me the URL where I can down load the latest
>copy of Squeak? Would you be willing to lend guidance and technical
>consulting if we tried to enhance AgentBase to support Squeak
>agents/applets?
>
>I'll call later to talk.
>
>
>**************************************
>Michael F. Korns
>214 Shorebreaker
>Laguna Niguel, California 92677
>(714) 443-4847
>mkorns@ix.netcom.com
>*************************************
>
Ted Kaehler
Walt Disney Imagineering, R&D
(home) 3415 Cork Oak Way, Palo Alto, CA 94303
voice (415) 424-1070
http://www.webPage.com/~kaehler2/
Date: 97 May 14 12:27:21 am
From: mack@sfo.com (Michael Ackerman)
To: squeak@create.ucsb.edu
Subject: Which Smalltalk is Squeak?
I am new to Smalltalk and Squeak. I understand that Squeak is "basically"
Smalltalk-80, but I have read that Smalltalk-80 comes in two versions, and
that the 2nd version supports multiple inheritance, while the first does
not. Which version is Squeak most like?
Thanks.
Michael Ackerman
Date: 97 May 14 7:31:15 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Casing the joint
To whom, etc:
Two methods in Object, #case: and #case:otherwise: seem not to be used
anywhere in the image (1.19d).
Are they still needed?
They seem to take a parameter that is an instance of
BlockAssociationCollection but there is no class with that name.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 14 7:33:35 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: mack@sfo.com (Michael Ackerman)
Cc: squeak@create.ucsb.edu
In-Reply-To: <v01510101af9f2d932341@[207.33.216.22]>
Subject: Re: Which Smalltalk is Squeak?
At 4:55 -0400 5/14/97, Michael Ackerman wrote:
>I am new to Smalltalk and Squeak. I understand that Squeak is "basically"
>Smalltalk-80, but I have read that Smalltalk-80 comes in two versions, and
>that the 2nd version supports multiple inheritance, while the first does
>not. Which version is Squeak most like?
> Thanks.
>
>Michael Ackerman
Michael:
I'm probably not the right person to answer this, but to my knowledge the
MI code in Smalltalk-80 worked but no one used it. Squeak does not support
it to the best of my knowledge.
Why? Because, unlike C++ where MI seems to be important for reasons I don't
quite get, it is not important in Smalltalk. The arguments have raged for
years, and there have been implementations, but when the rubber hits the
road no one really uses MI in Smalltalk.
SELF, a "Smalltalk variant" :), has MI; maybe one of the SELFers here can
speak about it.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 14 9:11:08 am
From: Hans-Martin Mosner <hmm@heeg.de>
To: Squeak Mailing List <squeak@create.ucsb.edu>
Subject: Morphic Menus, and 8-bit color dithering
This is a multi-part message in MIME format.
--------------64880EEB773C24486F5992E1
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hello,
here is a first implementation of morphic menus. You'll probably like
them, although they're a little slow on low-end machines.
Another goodie: dithering for 8-bit color. Makes the #lighter and
#darker colors look much better...
--------------64880EEB773C24486F5992E1
Content-Type: text/plain; charset=us-ascii; name="Color-dithering.st"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="Color-dithering.st"
!Color methodsFor: 'conversions'!
bitPatternForDepth: depth
"The raw call on BitBlt needs a Bitmap to represent this color. Return the color at the destination Form depth as a Bitmap. Patterns return longer Bitmaps. 6/14/96 tk
For the bits that are in a single pixel, use pixelValueAtDepth:.
For a 32-bit integer of (32/depth) pixels, use pixelWordAtDepth:"
| brightness |
depth == cachedDepth ifTrue: [^ cachedBitPattern].
cachedDepth := depth.
depth > 1 ifTrue: [^ cachedBitPattern := self computeBitPatternForDepth: depth].
"Spatial halftones for depth 1"
brightness := self luminance.
brightness < 0.2 ifTrue: [
^ cachedBitPattern := Bitmap with: 16rFFFFFFFF]. "black"
brightness < 0.4 ifTrue: [
^ cachedBitPattern := Bitmap with: 16rBBBBBBBB with: 16rEEEEEEEE]. "dark gray"
brightness < 0.6 ifTrue: [
^ cachedBitPattern := Bitmap with: 16r55555555 with: 16rAAAAAAAA]. "medium gray"
brightness < 0.8 ifTrue: [
^ cachedBitPattern := Bitmap with: 16r44444444 with: 16r11111111]. "light gray"
^ cachedBitPattern := Bitmap with: 16r0. "white"!
computeBitPatternForDepth: depth
| pixels |
depth = 8 ifFalse: [^Bitmap with: (self pixelWordForDepth: depth)].
pixels := self fourPixelValuesForDither: depth.
^Bitmap
with: (16r10001 * (pixels at: 1)) + (16r1000100 * (pixels at: 3))
with: (16r10001 * (pixels at: 4)) + (16r1000100 * (pixels at: 2))!
fourPixelValuesForDither: depth
| r g b rPlus gPlus bPlus |
depth = 8 ifFalse: [^Array new: 4 withAll: (self pixelValueForDepth: depth)].
rgb = 0 ifTrue: [^ Array new: 4 withAll: 1]. "Special case for black, very common"
rgb = 16r3FFFFFFF ifTrue: [^ Array new: 4 withAll: 0 "255"]. "Special case for white, very common"
self privateRed = self privateGreen ifTrue: [
self privateRed = self privateBlue ifTrue: [^Array new: 4 withAll: self closestPixelValue8]].
r := (self privateRed * 5) // ComponentMask.
g := (self privateGreen * 5) // ComponentMask.
b := (self privateBlue * 5) // ComponentMask.
rPlus := (self privateRed * 5) \\ ComponentMask
* 4 + HalfComponentMask // ComponentMask.
gPlus := (self privateGreen * 5) \\ ComponentMask
* 4 + HalfComponentMask // ComponentMask.
bPlus := (self privateBlue * 5) \\ ComponentMask
* 4 + HalfComponentMask // ComponentMask.
^(1 to: 4) collect: [:i |
(r + (i > rPlus ifTrue: [0] ifFalse: [1]) * 36) +
(b + (i > bPlus ifTrue: [0] ifFalse: [1]) * 6) +
(g + (i > gPlus ifTrue: [0] ifFalse: [1])) + 40]
! !
--------------64880EEB773C24486F5992E1
Content-Type: text/plain; charset=us-ascii; name="MorphicMenus.cs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="MorphicMenus.cs"
'From Squeak 1.19d of April 13, 1997 on 14 May 1997 at 4:35:18 pm'!
StringMorph subclass: #MenuItemMorph
instanceVariableNames: 'action flags subMenu '
classVariableNames: 'SubMenuMarker '
poolDictionaries: ''
category: 'Morphic-Menus'!
Morph subclass: #MenuLineMorph
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Menus'!
LayoutMorph subclass: #MenuMorph
instanceVariableNames: 'lastSelection receiver popUpOwner '
classVariableNames: ''
poolDictionaries: ''
category: 'Morphic-Menus'!
!Object methodsFor: 'menus'!
dispatchAsMenuActionTo: anObject
"Don't know what to do..."!
performMenuAction: anObject
^anObject dispatchAsMenuActionTo: self!
performMenuAction: anObject with: argument
^anObject dispatchAsMenuActionTo: self with: argument! !
!BlockContext methodsFor: 'menus'!
dispatchAsMenuActionTo: anObject
^self numArgs = 0
ifTrue: [self value]
ifFalse: [self value: anObject]!
dispatchAsMenuActionTo: anObject with: argument
^self numArgs = 0
ifTrue: [self value]
ifFalse: [self numArgs = 1
ifTrue: [self value: anObject]
ifFalse: [self value: anObject value: argument]]!
performMenuAction: anObject
self value: anObject! !
!HandMorph methodsFor: 'event dispatching'!
handleMouseUp: evt
| oldFocus |
mouseFocus = nil ifTrue: [^ self dropMorphsEvent: evt]. "drop morphs being carried, if any"
"ensure that at least one mouseMove: is reported for each mouse focus transaction:"
mouseFocus mouseMove: (self transformEvent: (evt copy setType: #mouseMove)).
oldFocus := mouseFocus. "make sure that focus becomes nil."
mouseFocus _ nil. "mouse focus transaction ends when mouse goes up"
oldFocus mouseUp: (self transformEvent: evt).
! !
!HandMorph methodsFor: 'meta menu'!
buildMetaMenu
"Build the meta menu. This menu has two sections. The first section contains commands that are interpreted by the hand itself; the second contains commands provided by the morph itself. Each entry contains a string to be presented in the menu and a symbol to be sent to either the hand itself (for commands in the first section) or to the morph provided the menu (for commands in the second section). If a selector takes an argument, the mouse-down event that invoked the menu is provided. This lets the command know which hand invoked it in order to do things like attaching the result of the command to that hand."
| menu arg |
menu _ MenuMorph new.
arg _ self argumentOrNil.
arg == nil ifTrue: [
menu add: 'new morph' action: #newMorph.
menu add: 'new parts bin' action: #newPartsBin.
menu add: 'new drawing' action: #makeNewDrawing.
menu add: 'change background color' action: #changeBackgroundColor.
menu addLine.
menu add: 'parts bin' action: #partsBin.
menu add: 'run all' action: #startRunningAll.
menu add: 'stop all' action: #stopRunningAll.
menu addLine.
menu add: 'add control variable ' action: #newVariable.
menu add: 'save as model ' action: #saveAsModel.
menu add: 'save as world' action: #saveAsWorld.
menu addLine.
menu add: 'inspect this world' action: #inspectWorld.
lastMetaMenuItem _ menu selections size.
^ menu].
menu add: 'grab' action: #grabMorph.
menu add: 'dismiss' action: #dismissMorph.
menu add: 'go behind' action: #goBehind.
menu add: 'duplicate' action: #duplicateMorph.
((self world rootMorphsAt: targetOffset) size > 1)
ifTrue: [menu add: 'embed' action: #embedMorph].
menu add: 'grab or extract' action: #extractMorph.
menu add: 'inspect' action: #inspectMorph.
menu add: 'browse' action: #browseMorphClass.
menu add: 'make own subclass' action: #subclassMorph.
menu addLine.
arg isMouseSensor
ifTrue: [menu add: 'desensitize' action: #desensitizeMorph]
ifFalse: [menu add: 'sensitize' action: #sensitizeMorph].
arg nameInModel ifNil: [
menu add: 'name me' action: #nameMorph].
menu addLine.
(arg isKindOf: SketchMorph) ifFalse: [
(arg isKindOf: StringMorph) ifFalse: [
menu add: 'resize' action: #resizeMorph.
].
menu add: 'fill color' action: #changeColor.
].
menu addLine.
lastMetaMenuItem _ menu selections size.
arg addCustomMenuItems: menu hand: self.
^ menu
!
invokeMetaMenu: evt
| menu caption receiver saveTargetOffset |
targetOffset _ saveTargetOffset _ self position.
menu _ self buildMetaMenu.
self argumentOrNil == nil
ifTrue: [caption _ 'World']
ifFalse: [caption _ self argumentOrNil class name].
menu addTitle: caption.
menu lastSelectionAction: lastMenuSelection.
menu popUpOwner: self.
menu receiver: [:item |
targetOffset _ saveTargetOffset.
menu delete.
owner displayWorld.
item ifNotNil: [
lastMenuSelection _ item.
receiver := (menu selections indexOf: item) <= lastMetaMenuItem
ifTrue: [self]
ifFalse: [self argumentOrNil].
Cursor normal showWhile: [receiver performMenuAction: item with: evt]]].
menu popUpAt: evt cursorPoint in: owner.
self newMouseFocus: menu items first!
newMorph
| morphClassList menu categories subMenu |
menu _ MenuMorph new.
menu addTitle: 'Select Morph Class'.
morphClassList _ Morph withAllSubclasses asSortedCollection:
[:m1 :m2 | m1 class name < m2 class name].
morphClassList remove: WorldMorph;
remove: HandMorph;
remove: MorphicModel;
remove: RemoteHandMorph.
morphClassList := morphClassList select:
[:c | (c inheritsFrom: MorphicModel) not or:
["Only include Models that have been saved"
c includesSelector: #initMorph]].
categories := (morphClassList collect: [:each | each category]) asSet asSortedCollection.
categories do: [:cat |
subMenu := MenuMorph new.
subMenu receiver: [:cls | self newMorphOfClass: cls].
morphClassList do: [:each |
each category = cat ifTrue: [subMenu add: each name action: each]].
menu add: cat subMenu: subMenu].
menu popUpOwner: self.
menu popUpAt: self position in: owner!
newMorphOfClass: morphClass
"taken out of the old method #newMorph"
| m |
m _ morphClass new.
m installModelIn: owner. "A chance to install model pointers"
self attachMorph: m.
owner startSteppingSubmorphsOf: m! !
!LayoutMorph methodsFor: 'private'!
resizeIfNeeded
"Resize this morph if it is space-filling or shrink-wrap and its owner is not a layout morph."
| newExtent |
newExtent _ bounds extent.
(owner == nil or: [owner isLayoutMorph not]) ifTrue: [
"if spaceFill and not in a LayoutMorph, grow to enclose submorphs"
hResizing = #spaceFill ifTrue: [newExtent x: (self minWidth max: self bounds width)].
vResizing = #spaceFill ifTrue: [newExtent y: (self minHeight max: self bounds height)]].
"if shrinkWrap, adjust size to just fit around submorphs"
hResizing = #shrinkWrap ifTrue: [newExtent x: self minWidth].
vResizing = #shrinkWrap ifTrue: [newExtent y: self minHeight].
newExtent = bounds extent ifFalse: [
"bounds really changed"
bounds _ bounds topLeft extent: newExtent.
self fixLayout.
self layoutChanged "flush fullBounds cache"].
! !
!MenuItemMorph methodsFor: 'flag accessing'!
isEnabled
^(flags bitAnd: 1) = 0!
isEnabled: aBoolean
self isEnabled = aBoolean ifTrue: [^self].
flags := flags bitXor: 1.
self color: (aBoolean ifTrue: [Color black] ifFalse: [Color gray])!
isInTransition
^(flags bitAnd: 2) > 0!
isInTransition: aBoolean
self isInTransition = aBoolean ifTrue: [^self].
flags := flags bitXor: 2.
self changed.
self showSubMenu! !
!MenuItemMorph methodsFor: 'accessing'!
action
^action!
action: aSymbol
action := aSymbol!
subMenu
^subMenu!
subMenu: aMenuMorph
subMenu := aMenuMorph.
self changed! !
!MenuItemMorph methodsFor: 'drawing'!
drawOn: aCanvas
(self isInTransition and: [self isEnabled]) ifTrue: [aCanvas fillRectangle: self bounds color: owner color darker].
super drawOn: aCanvas.
subMenu == nil ifFalse: [aCanvas image: SubMenuMarker at: (self bounds right - 8 @ (self bounds top + self bounds bottom - SubMenuMarker height + 1 // 2))]! !
!MenuItemMorph methodsFor: 'initialize-release'!
initialize
color _ Color black.
owner _ nil.
submorphs _ EmptyArray.
font _ nil.
hasFocus _ false.
contents := ''.
bounds := 0@0 extent: 10@10.
flags := 0! !
!MenuItemMorph methodsFor: 'events'!
mouseDown: evt
"Handle a mouse down event. Menu items get activated when the mouse is over them."
self isInMenu ifFalse: [^super mouseDown: evt].
evt shiftPressed ifTrue: ["enable label editing" ^super mouseDown: evt].
evt hand newMouseFocus: self.
self isInTransition: true!
mouseMove: evt
| m |
m _ self world mouseRecipientAt: evt cursorPoint.
self isInTransition: m == self.
m == self ifTrue: [^self].
(((m isKindOf: MenuItemMorph) and: [m isInMenu]) and: [
m owner == self owner or: [
m owner == subMenu or: [
m owner hasSubMenu: owner]]])
ifTrue: [m owner == subMenu ifFalse: [self hideSubMenu].
(m owner == self owner or: [m subMenu == owner or: [m owner == subMenu]])
ifFalse: [owner delete].
evt hand newMouseFocus: m]!
mouseUp: evt
"Handle a mouse up event. Menu items get activated when the mouse is over them."
self isInTransition: false.
self isInMenu ifTrue: [
owner deleteIfPopUp.
subMenu == nil
ifFalse: [self hideSubMenu]
ifTrue: [(self bounds containsPoint: evt cursorPoint)
ifTrue: [owner itemWasSelected: self]]]! !
!MenuItemMorph methodsFor: 'layout'!
hResizing
^#spaceFill!
isLayoutMorph
^true!
layoutInExtent: aPoint
| scanner |
scanner _ QuickPrint newOn: Display box: Display boundingBox font: font.
self extent: ((scanner stringWidth: contents) @ (scanner lineHeight) max: aPoint)!
minHeight
^self extent y!
minWidth
| scanner |
scanner _ QuickPrint newOn: Display box: Display boundingBox font: font.
^(scanner stringWidth: contents) + (subMenu == nil ifTrue: [0] ifFalse: [10])!
vResizing
^#shrinkWrap! !
!MenuItemMorph methodsFor: 'private'!
hideSubMenu
subMenu == nil ifFalse: [subMenu delete].
self isInTransition: false!
isInMenu
^owner isKindOf: MenuMorph!
showSubMenu
subMenu == nil ifFalse: [
subMenu delete; popUpOwner: self.
subMenu popUpAt: self bounds topRight in: self world]! !
!MenuItemMorph class methodsFor: 'class initialization'!
initialize
"MenuItemMorph initialize"
SubMenuMarker := Form
extent: 5@9
fromArray: #( 2147483648 3221225472 3758096384 4026531840 4160749568 4026531840 3758096384 3221225472 2147483648)
offset: 0@0! !
!MenuLineMorph methodsFor: 'drawing'!
drawOn: aCanvas
aCanvas fillRectangle: (bounds topLeft corner: bounds rightCenter) color: owner color darker.
aCanvas fillRectangle: (bounds leftCenter corner: bounds bottomRight) color: owner color lighter! !
!MenuLineMorph methodsFor: 'layout'!
hResizing
^#spaceFill!
isLayoutMorph
^true!
layoutInExtent: aPoint
self extent: aPoint!
minHeight
^2!
minWidth
^10!
vResizing
^#shrinkWrap! !
!MenuMorph methodsFor: 'initialize-release'!
initialize
super initialize.
self setColor: (Color red: 0.8 green: 0.8 blue: 0.8) borderWidth: 2 borderColor: #raised.
inset := 3.
orientation _ #vertical.
hResizing _ #shrinkWrap.
vResizing _ #shrinkWrap.
! !
!MenuMorph methodsFor: 'geometry'!
minHeightWhenEmpty
^ 10
!
minWidthWhenEmpty
^ 20
!
popUpAt: aPoint in: world
| selectedItem delta |
selectedItem := self items detect: [:each | each == lastSelection] ifNone: [].
selectedItem == nil
ifTrue: [self position: aPoint]
ifFalse: [self position: aPoint - selectedItem position + self position].
delta := self bounds amountToTranslateWithin: world bounds.
delta = (0@0) ifFalse: [self position: self position + delta].
world addMorphFront: self.
self changed!
positionSelectionAt: aPoint
| selectedItem |
selectedItem := self items detect: [:each | each == lastSelection] ifNone: [].
selectedItem == nil
ifTrue: [self position: aPoint]
ifFalse: [self position: aPoint - selectedItem position + self position]! !
!MenuMorph methodsFor: 'adding'!
add: aString action: anAction
| item |
item := MenuItemMorph new.
item contents: aString; action: anAction.
self addMorphBack: item!
add: aString subMenu: aMenuMorph
| item |
item := MenuItemMorph new.
item contents: aString; subMenu: aMenuMorph.
self addMorphBack: item!
addLine
self addMorphBack: MenuLineMorph new!
addTitle: aString
| title |
title := LayoutMorph new setColor: (Color red: 0.5 green: 1 blue: 0.75) borderWidth: 1 borderColor: #inset.
title vResizing: #shrinkWrap.
title orientation: #vertical.
title centering: #center.
title addMorph: (StringMorph new contents: aString).
self addMorphFront: title! !
!MenuMorph methodsFor: 'accessing'!
hasSubMenu: aMenuMorph
| sub |
self items do: [:each |
sub := each subMenu.
sub == nil ifFalse: [
sub == aMenuMorph ifTrue: [^true].
(sub hasSubMenu: aMenuMorph) ifTrue: [^true]]].
^false!
isPopUp
^popUpOwner notNil!
items
^submorphs select: [:each | each isKindOf: MenuItemMorph]!
lastSelectionAction
^lastSelection == nil ifTrue: [lastSelection action]!
lastSelectionAction: aSymbol
lastSelection := self items detect: [:each | each action == aSymbol] ifNone: []!
popUpOwner
^popUpOwner!
popUpOwner: aMenuItemMorph
popUpOwner := aMenuItemMorph!
receiver
^receiver!
receiver: anObject
receiver := anObject!
selections
^self items collect: [:each | each action]! !
!MenuMorph methodsFor: 'menu'!
addCustomMenuItems: aCustomMenu hand: aHandMorph
super addCustomMenuItems: aCustomMenu hand: aHandMorph.
aCustomMenu addLine.
aCustomMenu add: 'add item...' action: #addItem.
aCustomMenu add: 'add title...' action: #addTitle.
aCustomMenu add: 'add line' action: #addLine.
(self canDetachSubMenu: aHandMorph)
ifTrue: [aCustomMenu add: 'detach submenu' action: #detachSubMenu:]!
addItem
| string action |
string := FillInTheBlank request: 'Label for new item?'.
string = '' ifTrue: [^self].
action := FillInTheBlank request: 'Action?'.
action := action = '' ifFalse: [action first = $[
ifTrue: [Object readFromString: action]
ifFalse: [action asSymbol]].
self add: string action: action!
addTitle
| string |
string := FillInTheBlank request: 'Title for menu?'.
string = '' ifTrue: [^self].
self addTitle: string!
beSubMenu: evt
| rootMorphs targetRoot targetMorph |
rootMorphs _ evt hand world rootMorphsAt: evt hand targetOffset.
rootMorphs size < 2 ifTrue: [^ self].
targetRoot _ rootMorphs at: 2.
targetMorph _ evt hand chooseTargetSubmorphOf: targetRoot.
targetMorph ifNotNil: [
targetMorph subMenu: self.
self delete.
targetMorph changed].
!
canDetachSubMenu: hand
| possibleTargets item |
possibleTargets := hand argumentOrNil morphsAt: hand targetOffset.
item := possibleTargets detect: [:each | each isKindOf: MenuItemMorph] ifNone: [].
item == nil ifTrue: [^false].
^item subMenu notNil!
deleteIfPopUp
self isPopUp ifTrue: [
self delete.
(popUpOwner isKindOf: MenuItemMorph) ifTrue: [
popUpOwner owner deleteIfPopUp]].
!
detachSubMenu: evt
| possibleTargets item |
possibleTargets := evt hand argumentOrNil morphsAt: evt hand targetOffset.
item := possibleTargets detect: [:each | each isKindOf: MenuItemMorph] ifNone: [].
item == nil ifTrue: [^self].
item subMenu == nil ifFalse: [
evt hand attachMorph: item subMenu.
item subMenu popUpOwner: nil.
item subMenu: nil]!
itemWasSelected: aMenuItem
lastSelection := aMenuItem.
receiver performMenuAction: aMenuItem action! !
!MenuMorph methodsFor: 'dropping/grabbing'!
acceptDroppingMorph: aMorph event: evt
"Allow the user to add submorphs just by dropping them on this morph."
| item |
(aMorph isKindOf: MenuMorph) ifTrue: [
item := (self morphsAt: evt cursorPoint)
detect: [:each | each isKindOf: MenuItemMorph]
ifNone: []].
item == nil ifTrue: [^super acceptDroppingMorph: aMorph event: evt].
item subMenu: aMorph.
aMorph delete! !
!MorphicEvent methodsFor: 'private'!
setMousePoint: aPoint buttons: anInteger lastEvent: lastEvent hand: hand
cursorPoint _ aPoint.
buttons _ anInteger.
keyValue _ 0.
sourceHand _ hand.
self anyButtonPressed ifTrue: [
lastEvent anyButtonPressed
ifTrue: [type _ #mouseMove]
ifFalse: [type _ #mouseDown].
] ifFalse: [
lastEvent anyButtonPressed
ifTrue: [type _ #mouseUp]
ifFalse: [type _ #mouseMove]].
! !
!Symbol methodsFor: 'menus'!
dispatchAsMenuActionTo: receiver
^receiver perform: self!
dispatchAsMenuActionTo: receiver with: argument
^self numArgs = 0
ifTrue: [receiver perform: self]
ifFalse: [receiver perform: self with: argument]! !
MenuItemMorph initialize!
--------------64880EEB773C24486F5992E1--
Date: 97 May 14 9:16:21 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v03102803af9f82361441@[129.34.225.178]>
Subject: Re: Casing the joint
>Two methods in Object, #case: and #case:otherwise: seem not to be used
>anywhere in the image (1.19d).
>
>Are they still needed?
>
>They seem to take a parameter that is an instance of
>BlockAssociationCollection but there is no class with that name.
>
>Dave
David, and all --
Squeak has a brace construct that was put in by Larry Tesler, in the early=
days of Apple Smalltalk. It is not part of the ST-80 standard. =
Consequently, we do not use it in the system, and we have never encouraged=
its use. Moverover some of the lateral support in the Decompiler, etc., no=
longer works, though neither should it be hard to fix.
It's pretty simple. The syntax is=20
{ any number expressions separated by '.' }
The result is an array with the values of the expressions. Thus
z :=3D {1@2. 3@4. 5@6}.
stores into z a new array containing 3 points. It compiles the following co=
de:
<76> pushConstant: 1
<77> pushConstant: 2
<BB> send: @
<20> pushConstant: 3
<23> pushConstant: 4
<BB> send: @
<24> pushConstant: 5
<25> pushConstant: 6
<BB> send: @
<41> pushLit: Array
<20> pushConstant: 3
<E2> send: fromBraceStack:
<68> popIntoTemp: 0.
Array>>fromBraceStack: nElements allocates a new array, and then pops the=
elements off the stack of its sender, storing them into itself. Clearly=
this construct is limited by stack depth considerations.
If you buy into brace construct, then you can make up dictionaries on the=
fly using the -> association message, as in
dict :=3D {#green -> #go. #yellow -> #slow. #red -> #stop} as: Dictionary.
Also, if you feel the need for a CASE construct, you can get it by=
assembling arrays of blocks this way:
z :=3D someColor caseOf:
{[#green]->[1+1].
['yellow' asSymbol]->[2+2].
[#red]->[3+3]}.
The compiler recognizes this construct and compiles it in-line so that a=
large case construct won't blow the stack depth limit. In so doing, it=
also avoids the execution overhead of the block evaluations.
There are a number of examples in comments that you can find beginning with=
Object>>caseOf: and BraceConstructor class>>example. For the most part it=
all works, and we use it for scratch programming (you'll find a couple in=
WarpBlt examples). It's as good as anything similar I've seen proposed for=
Smalltalk, but we haven't pursued it because it involves syntax that is not=
standard.
David is right to bring this up. We ought to "embrace" the brace construct,=
document it, and use it, or strip it out now before it creates any more=
confusion. It's begninning to feel like Squeak may well become its own=
standard, so I think the real question is, do we like it, more than, is it =
compatible.
- Dan
Date: 97 May 14 9:21:43 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Squeak@create.ucsb.edu
Subject: Fixes for Pen Computing
--============_-1348490133==_============
Content-Type: text/plain; charset="us-ascii"
Attached are two methods (one from Blair McGlashan) which are needed for Squeak's UI to function well with touch pens, as on the Cassiopeia. Such pens do not provide any mouse movement input except when the "button is pressed".
With these fixes, things seem to run fine, all except that you don't see cursor changes on mouse-over. I'll include these in the next release.
- Dan
--============_-1348490133==_============
Content-Type: text/plain; name="PenChanges-di.cs"; charset="us-ascii"
Content-Disposition: attachment; filename="PenChanges-di.cs"
'From Squeak 1.19d of April 13, 1997 on 12 May 1997 at 1:34:30 pm'!
!ScrollController methodsFor: 'scrolling'!
scroll
"Check to see whether the user wishes to jump, scroll up, or scroll down."
| savedCursor |
savedCursor _ sensor currentCursor.
[self scrollBarContainsCursor]
whileTrue:
[Processor yield.
sensor cursorPoint x <= self downLine
ifTrue: [self scrollDown]
ifFalse: [sensor cursorPoint x <= self upLine
ifTrue: [self scrollAbsolute]
ifFalse: [sensor cursorPoint x <= self yellowLine
ifTrue: [self scrollUp]
ifFalse: [sensor cursorPoint x <= scrollBar right
ifTrue: "Might not be, with touch pen"
[self changeCursor: Cursor menu.
sensor anyButtonPressed
ifTrue: [self changeCursor: savedCursor.
self anyButtonActivity]]]]]].
savedCursor show! !
!StandardSystemController methodsFor: 'borders'!
adjustWindowBorders
| side |
VBorderCursor showWhile:
[ [side _ view displayBox sideNearestTo: sensor cursorPoint.
self cursorOnBorder and: [(side = #left) | (side = #right)]]
whileTrue:
[(sensor redButtonPressed and: [self cursorOnBorder]) ifTrue:
[side = #left ifTrue:
[view newFrame: [:f | f withLeft: sensor cursorPoint x]].
side = #right ifTrue:
[view newFrame: [:f | f withRight: sensor cursorPoint x]]]]].
HBorderCursor showWhile:
[ [side _ view displayBox sideNearestTo: sensor cursorPoint.
self cursorOnBorder and: [(side = #top) | (side = #bottom)]]
whileTrue:
[(sensor redButtonPressed and: [self cursorOnBorder]) ifTrue:
[side = #top ifTrue:
[view newFrame: [:f | f withTop: sensor cursorPoint y]].
side = #bottom ifTrue:
[view newFrame: [:f | f withBottom: sensor cursorPoint y]].
]]]! !
--============_-1348490133==_============--
Date: 97 May 14 10:25:27 am
From: joel@ObjectPeople.com
To: Dan Ingalls <DanI@wdi.disney.com>
Cc: Squeak@create.ucsb.edu
Subject: Re: Casing the joint
> If you buy into brace construct, then you can make up dictionaries on the fly using the -> association message, as in
> dict := {#green -> #go. #yellow -> #slow. #red -> #stop} as: Dictionary.
>
> Also, if you feel the need for a CASE construct, you can get it by assembling arrays of blocks this way:
> z := someColor caseOf:
> {[#green]->[1+1].
> ['yellow' asSymbol]->[2+2].
> [#red]->[3+3]}.
> The compiler recognizes this construct and compiles it in-line so that a large case construct won't blow the stack depth limit. In so doing, it also avoids the execution overhead of the block evalu
> tions.
>
> There are a number of examples in comments that you can find beginning with Object>>caseOf: and BraceConstructor class>>example. For the most part it all works, and we use it for scratch programmin
> (you'll find a couple in WarpBlt examples). It's as good as anything similar I've seen proposed for Smalltalk, but we haven't pursued it because it involves syntax that is not standard.
>
> David is right to bring this up. We ought to "embrace" the brace construct, document it, and use it, or strip it out now before it creates any more confusion. It's begninning to feel like Squeak m
> y well become its own standard, so I think the real question is, do we like it, more than, is it compatible.
I think this is a great idea, and I like it. This is one area in
which I think Smalltalk has fallen short, and they can be very
useful.
IBM/OTI has started an approach similar to this, I believe
of the form ##( Time now seconds ), where ##( expression)
makes a compile time constant, evaluating the 'expression'.
Joel
Joel Lucuik | The Object People
Joel@ObjectPeople.com | Your Smalltalk Experts
613.225.8812 (V) 613.225.5943 (F) | http://www.objectpeople.on.ca
"Where's the kaboom? The EARTH-SHATTERING kaboom????
-Marvin the Martian"
Date: 97 May 14 12:42:08 pm
From: Ranjan Bagchi <ranjan.bagchi@pobox.com>
To: Dan Ingalls <DanI@wdi.disney.com>
Cc: "David N. Smith" <dnsmith@watson.ibm.com>, Squeak@create.ucsb.edu
Subject: Re: Casing the joint
Dan Ingalls wrote:
> David, and all --
>
> Squeak has a brace construct that was put in by Larry Tesler, in
> the early days of Apple Smalltalk. It is not part of the ST-80
> standard. Consequently, we do not use it in the system, and we have
> never encouraged its use. Moverover some of the lateral support in
> the Decompiler, etc., no longer works, though neither should it be
> hard to fix.
>
> It's pretty simple. The syntax is
> { any number expressions separated by '.' }
Thanks for sending this -- I noticed years ago that VisualWorks'
square-brace/parenthesis/quote matching was sensitive to braces
also, and was puzzled -- since I couldn't find it used anywhere.
I also know a dozen places I could use this (or could have, since I
don't
do Smalltalk professionally anymore) -- I'd used streaming to build up
collections of complicated objects, and brace-notation appears to be
more
pleasing to the reader. I'll have to play with it.
Cool.. I appreciate the history.
-rj
Date: 97 May 14 2:02:24 pm
From: Randal Schwartz <merlyn@stonehenge.com>
To: Dan Ingalls <DanI@wdi.disney.com>
Cc: "David N. Smith" <dnsmith@watson.ibm.com>, Squeak@create.ucsb.edu
In-Reply-To: Dan Ingalls's message of Wed, 14 May 1997 09:47:50 -0800
Subject: Re: Casing the joint
>>>>> "Dan" == Dan Ingalls <DanI@wdi.disney.com> writes:
Dan> David is right to bring this up. We ought to "embrace" the brace
Dan> construct, document it, and use it, or strip it out now before it
Dan> creates any more confusion. It's begninning to feel like Squeak
Dan> may well become its own standard, so I think the real question
Dan> is, do we like it, more than, is it compatible.
Well, for what it's worth, QKS-smalltalk has had that construct from
the beginning as well. It seems much more natural than
Array with: with: with...
--
Name: Randal L. Schwartz / Stonehenge Consulting Services (503)777-0095
Keywords: Perl training, UNIX[tm] consulting, video production, skiing, flying
Email: <merlyn@stonehenge.com> Snail: (Call) PGP-Key: (finger merlyn@ora.com)
Web: <A HREF="http://www.stonehenge.com/merlyn/">My Home Page!</A>
Quote: "I'm telling you, if I could have five lines in my .sig, I would!" -- me
Date: 97 May 14 3:23:46 pm
From: Ward Cunningham <ward@c2.com>
To: joel@ObjectPeople.com
Cc: Dan Ingalls <DanI@wdi.disney.com>, Squeak@create.ucsb.edu
Subject: Re: Casing the joint
> I think this is a great idea, and I like it. This is one area in
> which I think Smalltalk has fallen short, and they can be very
> useful.
>
> IBM/OTI has started an approach similar to this, I believe
> of the form ##( Time now seconds ), where ##( expression)
> makes a compile time constant, evaluating the 'expression'.
I've heard that such features have caused no end of problems in the lisp
community. For example, I imagine code like
{Form fromUser} display
could be handy in development but hard to maintain. -- Ward
--
Ward Cunningham
v 503-245-5633 mailto:ward@c2.com
f 503-246-5587 http://c2.com/
Date: 97 May 14 3:46:56 pm
From: Ian Piumarta <piumarta@prof.inria.fr>
To: ward@c2.com
Cc: Squeak@create.ucsb.edu
Subject: Re: Casing the joint
> I've heard that such features have caused no end of problems in the lisp
> community.
Quasiquote? It's the best thing since sliced time! I suspect that any
problems with it might only be due to incrementality in the programming
environment, and a very loose notion of when "compile time" actually is.
If not, then I'd be interested to hear more details...
Ian
------------------------------- projet SOR -------------------------------
Ian Piumarta, INRIA Rocquencourt, Internet: Ian.Piumarta@inria.fr
BP105, 78153 Le Chesnay Cedex, FRANCE Voice: +33 1 39 63 52 87
----------------------- Systemes a Objets Repartis -----------------------
Date: 97 May 14 9:19:23 pm
From: Dan Ingalls <DanI@wdi.disney.com>
To: Squeak@create.ucsb.edu
Subject: New Arithmetic Coercion Mechanism
After some six months of not getting around to it, I have finally redone=
Squeak's ungainly arithmetic coercion. To quote from the file header...
This order-dependent fileIn replaces the coercion mechanism in Squeak with a=
much more efficient mechanism described in the new comment for class=
Number. The net result is that careless mixed-mode arithmetic such as=
355.0 / 113 is nearly as fast as careful pre-conversion, as in 355.0 / (113=
asFloat). The intention is that many explicit conversion messages can now=
be eliminated, resulting in simpler code. In many cases the simpler code=
will also be faster, since values that are already the correct type will=
not even be examined.
This will be in the next image, but interested parties are welcome to try it=
critique it, and tell me of any bugs you encounter. Caution is advised=
since I did the work in a later version thatn 1.19d, but I did file it in=
to 1.19 and it seemed to be OK.
Enjoy
- Dan
P.S. As another incentive to clean out gratuitous conversions, a=
Float-tolerant BitBlt is on the way...
Date: 97 May 14 9:21:11 pm
From: Dan Ingalls <DanI@wdi.disney.com>
To: Squeak@create.ucsb.edu
Subject: ...and now the file (blush)...
--============_-1348446936==_============
Content-Type: text/plain; charset="us-ascii"
--============_-1348446936==_============
Content-Type: text/plain; name="NewCoercion-di.cs"; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment; filename="NewCoercion-di.cs"
'From Squeak 1.19d of April 13, 1997 on 14 May 1997 at 1:48:35 pm'!
"Change Set: NewCoercion
Date: 14 May 1997
Author: Dan Ingalls
This order-dependent fileIn replaces the coercion mechanism in Squeak with a=
much more efficient mechanism described in the new comment for class=
Number. The net result is that careless mixed-mode arithmetic such as=
355.0 / 113 is nearly as fast as careful pre-conversion, as in 355.0 / (113=
asFloat). The intention is that many explicit conversion messages can now=
be eliminated, resulting in simpler code. In many cases the simpler code=
will actually be faster, since values that are already the correct type=
will not even be examined."!
Number comment:
'I am an abstract representation of a number. My subclasses Float, Fraction,=
and Integer, and their subclasses, provide concrete representations of a=
numeric quantity.
All my subclasses participate in a simple type coercion mechanism that=
supports mixed-mode arithmetic and comparisons. It works as follows: If
self<typeA> op: arg<typeB>
fails because of incompatible types, then it is retried in the following gui=
se:
(arg adaptTypeA: self) op: arg adaptToTypeA.
This gives the arg of typeB an opportunity to resolve the incompatibility,=
knowing exactly what two types are involved. If self is more general, then=
arg will be converted, and viceVersa. This mechanism is extensible to any=
new number classes that one might wish to add to Squeak. The only=
requirement is that every subclass of Number must support a pair of=
conversion methods specific to each of the other subclasses of Number.'!
!Number methodsFor: 'testing'!
isFloat
^ false!
isFraction
^ false! !
!Number methodsFor: 'converting'!
adaptFloat: aFloat
"If I am involved in arithmetic with a Float, I must know whether to=
convert it."
self subclassResponsibility!
adaptFraction: aFraction
"If I am involved in arithmetic with a Fraction, I must know whether to=
convert it."
self subclassResponsibility!
adaptInteger: anInteger
"If I am involved in arithmetic with an Integer, I must know whether to=
convert it."
self subclassResponsibility!
adaptToFloat
"If I am involved in arithmetic with a Float, I must know whether to be con=
verted."
self subclassResponsibility!
adaptToFraction
"If I am involved in arithmetic with a Fraction, I must know whether to be =
converted."
self subclassResponsibility!
adaptToInteger
"If I am involved in arithmetic with an Integer, I must know whether to be =
converted."
self subclassResponsibility! !
!Float methodsFor: 'truncation and round off'!
fractionPart
"Primitive. Answer a Float whose value is the difference between the=20
receiver and the receiver's asInteger value. Optional. See Object=20
documentation whatIsAPrimitive."
<primitive: 52>
^self - self truncated asFloat! !
!Float methodsFor: 'converting'!
adaptFraction: aFraction
"If I am involved in arithmetic with a Fraction, convert the Fraction."
^ aFraction asFloat!
adaptInteger: anInteger
"If I am involved in arithmetic with an Integer, convert the Integer."
^ anInteger asFloat!
adaptToFraction
"If I am involved in arithmetic with a Fraction, do not convert me."
^ self!
adaptToInteger
"If I am involved in arithmetic with an Integer, do not convert me."
^ self!
isFloat
^ true! !
!Fraction methodsFor: 'converting'!
adaptFloat: aFloat
"If I am involved in arithmetic with a Float, do not convert the Float."
^ aFloat!
adaptInteger: anInteger
"If I am involved in arithmetic with an Integer, convert the Integer."
^ anInteger asFloat!
adaptToFloat
"If I am involved in arithmetic with a Float, convert me to a Float."
^ self asFloat!
adaptToInteger
"If I am involved in arithmetic with an Integer, do not convert me."
^ self!
isFraction
^ true! !
!Integer methodsFor: 'converting'!
adaptFloat: aFloat
"If I am involved in arithmetic with a Float, do not convert the Float."
^ aFloat!
adaptFraction: aFraction
"If I am involved in arithmetic with a Fraction, do not convert the Fractio=
n."
^ aFraction!
adaptToFloat
"If I am involved in arithmetic with a Float, convert me to a Float."
^ self asFloat!
adaptToFraction
"If I am involved in arithmetic with a Fraction, convert me to a Fraction."
^ self asFraction! !
!SmallInteger methodsFor: 'converting'!
adaptToFloat
"Fast conversion equivalent to self asFloat."
<primitive: 40>
self primitiveFailed! !
Integer removeSelector: #coerceToPoint!
Number comment:
'I am an abstract representation of a number. My subclasses Float, Fraction,=
and Integer, and their subclasses, provide concrete representations of a=
numeric quantity.
All my subclasses participate in a simple type coercion mechanism that=
supports mixed-mode arithmetic and comparisons. It works as follows: If
self<typeA> op: arg<typeB>
fails because of incompatible types, then it is retried in the following gui=
se:
(arg adaptTypeA: self) op: arg adaptToTypeA.
This gives the arg of typeB an opportunity to resolve the incompatibility,=
knowing exactly what two types are involved. If self is more general, then=
arg will be converted, and viceVersa. This mechanism is extensible to any=
new number classes that one might wish to add to Squeak. The only=
requirement is that every subclass of Number must support a pair of=
conversion methods specific to each of the other subclasses of Number.'!
!Float methodsFor: 'arithmetic'!
* aNumber=20
"Primitive. Answer the result of multiplying the receiver by aNumber.
Fail if the argument is not a Float. Essential. See Object documentation
whatIsAPrimitive."
<primitive: 49>
^ (aNumber adaptFloat: self) * aNumber adaptToFloat!
+ aNumber=20
"Primitive. Answer the sum of the receiver and aNumber. Essential.
Fail if the argument is not a Float. See Object documentation
whatIsAPrimitive."
<primitive: 41>
^ (aNumber adaptFloat: self) + aNumber adaptToFloat!
- aNumber=20
"Primitive. Answer the difference between the receiver and aNumber.
Fail if the argument is not a Float. Essential. See Object documentation
whatIsAPrimitive."
<primitive: 42>
^ (aNumber adaptFloat: self) - aNumber adaptToFloat!
/ aNumber=20
"Primitive. Answer the result of dividing receiver by aNumber.
Fail if the argument is not a Float. Essential. See Object documentation
whatIsAPrimitive."
<primitive: 50>
aNumber =3D 0
ifTrue: [self error: 'attempt to divide by zero']
ifFalse: [^ (aNumber adaptFloat: self) / aNumber adaptToFloat]! !
!Float methodsFor: 'comparing'!
< aNumber=20
"Primitive. Compare the receiver with the argument and return true
if the receiver is less than the argument. Otherwise return false.
Fail if the argument is not a Float. Essential. See Object documentation
whatIsAPrimitive."
<primitive: 43>
^ (aNumber adaptFloat: self) < aNumber adaptToFloat!
<=3D aNumber=20
"Primitive. Compare the receiver with the argument and return true
if the receiver is less than or equal to the argument. Otherwise return
false. Fail if the argument is not a Float. Optional. See Object
documentation whatIsAPrimitive."
<primitive: 45>
^ (aNumber adaptFloat: self) <=3D aNumber adaptToFloat!
=3D aNumber=20
"Primitive. Compare the receiver with the argument and return true
if the receiver is equal to the argument. Otherwise return false.
Fail if the argument is not a Float. Essential. See Object documentation
whatIsAPrimitive."
<primitive: 47>
aNumber isNumber ifFalse: [^ false].
^ (aNumber adaptFloat: self) =3D aNumber adaptToFloat!
> aNumber=20
"Primitive. Compare the receiver with the argument and return true
if the receiver is greater than the argument. Otherwise return false.
Fail if the argument is not a Float. Essential. See Object documentation
whatIsAPrimitive."
<primitive: 44>
^ (aNumber adaptFloat: self) > aNumber adaptToFloat!
>=3D aNumber=20
"Primitive. Compare the receiver with the argument and return true
if the receiver is greater than or equal to the argument. Otherwise return
false. Fail if the argument is not a Float. Optional. See Object=
documentation=20
whatIsAPrimitive. "
<primitive: 46>
^ (aNumber adaptFloat: self) >=3D aNumber adaptToFloat! !
!Fraction methodsFor: 'arithmetic'!
* aNumber
"Answer the result of multiplying the receiver by aNumber."
aNumber isFraction
ifTrue: [^ (Fraction numerator: numerator * aNumber numerator
denominator: denominator * aNumber denominator)
reduced]
ifFalse: [^ (aNumber adaptFraction: self) * aNumber adaptToFraction]!
+ aNumber
"Answer the sum of the receiver and aNumber."
| commonDenominator newNumerator |
aNumber isFraction
ifTrue:=20
[denominator =3D aNumber denominator ifTrue: [
^ (Fraction=20
numerator: numerator + aNumber numerator
denominator: denominator) reduced].
commonDenominator _ denominator lcm: aNumber denominator.
newNumerator _
(numerator * (commonDenominator / denominator)) +
(aNumber numerator * (commonDenominator / aNumber denominator)).
^ (Fraction=20
numerator: newNumerator=20
denominator: commonDenominator) reduced]
ifFalse: [^ (aNumber adaptFraction: self) + aNumber adaptToFraction]!
- aNumber
"Answer the difference between the receiver and aNumber."
aNumber isFraction
ifTrue: [^ self + aNumber negated]
ifFalse: [^ (aNumber adaptFraction: self) - aNumber adaptToFraction]!
/ aNumber
"Answer the result of dividing the receiver by aNumber."
aNumber isFraction
ifTrue: [^self * aNumber reciprocal]
ifFalse: [^ (aNumber adaptFraction: self) / aNumber adaptToFraction]! !
!Fraction methodsFor: 'comparing'!
< aNumber
aNumber isFraction
ifTrue: [aNumber numerator =3D 0
ifTrue: [^numerator < 0]
ifFalse: [^self - aNumber < 0]]
ifFalse: [^ (aNumber adaptFraction: self) < aNumber adaptToFraction]!
=3D aNumber
aNumber isNumber ifFalse: [^ false].
aNumber isFraction
ifTrue: [aNumber numerator =3D 0
ifTrue: [^numerator =3D 0]
ifFalse: [^aNumber numerator =3D numerator=20
and: [aNumber denominator =3D denominator]]]
ifFalse: [^ (aNumber adaptFraction: self) =3D aNumber adaptToFraction]! !
!Integer methodsFor: 'arithmetic'!
* aNumber
"Refer to the comment in Number * "=20
aNumber isInteger
ifTrue: [^ self digitMultiply: aNumber=20
neg: self negative ~~ aNumber negative]
ifFalse: [^ (aNumber adaptInteger: self) * aNumber adaptToInteger]!
+ aNumber
"Refer to the comment in Number + "
aNumber isInteger
ifTrue: [self negative =3D=3D aNumber negative
ifTrue: [^(self digitAdd: aNumber) normalize]
ifFalse: [^self digitSubtract: aNumber]]
ifFalse: [^ (aNumber adaptInteger: self) + aNumber adaptToInteger]!
- aNumber
"Refer to the comment in Number - "
aNumber isInteger
ifTrue: [self negative =3D=3D aNumber negative
ifTrue: [^ self digitSubtract: aNumber]
ifFalse: [^ (self digitAdd: aNumber) normalize]]
ifFalse: [^ (aNumber adaptInteger: self) - aNumber adaptToInteger]!
/ aNumber
"Refer to the comment in Number / "
| quoRem |
aNumber isInteger
ifTrue: [quoRem _ self digitDiv: aNumber=20
neg: self negative ~~ aNumber negative.
(quoRem at: 2) =3D 0
ifTrue: [^(quoRem at: 1) normalize]
ifFalse: [^(Fraction numerator: self denominator: aNumber) reduced]]
ifFalse: [^ (aNumber adaptInteger: self) / aNumber adaptToInteger]!
quo: aNumber=20
"Refer to the comment in Number quo: "
| ng quo |
aNumber isInteger
ifTrue:=20
[ng _ self negative =3D=3D aNumber negative =3D=3D false.
quo _ (self digitDiv: aNumber neg: ng) at: 1.
^ quo normalize]
ifFalse: [^ (aNumber adaptInteger: self) quo: aNumber adaptToInteger]! !
!Integer methodsFor: 'comparing'!
< aNumber
aNumber isInteger
ifTrue: [self negative =3D=3D aNumber negative
ifTrue: [self negative
ifTrue: [^(self digitCompare: aNumber) > 0]
ifFalse: [^(self digitCompare: aNumber) < 0]]
ifFalse: [^self negative]]
ifFalse: [^ (aNumber adaptInteger: self) < aNumber adaptToInteger]!
=3D aNumber
aNumber isNumber ifFalse: [^ false].
aNumber isInteger
ifTrue: [aNumber negative =3D=3D self negative
ifTrue: [^ (self digitCompare: aNumber) =3D 0]
ifFalse: [^ false]]
ifFalse: [^ (aNumber adaptInteger: self) =3D aNumber adaptToInteger]!
> aNumber
aNumber isInteger
ifTrue: [self negative =3D=3D aNumber negative
ifTrue: [self negative
ifTrue: [^(self digitCompare: aNumber) < 0]
ifFalse: [^(self digitCompare: aNumber) > 0]]
ifFalse: [^ aNumber negative]]
ifFalse: [^ (aNumber adaptInteger: self) > aNumber adaptToInteger]! !
Number removeSelector: #retry:coercing:!
Number removeSelector: #generality!
Number removeSelector: #coerce:!
=46loat removeSelector: #coerce:!
=46loat removeSelector: #generality!
=46raction removeSelector: #coerce:!
=46raction removeSelector: #generality!
Integer removeSelector: #coerce:!
Integer removeSelector: #generality!
Number class removeSelector: #newFrom:!
SmallInteger removeSelector: #generality!
SmallInteger removeSelector: #coerce:!
Smalltalk removeEmptyMessageCategories!
--============_-1348446936==_============--
Date: 97 May 14 11:09:38 pm
From: lstrand@concentric.net
To: "David N. Smith" <dnsmith@watson.ibm.com>,
"Michael Ackerman" <mack@sfo.com>
Cc: <squeak@create.ucsb.edu>
Subject: Re: Which Smalltalk is Squeak?
David Smith wrote:
>Why? Because, unlike C++ where MI seems to be important for reasons I don't
>quite get, it is not important in Smalltalk.
Look at the Commander example in the Blue/Purple book (in the "Pens"
chapter) -- particularly the section "Additional Protocol for Commander
Pen". (A Commander simply accepts messages from Pen's protocol and
broadcasts them to a bunch of pens, each pen drawing in parallel.)
Even though Commander is a subclass of Array and not of Pen, with the
additional Pen protocol it may be used anywhere a Pen may be used.
Because messages are bound at runtime in Smalltalk, anything that
conforms to Pen's protocol may effectively be considered a Pen. So in
Smalltalk MI isn't absolutely necessary.
In C++, Commander would have to be a subclass of Pen in order to be used
as a Pen; the compiler enforces this. One has to use MI to get the
desired effect (a class which can be used both as an Array and a Pen).
In this case, I would choose Pen as a superclass, and add an instance
variable to refer to an Array of Pens, just to avoid MI. But other cases
(e.g., ReadWriteStream) beg the use of MI.
It is facinating to me how many features of C++ are forced by its rigid
compile-time checks. If you were to design a "static Smalltalk", right
away you would be forced to add templates and MI... very quickly you
would have a language which is ten times as complicated but no more
powerful.
--Leif
Date: 97 May 14 11:59:45 pm
From: Georg Gollmann <gollmann@edvz.tuwien.ac.at>
To: Squeak@create.ucsb.edu
In-Reply-To: <v03007800af9faa1feff6@[206.16.10.79]>
Subject: Re: Casing the joint
At 9:47 Uhr -0800 14.5.1997, Dan Ingalls wrote:
>
>It's pretty simple. The syntax is
> { any number expressions separated by '.' }
GemStone Smalltalk has this with the syntax
#[ any number expressions separated by ',' ]
>David is right to bring this up. We ought to "embrace" the brace construct,
>document it, and use it, or strip it out now before it creates any more
>confusion. It's begninning to feel like Squeak may well become its own
>standard, so I think the real question is, do we like it, more than, is it
>compatible.
I am very much in favour of having an array constructor, the current syntax
is fine with me.
Georg
----
Dipl.Ing. Georg Gollmann TU-Wien, EDV-Zentrum
phon:(+43-1) 58801 - 5848
fax: (+43-1) 587 42 11
mail:gollmann@edvz.tuwien.ac.at
http://ftp.tuwien.ac.at/~go/Gollmann.html
Date: 97 May 15 12:02:31 am
From: Georg Gollmann <gollmann@edvz.tuwien.ac.at>
To: Dan Ingalls <DanI@wdi.disney.com>, Squeak@create.ucsb.edu
In-Reply-To: <v03007804afa05368b776@[206.16.10.79]>
Subject: Re: New Arithmetic Coercion Mechanism (Buglet)
At 21:51 Uhr -0800 14.5.1997, Dan Ingalls wrote:
>After some six months of not getting around to it, I have finally redone
>Squeak's ungainly arithmetic coercion. To quote from the file header...
>
Fraction>adaptInteger: converts its argument to Float, it should convert to
Fraction.
Georg
----
Dipl.Ing. Georg Gollmann TU-Wien, EDV-Zentrum
phon:(+43-1) 58801 - 5848
fax: (+43-1) 587 42 11
mail:gollmann@edvz.tuwien.ac.at
http://ftp.tuwien.ac.at/~go/Gollmann.html
Date: 97 May 15 12:23:08 am
From: mack@sfo.com (Michael Ackerman)
To: squeak@create.ucsb.edu
Subject: Blue Book
What is the Blue/Purple book?
Michael Ackerman
Date: 97 May 15 5:30:16 am
From: Anthony Lander <anthony@objectPeople.com>
To: squeak@create.ucsb.edu
Subject: Correcting long-standing problems
Once everyone (i.e. Dan) is busy correcting long-standing problems, such as
hashing and coersion, could I convince you to tackle one more?
#mustBeBoolean
Man, this bothers me. I've reimplemented #doesNotUnderstand: more times
than you can shake a stick at. You simply cannot build a good proxy object
in Smalltalk because of this message. Can the VM be changed such that
messages like #and: fail by really sending the #and: message (not inlined)
instead of sending #mustBeBoolean?
-Anthony Lander
-----Proof of the Comming Java Backlash--------------------------------
All device drivers will be Java in a few years, at least the ones
that might have been in C. This is because Java can be faster than C
and because it is portable. -found in comp.lang.java
Date: 97 May 15 5:42:25 am
From: joel@ObjectPeople.com
To: Ward Cunningham <ward@c2.com>
Cc: Dan Ingalls <DanI@wdi.disney.com>, Squeak@create.ucsb.edu
Subject: Re: Casing the joint
> Date: Wed, 14 May 1997 15:42:13 -0700
> From: Ward Cunningham <ward@c2.com>
> Organization: Cunningham & Cunningham, Inc.
> To: joel@ObjectPeople.com
> Cc: Dan Ingalls <DanI@wdi.disney.com>, Squeak@create.ucsb.edu
> Subject: Re: Casing the joint
> > I think this is a great idea, and I like it. This is one area in
> > which I think Smalltalk has fallen short, and they can be very
> > useful.
> >
> > IBM/OTI has started an approach similar to this, I believe
> > of the form ##( Time now seconds ), where ##( expression)
> > makes a compile time constant, evaluating the 'expression'.
>
> I've heard that such features have caused no end of problems in the lisp
> community. For example, I imagine code like
>
> {Form fromUser} display
>
> could be handy in development but hard to maintain. -- Ward
>
I can see where compile-time constants could be hard to maintain.
It would be easy to detect these, as a senders-like utility.
For an array constructor, I think the advantages of useability/readability
outweigh the problems.
Perhaps 2 syntaxes would be good:
##( expression ) - for compile-time constants and,
{ element1 element2 ... } - for array construction
Joel
Joel Lucuik | The Object People
Joel@ObjectPeople.com | Your Smalltalk Experts
613.225.8812 (V) 613.225.5943 (F) | http://www.objectpeople.on.ca
"Where's the kaboom? The EARTH-SHATTERING kaboom????
-Marvin the Martian"
Date: 97 May 15 6:16:11 am
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: hashing
What is better? A faster hash function or a more disperse hash function?
(an efficient hash function or an effective one?)
When you test for the equality of two sets you iterate over each of the =
elements. So, a slow hash function does not essentially change the =
complexity of the test. However, as a general rule, hashing is supposed =
to be fast, so it should be fast.
//Leandro
Date: 97 May 15 6:25:10 am
From: Ward Cunningham <ward@c2.com>
To: Ian Piumarta <piumarta@prof.inria.fr>
Cc: Squeak@create.ucsb.edu
Subject: Re: Casing the joint
Ian Piumarta wrote:
>
> > I've heard that such features have caused no end of problems in the lisp
> > community.
>
> Quasiquote? It's the best thing since sliced time!
Ian -- Your right. My statement left no room for argument. I am just
repeating a warning that was given to me by a lisp implementor around
1985. I should have challenged him then. "What kind of trouble?" I
should have asked. But I didn't. I thought I knew.
I had added the evaluated literal feature to Tektronix Smalltalk. It's
really a sweet little mod to the scanner that everyone should try. My
syntax was:
#[ an expression ]
which seemed to express literal (#) and unusual evaluation ([]) nicely.
I was concerned about the variety of evaluation contexts, but didn't
figure it was any worse than the special handling of class initialize
methods.
This extension was mentioned in a casual meeting with our visitor. (I'm
not being coy here. I'm actually having trouble remembering who. It
might have been Steele. It was at least someone who had seen quite a few
lisps and knew their weaknesses. A scheme guy for sure.) The warning was
immediate. I let the subject drop. I kept the feature in my own image
for quite a while, but I don't remember using it, or missing it. -- Ward
--
Ward Cunningham
v 503-245-5633 mailto:ward@c2.com
f 503-246-5587 http://c2.com/
Date: 97 May 15 6:47:36 am
From: Thierry Goubier <Thierry.Goubier@enst-bretagne.fr>
To: Anthony Lander <anthony@objectPeople.com>
Cc: squeak@create.ucsb.edu
In-Reply-To: <3.0.32.19970515085754.00912140@mail.objectPeople.com>
Subject: Re: Correcting long-standing problems
On Thu, 15 May 1997, Anthony Lander wrote:
> Once everyone (i.e. Dan) is busy correcting long-standing problems, such as
> hashing and coersion, could I convince you to tackle one more?
>
> #mustBeBoolean
> Man, this bothers me. I've reimplemented #doesNotUnderstand: more times
> than you can shake a stick at. You simply cannot build a good proxy object
> in Smalltalk because of this message. Can the VM be changed such that
> messages like #and: fail by really sending the #and: message (not inlined)
> instead of sending #mustBeBoolean?
I have maybe a question on this. The error will only happen if you have a
proxy standing as the result of a test, if I'm right. For example, it will
happen with : aProxy and: [<another test>], and probably in similar cases.
The question is what is the meaning of this expression ? I'd say that
either this is a programming error (would happen with something else
than a proxy) or an environment where your proxy has replaced true or
false. I've never dared doing the latter... For my persistent store, I
heavily rely on proxys, and have never managed to fall on this (I take
great care not to proxify objects like true or false, however). Can you
give an example of proxy uses when you managed to get this error ?
Thierry.
___________________Thierry.Goubier@enst-bretagne.fr__________________
But to look for heaven is to live here in hell [Sting]
http://www-info.enst-bretagne.fr/~goubier/
Date: 97 May 15 6:54:10 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: caniglia@mate.dm.uba.ar, squeak@create.ucsb.edu
Subject: RE: hashing
> What is better? A faster hash function or a more disperse hash function?
That depends on the density of collections. If all my (unordered)
collections have only one element in them, then the fastest hash function
possible is what I want. If all my collections are almost full, then the
most dispersed hash function is what I want. There's no "correct" answer
to the question: it will always be a compromise between generating a fast
initial probe index, and the number of reprobes needed to find the target
element (or nil ;-).
Maybe the question should be: "Does anyone know what the optimal
compromise is for the average collection in Squeak, taking into account
whatever happens to be the "grow threshold" for collections this week?"
Ian
PS: As usual you can trade space for time: setting the threshold low, so
that collections grow when they're e.g. 10% full, lets you get away with
a much faster (less disperse) hash function.
Date: 97 May 15 7:25:12 am
From: Anthony Lander <anthony@objectPeople.com>
To: Thierry Goubier <Thierry.Goubier@enst-bretagne.fr>
Cc: squeak@create.ucsb.edu
Subject: Re: Correcting long-standing problems
>[re: #mustBeBoolean being sent to a proxy object]
>
>I have maybe a question on this. The error will only happen if you have a
>proxy standing as the result of a test, if I'm right. For example, it will
>happen with : aProxy and: [<another test>], and probably in similar cases.
Sure. But that's not necessarily a bad thing. From the rest of your message, I
gather tha you don't think you should ever proxy sole-instance objects
(true, false, nil).
You are assuming that people only ever use proxies as message forwarders. I
have
a counter-example:
The specific case I'm thinking of uses a proxy object to catch the messages
it is
sent so that it can build a build parse tree from them. The parse tree is used
to cross-compile expressions into another language.
This opens another can of worms with respect to #== and #identityHash, and
with
respect to the transparency of compiler optimizations. I'll save all that
for another
time. I have to get my thoughts on the subject in order before I post them.
>For my persistent store, I heavily rely on proxys, and have never managed
to fall
>on this (I take great care not to proxify objects like true or false,
however).
Of course. With repect to persistence, you shouldn't proxy objects that
aren't part
of the application domain....well, except for maybe collections of domain
objects.
-Anthony
------------------------------------------------------------
Remember the five-step response of all experts
when first confronted with a new development in their field:
IGNORE, RIDICULE, ATTACK, COPY, STEAL. -Arthur Jones
Date: 97 May 15 8:12:56 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: mack@sfo.com (Michael Ackerman)
Cc: squeak@create.ucsb.edu
In-Reply-To: <v01510100afa07ee17752@[207.33.216.16]>
Subject: Re: Blue Book (and Orange, and a Trivia Question)
At 4:51 -0400 5/15/97, Michael Ackerman wrote:
>What is the Blue/Purple book?
>
>Michael Ackerman
It's two books, one with a big blue rectangle in the center of its cover,
and one with a similar but purple rectangle.
The Blue Book is: Smalltalk-80: the Language and Its Implementation,
Goldberg & Robson, Addison-Wesley, ca 1983. It is out of print but Powells
in Portland sometimes has it used. (http://www.powells.portland.or.us/)
You might also try Amazon.com who now carries used books, and does used
book searches.
The Purple Book is: Smalltalk-80: The Language, Goldberg & Robson,
Addison-Wesley, ca 1987. It is still in print so far as I know. It is the
blue book less a section in which Smalltalk is implemented in Smalltalk,
clearly a dumb idea! :-)
If you can find one, get the Blue Book. I have two and would not part with
either an any price anyone would pay, but you might find someone who will
sell.
There are two others: the Orange Book and the Green Book. The Orange Book
is Smalltalk-80: The Interactive Programming Environment; it tells how to
use Smalltalk-80.
The Green Book is Smallalk-80: Bits of History and Words of Advice, a set
of papers about implementing Smalltalk.
Both are old, though the Orange Book probably describes how to use early
versions of Squeak fairly well. (I haven't relly looked at it in years.)
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 15 8:19:22 am
From: Hans-Martin Mosner <hmm@heeg.de>
To: Squeak Mailing List <squeak@create.ucsb.edu>
Subject: Debugger Bug
Hello Squeakers,
there's a little bug in the code related to single stepping in the
debugger.
Symptom:
The bug can manifest itself in various forms. In my case, I got a
#primitiveFail when I was trying to access an instance variable through
a simple getter method, but you could conceivably get much more nasty
effects.
Cause:
The method ContextPart>>doPrimitive:receiver:args stuffs the primitive
number into a pre-existing method and then calls that method. After
modifying the method, it should flush the method lookup cache using
"Class flushCache", but this statement is commented out.
Fix:
To fix, just remove the comment quote around this statement.
Hans-Martin
Date: 97 May 15 8:30:55 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: joel@ObjectPeople.com
Cc: Ward Cunningham <ward@c2.com>, Dan Ingalls <DanI@wdi.disney.com>,
Squeak@create.ucsb.edu
In-Reply-To: <13073955100300@objectpeople.com>
Subject: Re: Casing the joint
At 5:11 -0400 5/15/97, joel@ObjectPeople.com wrote:
>> Date: Wed, 14 May 1997 15:42:13 -0700
>> From: Ward Cunningham <ward@c2.com>
>> Organization: Cunningham & Cunningham, Inc.
>> To: joel@ObjectPeople.com
>> Cc: Dan Ingalls <DanI@wdi.disney.com>, Squeak@create.ucsb.edu
>> Subject: Re: Casing the joint
>
>> > I think this is a great idea, and I like it. This is one area in
>> > which I think Smalltalk has fallen short, and they can be very
>> > useful.
>> >
>> > IBM/OTI has started an approach similar to this, I believe
>> > of the form ##( Time now seconds ), where ##( expression)
>> > makes a compile time constant, evaluating the 'expression'.
I hear that this construct, never documented except in the 3rd printing of
my IBM Smalltalk book, is no longer recommended due to some kind of problem
when developing on platform A an application intended for Platform B. (Like
building an image on Windows intended to run on MVS). The expression runs
on the development plaform and might answer, say, an IEEE float, but the
image runs on MVS which has a different float format. (IBM Smalltalk
normally requires loading an application into a development environment for
a target machine and then generation of a new runtime for that machine;
images are not portable; Envy applications are portable.)
I still think it is a nice construct and would suggest that Squeak use it
or some functional equivalent. Note that one can build most anything,
including dictionaries, and no aditional odd syntax is needed.
For some examples. see:
http://www.dnsmith.com/dnsmith/DNSSL2/htmlForAW/ver3new.html
and scroll down a screen or so.
>> I've heard that such features have caused no end of problems in the lisp
>> community. For example, I imagine code like
>>
>> {Form fromUser} display
>>
>> could be handy in development but hard to maintain. -- Ward
Some people can screw up anything!
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 15 9:13:33 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Ian Piumarta <piumarta@prof.inria.fr>
Cc: squeak@create.ucsb.edu
In-Reply-To: <199705151419.QAA26273@prof.inria.fr>
Subject: RE: hashing
At 10:19 -0400 5/15/97, Ian Piumarta wrote:
>> What is better? A faster hash function or a more disperse hash function?
>
>That depends on the density of collections. If all my (unordered)
>collections have only one element in them, then the fastest hash function
>possible is what I want. If all my collections are almost full, then the
>most dispersed hash function is what I want. There's no "correct" answer
>to the question: it will always be a compromise between generating a fast
>initial probe index, and the number of reprobes needed to find the target
>element (or nil ;-).
>
>Maybe the question should be: "Does anyone know what the optimal
>compromise is for the average collection in Squeak, taking into account
>whatever happens to be the "grow threshold" for collections this week?"
>
>Ian
>
>PS: As usual you can trade space for time: setting the threshold low, so
>that collections grow when they're e.g. 10% full, lets you get away with
>a much faster (less disperse) hash function.
If a hash answers the same value a lot then lots of collisions will occur.
Look in all the #scanFor: methods in collections. They all do sequential
searches from the 'hash point' to the end, and then wrap.
I've only examined Float (and I have a new version of Float>>#hash with a
better hash value and better measurements comming soon) but the original
hash distribution was awful. For example, here is one of my tests:
Float testHashSize: 100000 from: -20.0 to: 20.0 by: 0.0001
#hash Samples 400001 Zeros 97491 Min 1 Avg 4 Max 431 Dev 35.17
#hasnDNS Samples 400001 Zeros 34471 Min 1 Avg 4 Max 14 Dev 3.26
#hashDNS2 Samples 400001 Zeros 2079 Min 1 Avg 4 Max 13 Dev 1.98
The expression tests three hash algorithms using a bucket test with 100,000
buckets, the original, mine of a few days ago, and my new one. Zeros are
the number of empty buckets after generating 400,000 hash values.
Min/Avg/Max apply to non-zero buckets.
With 400,000 different float values and 100,000 buckets into which to put
the hashes:
* the original managed to answer (100,000-97,491) = 2509 different values
* my improved version, distributed by Dan recently, answered
(100,000-34471) = 65529 different answers (and it CAN answer only 65536
different answers since it answers a 16 bit number; I was surprised at how
well it did!)
* and the unreleased hash (30 bit answers) answered (100,000-2079) = 97921
different answers.
In the worst case, the newer algorithms at most answered the same value 14
times (though there is no way to tell now many times it did that). The
original managed to answer at least one hash value 431 times.
A bad hash slows everything down. Good hash values are hard to obtain (and
Float is probably an easy case). I think it is worth paying a bit more for
a decent hash value up front to prevent a lot of sequential searches trying
to find an empty slot. (My newest version is slower than the original by a
factor of 3 or less.)
The real problem here is the equal test that is required by Set/Bag &
friends. In other posts I've suggested that equality testing (#=) should
not be used in hashed collections since it leads to bad hashes and bizare
results.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 15 10:04:15 am
From: gregory@eng.adaptec.com (Greg Gritton x2386)
To: Thierry.Goubier@enst-bretagne.fr, anthony@objectPeople.com
Cc: squeak@create.ucsb.edu
Subject: Re: Correcting long-standing problems
Another use of a proxy for such basic objects such as true or false
is a "future". A future is a placeholder for a time-consuming operation
that is started in another thread (perferably on another processor)
and is ongoing. This is an easy to use construct for parallelizing
programs.
For example:
doTwoOperationsInParallel
| a b |
a := self anotherThreadsOperation.
b := self someOtherLongOperation.
a ifTrue: [ ^0 ] ifFalse: [ ^b ]
Suppose anotherThreadsOperation returned a proxy immediately,
and replaced that proxy with the actual result when the operation was
complete. A parallel system would be able to execute
anotherThreadsOperation and someOtherLongOperation at the same time.
The programmer would't have to worry about syncronizing them.
The two threads could occur in parallel until a message was sent
to the result of one of the threads.
In this example, the ifTrue:ifFalse: message is sent to "a".
If anotherThreadsOperation wasn't complete, this statement would
send the message ifTrue:ifFalse: to the proxy, which would then
stall until the actual value was available.
This example might not be directly applicable to Squeak now
(which I don't believe supports multiple CPUs), but illustrates
the general principle of replacing optimized message sends
with the actual message if the receiver isn't a boolen, rather
than simply responding with #mustBeBoolean.
It would seem the logically correct thing to do.
On the other hand, if doing this impacted the performance for the
vast majority of ifTrue:ifFalse: sends where the variable is a boolean,
it might be best to leave it the way it is. It is a tradeoff.
However, if there is no performance penalty to re-sending the correct
message rather than #mustBeBoolean, it would be useful for some things.
Greg Gritton
When
Date: 97 May 15 10:16:05 pm
From: Travis Griggs <tkc@bmi.net>
To: Thierry Goubier <Thierry.Goubier@enst-bretagne.fr>
Cc: Anthony Lander <anthony@objectPeople.com>, squeak@create.ucsb.edu
Subject: Re: Correcting long-standing problems
Thierry Goubier wrote:
>
> On Thu, 15 May 1997, Anthony Lander wrote:
>
> > Once everyone (i.e. Dan) is busy correcting long-standing problems, such as
> > hashing and coersion, could I convince you to tackle one more?
> >
> > #mustBeBoolean
> > Man, this bothers me. I've reimplemented #doesNotUnderstand: more times
> > than you can shake a stick at. You simply cannot build a good proxy object
> > in Smalltalk because of this message. Can the VM be changed such that
> > messages like #and: fail by really sending the #and: message (not inlined)
> > instead of sending #mustBeBoolean?
>
> I have maybe a question on this. The error will only happen if you have a
> proxy standing as the result of a test, if I'm right. For example, it will
> happen with : aProxy and: [<another test>], and probably in similar cases.
>
> The question is what is the meaning of this expression ? I'd say that
> either this is a programming error (would happen with something else
> than a proxy) or an environment where your proxy has replaced true or
> false. I've never dared doing the latter...
This is true. Most proxy schemes make special exceptions for some (if
not all) immutable object types (nil, true, false, SmallInt, character,
String, ByteArray) by creating local copies. Some even go further and
add quasi-immutable types as well (other number types, etc).
--
Travis or Kerrin Griggs
Key Technology (509) 529-2161
tkc@bmi.net (509) 527-8743
Date: 97 May 17 1:36:31 am
From: Hans-Martin Mosner <hm.mosner@cww.de>
To: Squeak Mailing List <squeak@create.ucsb.edu>
Subject: Color dithering (performance improvement)
Dies ist eine mehrteilige Nachricht im MIME-Format.
--------------5899337C242C
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Here is a new version of the color dithering code I sent out earlier.
The determination of te dither pixel values should be a bit faster, and
the method is slightly less convoluted.
Hans-Martin
--------------5899337C242C
Content-Type: text/plain; charset=us-ascii; x-mac-type="54455854"; x-mac-creator="522A6368"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline; filename="ColorDithering.cs"
'From Squeak 1.19d of April 13, 1997 on 17 May 1997 at 10:59:46 am'!
"Change Set: ColorDithering
Date: 17 May 1997
Author: Hans-Martin Mosner <hmm@heeg.de>
Enables dithering for 8-bit color, resulting in more color shades."!
!Color methodsFor: 'conversions'!
bitPatternForDepth: depth
"The raw call on BitBlt needs a Bitmap to represent this color. Return the color at the destination Form depth as a Bitmap. Patterns return longer Bitmaps. 6/14/96 tk
For the bits that are in a single pixel, use pixelValueAtDepth:.
For a 32-bit integer of (32/depth) pixels, use pixelWordAtDepth:"
| brightness |
depth == cachedDepth ifTrue: [^ cachedBitPattern].
cachedDepth _ depth.
depth > 1 ifTrue: [^ cachedBitPattern _ self computeBitPatternForDepth: depth].
"Spatial halftones for depth 1"
brightness _ self luminance.
brightness < 0.2 ifTrue: [
^ cachedBitPattern _ Bitmap with: 16rFFFFFFFF]. "black"
brightness < 0.4 ifTrue: [
^ cachedBitPattern _ Bitmap with: 16rBBBBBBBB with: 16rEEEEEEEE]. "dark gray"
brightness < 0.6 ifTrue: [
^ cachedBitPattern _ Bitmap with: 16r55555555 with: 16rAAAAAAAA]. "medium gray"
brightness < 0.8 ifTrue: [
^ cachedBitPattern _ Bitmap with: 16r44444444 with: 16r11111111]. "light gray"
^ cachedBitPattern _ Bitmap with: 16r0. "white"!
computeBitPatternForDepth: depth
| pixels |
depth = 8 ifFalse: [^Bitmap with: (self pixelWordForDepth: depth)].
pixels := self fourPixelValuesForDither: depth.
^Bitmap
with: (16r10001 * (pixels at: 1)) + (16r1000100 * (pixels at: 3))
with: (16r10001 * (pixels at: 2)) + (16r1000100 * (pixels at: 4))!
fourPixelValuesForDither: depth
"This only works in the 8-bit color cube."
"Color allInstancesDo: [:each | each bitPatternForDepth: 4]" "flush existing cached patterns"
| r g b rPlus gPlus bPlus rBase gBase bBase |
depth = 8 ifFalse: [^Array new: 4 withAll: (self pixelValueForDepth: depth)].
rgb = 0 ifTrue: [^ Array new: 4 withAll: 1]. "Special case for black, very common"
rgb = 16r3FFFFFFF ifTrue: [^ Array new: 4 withAll: 0 "255"]. "Special case for white, very common"
self privateRed = self privateGreen ifTrue: [
self privateRed = self privateBlue ifTrue: [^Array new: 4 withAll: self closestPixelValue8]].
r := (self privateRed * 20) + HalfComponentMask // ComponentMask.
g := (self privateGreen * 20) + HalfComponentMask // ComponentMask.
b := (self privateBlue * 20) + HalfComponentMask // ComponentMask.
rBase := r // 4.
rPlus := r \\ 4.
gBase := g // 4.
gPlus := g \\ 4.
bBase := b // 4.
bPlus := b \\ 4.
^(0 to: 3) collect: [:i |
(rBase + (i >= rPlus ifTrue: [0] ifFalse: [1]) * 36) +
(bBase + (i >= bPlus ifTrue: [0] ifFalse: [1]) * 6) +
(gBase + (i >= gPlus ifTrue: [0] ifFalse: [1])) + 40]
! !
--------------5899337C242C--
Date: 97 May 17 8:55:33 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Characters in intervals
All:
(A not too high-priority suggestion.)
This works fine:
| a |
a := OrderedCollection new: 10.
$1 asciiValue to: $9 asciiValue do: [ :ch |
a add: ch asCharacter ].
a
OrderedCollection ($1 $2 $3 $4 $5 $6 $7 $8 $9 )
But this does not (on Squeak or IBM or VW or others):
| a |
a := OrderedCollection new: 10.
$1 to: $9 do: [ :ch |
a add: ch ].
All fail trying to add a 1 to a character (or subtracting 1 from a
character!!). However, put parentheses around the interval and it works
again:
| a |
a := OrderedCollection new: 10.
($1 to: $9) do: [ :ch |
a add: ch ].
($1 $2 $3 $4 $5 $6 $7 $8 $9 )
I think the second version should work too and it should be easy to fix
with a new method in Character (similarily to how #to: is fixed):
to: other do: aBlock
"(DNS May97)"
| collection |
collection := (self asciiValue to: other asciiValue) collect:
[:ascii | Character value: ascii].
collection do: aBlock
except that #do:to: is compiled inline. This works:
| a |
a := OrderedCollection new: 10.
$1 perform: #to:do: with: $9 with: [ :ch |
a add: ch ].
($1 $2 $3 $4 $5 $6 $7 $8 $9 )
I would like to suggest that any magnitude that answers a collection from
the expression (a to: b) also work properly with with #to:do:. Anything
else violates the principle of lease surprise. (Actually Character seems,
on a quick look, to be the only other magnitude that supports #to:.)
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 17 2:48:27 pm
From: Dan Ingalls <DanI@wdi.disney.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v0310280cafa38609cdc6@[129.34.225.178]>
Subject: Re: Characters in intervals
>I think the second version should work too and it should be easy to fix
>with a new method in Character (similarily to how #to: is fixed):
>
>to: other do: aBlock
> "(DNS May97)"
> | collection |
> collection :=3D (self asciiValue to: other asciiValue) collect:
> [:ascii | Character value: ascii].
> collection do: aBlock
I'm with you regarding uniform behavior. In this case, though, I'd keep it =
simple:
<Magnitude> to: other do: aBlock
^ (self to: other) do: aBlock
What keeps it from being a simple fix is that the compiler has to check=
whether or not to compile to:do: inline. Right now it always does. We=
could check for non-integer constants, which would work for your example. =
But we still wouldn't be able to do "a to: b do: [...]" correctly, unless=
we stop compiling all cases of to:do: inline. Another use for type inferen=
ce.
- D
Date: 97 May 17 4:47:22 pm
From: johnson@cs.uiuc.edu (Ralph E. Johnson)
To: squeak@create.ucsb.edu
Subject: Re: Correcting long-standing problems
At 8:57 AM 5/15/97, Anthony Lander wrote:
>Once everyone (i.e. Dan) is busy correcting long-standing problems, such as
>hashing and coersion, could I convince you to tackle one more?
>
> #mustBeBoolean
>Man, this bothers me. I've reimplemented #doesNotUnderstand: more times
>than you can shake a stick at. You simply cannot build a good proxy object
>in Smalltalk because of this message. Can the VM be changed such that
>messages like #and: fail by really sending the #and: message (not inlined)
>instead of sending #mustBeBoolean?
This is not just a VM change. The compiler optimizes #and by
generating in-line branches. So, there is no block for the VM to
use as the argument of the message. I suppose the compiler could
generate two versions of the method, and the #mustBeBoolean message
could restart the slower version of the method. Alternatively, the
compiler could just not optimizie #and:. I bet it wouldn't make
much of a difference to most of the image. It is pretty easy to
hack the compiler to tell it not to optimize certain methods.
It has a table of methods that it optimizes, and you can just change
the table.
-Ralph
Date: 97 May 19 11:36:27 am
From: lnotarfr@dc.uba.ar (Luciano Esteban Notarfrancesco)
To: piumarta@prof.inria.fr (Ian Piumarta)
Cc: squeak@create.ucsb.edu
In-Reply-To: <199705151419.QAA26273@prof.inria.fr> from "Ian Piumarta" at May 15, 97 04:19:06 pm
Subject: Re: hashing
>
> > What is better? A faster hash function or a more disperse hash function?
>
> That depends on the density of collections. If all my (unordered)
> collections have only one element in them, then the fastest hash function
> possible is what I want. If all my collections are almost full, then the
> most dispersed hash function is what I want. There's no "correct" answer
> to the question: it will always be a compromise between generating a fast
> initial probe index, and the number of reprobes needed to find the target
> element (or nil ;-).
>
> Maybe the question should be: "Does anyone know what the optimal
> compromise is for the average collection in Squeak, taking into account
> whatever happens to be the "grow threshold" for collections this week?"
Actually, the problem here is related to the hash implementation for
unordered collection. For Sets, for example, I found only two ways to
do it: the easy one, that involves none of the elements of the Set
(e.g., ^self size) and the hard (slow) solution, that involves all the
elements of the Set (e.g., ^self inject: 0 into: [ :hashValue :each |
hashValue + each hash]). I don't know what to do in this case.
May be the problem here is not the iteration over all the elements of
the Set. The problem might be the hash function of the elements. I mean,
if the elements are all Integers or Symbols (objects with fast hash
functions) then it could be good (disperse and still fast) to iterate
over all of them and answer the sum of all the hashes.
A way to solve this (and probably a bad idea) is to implement another
hash guarrantied to be fast. For example, Object could implement
fastHash
^self hash
!
and that Set could do
fastHash
^self size
!
hash
^self inject: 0 into: [ :hashValue :each |
hashValue + each fastHash
]
!
... it's just the first alternative solution I found.
-- Luciano.
Date: 97 May 19 1:01:57 pm
From: "Terry Raymond" <traymond@craftedsmalltalk.com>
To: "squeak" <squeak@create.ucsb.edu>
Subject: OS/2 port of Squeak?
Hi
I just subscribed to this list and would like to know if there is an
OS/2 port of Squeak or is there one in progress?
Terry Raymond
Crafted Smalltalk
(401) 846-6573 http://www.craftedsmalltalk.com
Date: 97 May 20 4:55:22 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: squeak@create.ucsb.edu
Subject: New VM for Unix is in the usual place
Squeakers,
I've finally got round to copying the 1.19 VM from my laptop to the FTP
server. (It should have "made in Italy" stamped on it -- I was at a
conference when I first built it. ;-) On alix.inria.fr, in the directory
/pub/squeak/unix/Squeak-1.19d, you will find:
images/Squeak1.19.{image,changes} // as per Mac 1.19d distribution
images/SqueakV1.sources // as per Mac 1.19d distribution
(It's the "plain" 1.19d image with none of the patches sent to this list
since the original distribution.)
bin/SqueakVM-1.19-decAlpha-osf1_3.0* // stripped, etc...
bin/SqueakVM-1.19-i586-freebsd2.1.5
bin/SqueakVM-1.19-i586-linux1.2
bin/SqueakVM-1.19-sparc-solaris2.5*
bin/SqueakVM-1.19-sparc-sunos4.1*
src/...the...usual...stuff... // no gcc "goto" hacks applied
The mirrors on the other sites should catch up presently.
Please let me know immediately if you find any problems with any of these
VMs. (I've run each one briefly, and printed "Float pi", and they seem OK.)
New features include (and, apart from being built from the latest Interpreter
sources, are limited to):
- the image name now appears in the title bar/icon/whatever...
- the "-lazy" option has gone back in, with "busy" being the default
Luciano has implemented sound for Linux, but I've not had time to put the
support into the VM yet. Hopefully in the next couple of days. (I'll try to
do FreeBSD while I'm at it -- Luciano thinks that they're fairly similar.)
Also, if there's anyone out there with experience of NetAudio, and who would
like to implement support for it in Squeak, please get in touch.
People with other architectures are cordially invited to compile a VM, strip
it, and deposit the result in:
ftp://alix.inria.fr/pub/incoming
(then send me email to let me know that it's there!)
That's it. Enjoy!
Ian
------------------------------- projet SOR -------------------------------
Ian Piumarta, INRIA Rocquencourt, Internet: Ian.Piumarta@inria.fr
BP105, 78153 Le Chesnay Cedex, FRANCE Voice: +33 1 39 63 52 87
----------------------- Systemes a Objets Repartis -----------------------
Date: 97 May 20 9:26:45 am
From: Maloney <johnm@wdi.disney.com>
To: "Terry Raymond" <traymond@craftedsmalltalk.com>
Cc: "squeak" <squeak@create.ucsb.edu>
In-Reply-To: <199705192028.QAA24803@web2.idt.net>
Subject: Re: OS/2 port of Squeak?
At 1:23 PM -0400 5/19/97, Terry Raymond wrote:
>I just subscribed to this list and would like to know if there is an
>OS/2 port of Squeak or is there one in progress?
Not that I know of.
-- John
Date: 97 May 22 4:15:41 pm
From: "Terry Raymond" <traymond@craftedsmalltalk.com>
To: "squeak" <squeak@create.ucsb.edu>
Subject: Neon := Smalltalk + Forth
Hi
I just finished reading the archived messages and was suprised that with all
the discussion about Forth and Smalltalk no one mentioned Neon. Neon
was produced in the mid80's and it combined Forth and Smalltalk syntax.
It was available on the Mac only. Now, there are three follow on packages
that are available, all are free, Yerk, MOPS, and Win32Forth. Yerk and
MOPS are still Mac only packages. If you want to know more go to
dejanews and do a search in the c.l.f group. You can also get information
at www.forth.org.
Terry Raymond
Crafted Smalltalk
(401) 846-6573 http://www.craftedsmalltalk.com
Date: 97 May 22 5:41:30 pm
From: bbennett@unixg.ubc.ca
To: "squeak" <squeak@create.ucsb.edu>
In-Reply-To: <199705222342.TAA01863@web2.idt.net>
Subject: Re: Neon := Smalltalk + Forth
"Terry Raymond" <traymond@craftedsmalltalk.com> wrote:
>I just finished reading the archived messages and was suprised that with all
>the discussion about Forth and Smalltalk no one mentioned Neon. Neon
>was produced in the mid80's and it combined Forth and Smalltalk syntax.
>It was available on the Mac only. Now, there are three follow on packages
>that are available, all are free, Yerk, MOPS, and Win32Forth. Yerk and
>MOPS are still Mac only packages.
<snip>
Mops is not entirely Mac-only any longer.
Mike Hore, the author of Mops, has recently made an "adaptation of
Andrew McKewans's OOP system for ANS Standard Forth, to add further
extensions as provided by the Mops language."
<ftp://ftp.taygeta.com/Forth/ANS/classM10.txt>
<ftp://ftp.taygeta.com/Forth/ANS/classM10.zip>
-- Bruce Bennett <bbennett@unixg.ubc.ca>
Date: 97 May 22 6:33:04 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: New Arithmetic Coercion Mechanism
I have an observation about multiplication of fractional numbers. It may =
be not very critical in some applications but I think it must be =
considered here.
The traditional implementation of #* in the Fraction class uses =
something like this:
(Fraction
numerator: numerator * aNumber numerator
denominator: denominator * aNumber denominator) reduced
With this code the reduction is performed with a numerator and a =
denominator unnecessary "big" since this numbers are obtained by =
multiplication.
=20
Now consider this code
| f1 f2|
f1 :=3D numerator / aNumber denominator.
f2 :=3D aNumber numerator / denominator.
^Fraction
numerator: f1 numerator * f2 numerator
denominator: f1 denominator * f2 denominator
In this second version you change one reduction of possible big numbers =
with two reductions of smaller numbers.
This alternative version is a bit slower when all the numbers are small =
but is realy faster (10 times or so) than the traditional one when =
LargeIntegers are involved.
Saludos,
Leandro
Date: 97 May 22 8:29:21 pm
From: "Hal Hildebrand" <horus@pacbell.net>
To: "Squeak mailing list" <squeak@create.ucsb.edu>
Subject: Threaded interpreter
Is there some effort afoot (or ahand) at converting the Squeak interpreter
into a threaded interpreter?
Hoping to avoid duplication of effort...
Cheers,
Hal
__
Time is when the day is like a play by Sartre
When it seems that book burning's in perfect order
http://www.hellblazer.com (Web)
mailto:hal@parcplace.com (Business)
mailto:horus@pacbell.net (Personal)
Date: 97 May 22 10:30:48 pm
From: gregory@eng.adaptec.com (Greg Gritton x2386)
To: squeak@create.ucsb.edu, horus@pacbell.net
Subject: Re: Threaded interpreter
There is probably a lot of work that can be done before turning squeak
into a threaded interpreter. There is still a lot of time spent in
such methods as
- activateNewMethod
- lookupInMethodCacheSelclass
- recycleContextIfPossiblemethodContextClass
- fetchClassOf
- primitiveAt
Reorganizing the context structure to use stacks, the object format
to get rid of the special class format where the class is encoded into
the header word (with a lot of overhead every time a class
is fetched, which is required for dynamic dispatch),
combining commonly used bytecodes, etc. We can probably achieve
a significant speedup by doing these things without sacrificing
portability. Of course, a threaded interpreter would add
additional perfoemance.
Greg Gritton
Date: 97 May 23 1:02:18 am
From: "Han-earl -Zappaphile- Park" <8947020@arran.sms.ed.ac.uk>
To: squeak@create.ucsb.edu
Subject: Re: Neon := Smalltalk + Forth
>"Terry Raymond" <traymond@craftedsmalltalk.com> wrote:
>
>>I just finished reading the archived messages and was suprised that with all
>>the discussion about Forth and Smalltalk no one mentioned Neon. Neon
>>was produced in the mid80's and it combined Forth and Smalltalk syntax.
>>It was available on the Mac only. Now, there are three follow on packages
>>that are available, all are free, Yerk, MOPS, and Win32Forth. Yerk and
>>MOPS are still Mac only packages.
><snip>
For those interested in these things, there's at least one other Forth-Smalltalk
hybrid: HMSL (Hierarchical Music Specification Laguage) developed by Phil Burk,
Larry Polansky and David Rosenboom (and others). HMSL is avilable for the Mac
and Amiga (the OOP section was available separately as ODE on the Amiga
version).
Date: 97 May 23 9:32:27 am
From: Aaron Rosenzweig <recurve@xombi.wizard.net>
To: squeak@create.ucsb.edu
Cc: recurve@resourceful.com
Subject: Thanks!
I used Squeak in my computer science 330 class at the University of Maryland
this past semester. It was great! The class would have been many times more
unpleasant without it.
---
SW Son of Ginger and Harry, Aaron Rosenzweig
SW http://www.wam.umd.edu/~recurve/
SW... recurve@resourceful.com
SWN?
Date: 97 May 23 12:58:51 pm
From: Ian Piumarta <piumarta@prof.inria.fr>
To: gregory@eng.adaptec.com, hal@parcplace.com
Cc: squeak@create.ucsb.edu
Subject: Re: Threaded interpreter
Squeakers (Hal and Greg in particular),
Maybe it's time I explained to the list exactly what I've been doing
these past few weeks. Here's a very brief overview of the progress so
far.
I currently have two streams of VM development going on. The first
concerns dynamic translation.
I have implemented this directly in Squeak, writing it all in
Smalltalk rather than trying to build support for it in C or
assembler. To be fair, about 10 lines of compiler/architecture
specific code are required in the sq.h header file to support this,
although the GCC support is generic and will work on any platform
(including the Mac if you have either MachTen, [Mk]Linux[-pmac], or
CodeWarrior 11 [which allegedly comes with GCC]).
[Aside for John, if he's listening: the function call and "pointer
glue" code in the CW threaded dispatch costs almost nothing. I
succeeded in linking a GCC/MachTen-compiled interp.o (which has
inlined dispatches and no pointer glue) with the rest of the CW stuff
in the PPC project, and the performance is the same on all the Macs
(5400, 6400, 7600) that I've tried.]
We thought it would be interesting (at least initially) to see how
many of the management tasks could be performed using existing parts
of the system. For example, by translating CompiledMethods into real
Squeak obects the regular GC can take care of "flushing" stale
translated methods out of the object memory.
Currently, CompiledMethods are dynamically translated into a triplet
consisting of:
- an Array containing the addresses of (direct) threaded code
entry points, inlined operands for jump offsets, temp/receiver
variable indices, literal constants, and association pointers
for literal variables. The "opcode" addresses look like
SmallIntegers (many RISC architectures ignore the bottom 2 bits
in jump addresses) which allows the GC to take care of remapping
the inline "operands".
- a Bitmap containing a map of bytecode PC to threaded code PC
- a Bitmap containing a map of threaded code PC to bytecode PC.
The two PC maps are used for fetching and storing the context
registers, and for fetching the original bytecode when failing special
primitives. Both of these require further attention: e.g. it would be
nice to be able to store "raw" pointers into translated methods and
convert them into GC-safe forms only during a GC, and into the
Smalltalk-friendly forms only when it is known that a context will be
manipulated from Smalltalk. (More about this later.)
CompiledMethods are translated when they are first brought into the
method cache (there is an extra slot in each cache line to hold a
pointer to the translated method) during a send. For returns, the
translated method is also stored in a slot in MethodContexts.
The implementation of each opcode (there are currently about 70
opcodes, half of which are for the common and arithmetic sends) is
split into two parts to make simulation (in Smalltalk) easier. First
there is a definition part, which is used to initialise a table of
opcode entry points. Each opcode has an initialisation method that
looks like this:
oiMyOpcode
(self defineOp: MyOpcode) ifTrue: [
self beginOp: MyOpcode.
self opMyOpcode.
self endOp.
].
"MyOpcode" is a class variable containing an integer unique to this
opcode. In the compiled translator this is used to initialise the
correct slot in the opcode table with the address of the entry point
for the opcode, defined by the call to beginOp. "endOp" is the
threading operation, which causes the next instruction to be
dispatched. (endOp can be called anywhere within an opcode
implementation; e.g. if a special arithmetic opcode finds an integer
reveiver and argument that yield an integer result, the stack is
updated and endOp is called "internally" to elide the redundant jump
to the end of the opcode implementation.)
Second, the actual work of the opcode is performed in the
implementation method "opMyOpcode". Many of these look similar to the
implementations of the bytecodes in the current Interpreter.
The translator framework is written in such a way as to make the
bytecode-to-threaded code transformation as flexible as possible.
Several "common sequence" optimisations are already implemented, and
adding more is trivial. I also have a paper design for an inline
cache which should reduce the impact of the fetchClassOf overhead by
using several different "send" opcodes, specialised on the kind of
receiver. For example, the generic "send" opcode checks the class of
the receiver, and if it finds that it is a SmallInteger it replaces
the opcode with a different "send" specialised on SmallIntegers. This
latter "send" need only check the tag bit to decide if the cache has
hit or missed. It's obvious how this copes with the various kinds of
non-immediate objects having (for example) compact class headers,
etc...
Two passes are currently required to perform the translation. The
first pass "sizes" the translated code and builds the bytecode to
threaded PC map. The second pass generates the translated code,
resolving jump destinations using the map generated in the first pass,
and builds the threaded to bytecode PC map.
Threaded code performs about 10-20% better than byecodes on my
Performa, depending on the kind of work being done. (The figures are
better on the "serious" machines that we have at work -- mainly, I
suspect, because most of the gains are being swamped by the overheads
on my Mac due to its relatively low main memory bandwidth and sluggish
2nd level cache.)
The second stream of development is concerned with adding "volatile"
contexts to Squeak. (I also noticed that the majority of the time in
Squeak was being spent in message send and return.)
I have added a shared stack to the interpreter, which allows the
majority of message sends to avoid copying arguments. When a new
method is activated, a new "volatile" context is allocated for it.
None of the indexable fields of this context are used. Instead, a
volatile context contains two pointers: a "frame pointer" which points
to the first argument in the shared stack that is associated with its
activation, and a "stack pointer" which works just like the current
stackPointer, except that it points into the shared stack too. The
only loop needed during message sending is to store nil into the
temporary variable locations in the shared stack. The interpreter
also has a homePointer, which points at the first temporary location
for the active method/block (which could be either in the shared
stack, or inside the indexable part of the home context).
When an activation returns, its volatile context is placed on the head
of a free context list -- in much the same way as Squeak does things
at the moment. An important characteristic of this scheme is that
volatile contexts on the free list always have nil in their indexable
fields, so the loop in the current interpreter which clears these
fields is no longer needed.
Contexts are "stabilised" whenever they might outlive their
activations. Stabilisation involves copying the associated region of
the shared stack into the indexable part of the context. Stable
contexts are never recycled.
I considered using a scheme similar to BrouHaHa, but it turned out to
be impossible (or at least very expensive during stabilisation) with
the direct pointer object memory used in Squeak. (BrouHaHa benefits,
at least in this respect, from having an object table.)
I've "ruthlessly" hand-tuned the activateNewMethod and return:to:
methods, and am now looking at the remainder of the send code to find
other areas where it could be made faster. One thing which I will
implement in the next day or two is a change to the way blocks are
activated, so that the stored BlockContext is copied into a new
volatile context instead of being reactivated -- avoiding the need to
stablise the entire stack. A (rather unintentional ;-) side effect of
this will be that blocks become re-entrant. (From there it will
hopefully be trivial to integrate Hans Martin's closure work, at some
later date.)
There is a lot more performance to be gained from working on contexts.
However, these initial steps already show measurable performance
improvements during activities with both low and high allocation
rates:
benchmark: 30 benchFib Intepreter compileAll
units: calls/sec milliseconds
original Squeak: 459085 14350
volatile contexts: 503466 13408
gain: 10% 7%
(The benchFibs result is interesting: Squeak with volatile contexts on
a 333MHz DEC AXP has almost exactly the same activation performance as
ObjectWorks 4.1 on a Sparc IPX. ;-) ;-) ;-)
I've kept the context and translation work separate for the moment in
the hope that we'll be able to release a version of the Interpreter
that offers the new context handling without the additional overheads
implied by dynamic translation. In particular, the people working on
implementations for machines with small memories pobably wouldn't want
to pay the price of a larger object memory just to store the
translated code.
I'll keep you all updated w.r.t. further developments.
Ian
Date: 97 May 23 1:41:02 pm
From: James McCartney <james@clyde.as.utexas.edu>
To: Ian Piumarta <piumarta@prof.inria.fr>, squeak@create.ucsb.edu
Cc: squeak@create.ucsb.edu
In-Reply-To: <199705232025.WAA03394@prof.inria.fr>
Subject: Re: Threaded interpreter
At 1:25 PM -0700 5/23/97, Ian Piumarta wrote:
>Threaded code performs about 10-20% better than byecodes on my
>Performa, depending on the kind of work being done. (The figures are
>better on the "serious" machines that we have at work -- mainly, I
>suspect, because most of the gains are being swamped by the overheads
>on my Mac due to its relatively low main memory bandwidth and sluggish
>2nd level cache.)
Or perhaps it is that due to indirect function calls going through
the __ptr_glue() function on the PowerPC, it is not much faster to do
an indirect call than it is to switch().
--- james mccartney james@clyde.as.utexas.edu james@lcsaudio.com
If you have a PowerMac check out SuperCollider, a real time synth program:
ftp://mirror.apple.com//mirrors/Info-Mac.Archive/gst/snd/super-collider-demo.hqx
Date: 97 May 24 5:49:37 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: james@clyde.as.utexas.edu
Cc: squeak@create.ucsb.edu
Subject: Re: Threaded interpreter
> Or perhaps it is that due to indirect function calls going through
> the __ptr_glue() function on the PowerPC, it is not much faster to do
> an indirect call than it is to switch().
I don't think this is a problem. Using an interp.o compiled with GCC
under MachTen (which generates an *inlined* dispatch that involves
neither function call nor pointer glue), linked with the regular
CodeWarrior PPC files under MacOS, the performance is the same. (This is
quite surprising in itself, considering the rather poor code generated by
the CW compiler for all the convoluted constants in the arithmetic for
fetch/storePointer: etc...)
The PPC has an impressive bunch of pre-fetch logic that may well be
reducing the overhead of the function call to something approaching zero.
Ian
Date: 97 May 24 11:21:27 am
From: Paul Fernhout <kfsoft@netins.net>
Cc: squeak@create.ucsb.edu, pmueller@decrc.abb.de
Subject: Re: mobile robot language
Peter Mueller <pmueller@decrc.abb.de> wrote:
>
> I built a small mobile robot and searching for a 'language' to programm
> its movements.
>
> My idea is to have a (script)-language like this:
>
> move to point x,y
> set speed to z
> drive circular path ..
> ...
> ..
>
> I plan to download this as 'text' and interpred it by the robot. Is
> there a general used language like this? Is there a simulator for such
> script-languages (to predict the path)?
>
> Peter Mueller
Peter -
If your robot is going to have PC based controller (running Windows 95,
Unix, or Apple O/S) your could try using Squeak, which is available for
free at one of these sites (one is in Germany):
http://www.research.apple.com/research/proj/learning_concepts/squeak/
ftp://ftp.cs.uni-magdeburg.de/pub/Smalltalk/free/squeak/win32/
ftp://alix.inria.fr:/pub/squeak/
Squeak is a version of Smalltalk which includes complete source code and
has very few restrictions on commerical use. You can recompile the VM
(using a C compiler) and add primitives to do I/O. The biggest drawback
to the current version of Squeak is that is runs about 40X - 60X slower
than compiled C code. However, people are working on the improving the
speed, and for many applications, speed is not a major issue, or you can
delegate the computationally intensive part to a C coded primitive.
You could write an interpreter for a language like what you described
fairly easily in Smalltalk (once you learned the language and something
about writing interpreters in it - a freeware library of Smalltalk code
called TGEN might help with this).
Alternatively, and more easily, since a Squeak run-time may include the
Smalltalk compiler, you could send Smalltalk code directly to your
onboard Squeak environment, such as:
robot moveToPoint: x @ y. "move to point x,y"
robot setSpeedTo: z. "set speed to z"
robot driveCircularPath. "drive circular path"
The performance of such code sent directly to Squeak (even given its
slow performance) would likely be as good or better than the performance
from any interpreter you were to write from scratch in the near term.
On the subject of simulating paths: to use some object oriented
programming jargon, you could create two types of concrete robot classes
under a common superclass:
AbstractRobot
RealRobot
SimulatedRobot
A simulated robot instance
"robot := SimulatedRobot newForWindow: aRobotSimulationWindow"
could be used to test your code in a graphical window (implemented using
Squeak's graphical pen, which acts as 2D turtle). A real robot instance
"robot := RealRobot newForController: aRobotIOController"
would call I/O routines instead. Both could have the same interface,
defined in the class AbstractRobot.
Squeak comes with a complete range of tools to speed development
(debugger, inspector, browser, garbage collector, limited version
control). Smalltalk allows you to select expressions from a text window
and by choosing "do it" from a menu, the expression is compiled and
executed. This is useful for testing your robot code one step at a time
via simulation. If your robot is tethered to a development workstation,
you can test it interactively, either by having the desktop workstation
talk to the motor controller directly, or by just sending arbitray
snippets of code through to the robot as you select them or type them on
the workstation.
Someone else in this thread on comp.robotics.misc mentioned using Forth,
which is another good solution, and would have a much smaller learning
curve, and run well on less powerful machines. Forth is easier to use
to get started in doing real time control, and in the past I have used
it (via an onboard Forth computer) to send commands to a mobile robot
from a PC.
However, Squeak offers a much more powerful programming environment for
complex systems than Forth (including an portable graphics and windowing
system), which might be an advantage in the long term. Ideally, someday
I would like to see a mixture of Forth and Smalltalk somehow combining
the best features of both for use in simulation, knowledge engineering,
and real-time control.
-Paul Fernhout
Kurtz-Fernhout Software
kfsoft@netins.net
========================================
Download a public beta release of our garden simulator at:
http://www.gardenwithinsight.com
Date: 97 May 24 12:09:48 pm
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Bug in Fraction readFrom:
Hi:
Number>>#readFrom: does not handle fractions, leading to:
Fraction readFrom: '2/3'
producing the value 2. Here is a corrected version of
Number>>#readRemainderOf: which has four new lines near the end for
fractions. It doesn't fix the oddity of:
Fraction readFrom: '2.3'
producing the floating value 2.3! This is a general problem with #readFrom:
that, if fixed, would require splitting #readRemainderOf: into parts and
putting them in various classes, meanwhile probably breaking something
else. It also doesn't fix the oddity of '2asf' being 2, but that is another
story.
If you can't read the following, widen your mail window; in mine the
default tabs are 8 spaces and it looks awful in a narrow window.
readRemainderOf: integerPart from: aStream base: base
"Read optional fractional part and exponent, and return the final
result"
| value fraction fracpos |
value _ integerPart.
(aStream peekFor: $.)
ifTrue:
["<integer>.<fraction>"
(aStream atEnd not and: [aStream peek digitValue
between: 0 and: base - 1])
ifTrue:
[fracpos _ aStream position.
fraction _ Integer readFrom:
aStream base: base.
fraction _
fraction asFloat / (base
raisedTo: aStream position - fracpos).
value _ value asFloat + (value < 0
ifTrue: [fraction negated]
ifFalse: [fraction])]
ifFalse:
["oops - just <integer>."
aStream skip: -1.
"un-gobble the period"
^ value
"Number readFrom: '3r-22.2'"]].
(aStream peekFor: $e)
ifTrue:
["<integer>e<exponent>"
^ value * (base raisedTo: (Integer readFrom:
aStream))].
(aStream peekFor: $/) "DNS added four lines here
*************************************"
ifTrue:
["<integer>/integer"
^ value / (Integer readFrom: aStream)].
^ value
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 24 1:50:44 pm
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
In-Reply-To: <v03102800afacf0784526@[129.34.225.178]>
Subject: Re: Bug in Fraction readFrom:
At 15:37 -0400 5/24/97, David N. Smith wrote:
>If you can't read the following, widen your mail window; in mine the
>default tabs are 8 spaces and it looks awful in a narrow window.
Seemed lke a good idea :-)
Turns out that something folded all the lines and it's a mess.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 24 1:54:13 pm
From: "Hal Hildebrand" <horus@pacbell.net>
To: "Paul Fernhout" <kfsoft@netins.net>
Cc: <squeak@create.ucsb.edu>, <pmueller@decrc.abb.de>
Subject: Re: mobile robot language
Peter Mueller <pmueller@decrc.abb.de> wrote:
>
> I built a small mobile robot and searching for a 'language' to programm
> its movements.
>
> My idea is to have a (script)-language like this:
>
> move to point x,y
> set speed to z
> drive circular path ..
> ...
> ..
>
> I plan to download this as 'text' and interpred it by the robot. Is
> there a general used language like this? Is there a simulator for such
> script-languages (to predict the path)?
>
> Peter Mueller
Peter,
for what it's worth, this seems like an ideal application of "turtle"
geometry. Just like the Logo guys did. Smalltalk is an excellent language
for building these simulations.
Hal
__
Time is when the day is like a play by Sartre
When it seems that book burning's in perfect order
http://www.hellblazer.com (Web)
mailto:hal@parcplace.com (Business)
mailto:horus@pacbell.net (Personal)
Date: 97 May 25 7:56:04 am
From: "Hal Hildebrand" <horus@pacbell.net>
To: <gregory@eng.adaptec.com>, "Ian Piumarta" <piumarta@prof.inria.fr>
Cc: <squeak@create.ucsb.edu>
Subject: Re: Threaded interpreter
Okay, so this is a lot of work. It's going to take me a while to get the
big picture on the current translator architecture. But, this is fun.
The approach I prefer is to use 32 bit opcodes directly, rather than
bytecodes. You have a canonical form for image saves, and method creates.
But, when the method is first run, the translation to machine specific
addresses happens "in place", overwriting the compiled method's bytes.
Upon image save, these compiled methods are reconverted to the canonical
form.
Using a wide op code space allows you to create a CISC-like interpreter,
encoding the common bytecode sequences directly by the compiler. My
preference, anyway.
I like Ian's idea of making as much use of ST as one can in creating a
dynamic translator. Some guys I know did the same thing with Java. Worked
out pretty well.
A key to speed is the stack, however. One can provide the illusion of full
closures without paying the cost. You just have to be willing to provide
support for "thisContext" entirely through primitives, and you can never
store "thisContext" into a variable.
Oh well, lot's to do. Lot's to do.
Thanks, all, for such a wonderful system to play with. It's pretty cool.
Hal
__
Time is when the day is like a play by Sartre
When it seems that book burning's in perfect order
http://www.hellblazer.com (Web)
mailto:hal@parcplace.com (Business)
mailto:horus@pacbell.net (Personal)
Date: 97 May 25 7:02:38 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: [Windows] arrow keys
Hi.
The arrow keys do not move the cursor in my 1.19d for Windows (I am using NT 4.0).
The same problem happens with Home, End, Page Up and Page Down.
Has anybody else found these difficulties?
Saludos,
Leandro
Date: 97 May 25 7:19:01 pm
From: johnson@cs.uiuc.edu (Ralph E. Johnson)
To: "Hal Hildebrand" <horus@pacbell.net>
Cc: <squeak@create.ucsb.edu>
Subject: Re: Threaded interpreter
So, you have discovered Squeak! I signed up on the list some time
ago and got one of the versions of Squeak, but I haven't had time
to do much more than just look around. It is neat to have a free
Smalltalk-80, it is neat that it is implemented in itself, and there
is a neat community forming around it. I'm glad you are interested.
But how do you have the time to play with it?
-Ralph
Date: 97 May 26 8:51:42 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Decompiled code is wrong; more float problems
I ran this code from a workspace:
| from to mult |
from := 1.0e-200.
to := 1.0e200.
mult := 5.0.
[ from <= to ]
whileTrue: [
from asTrueFraction2.
from := from * mult ].
Since it took a while, I command-dotted it and saw this, not so equivalent,
source code:
DoIt
| t1 t2 t3 |
t1 _ 1.00000000000002e-200.
t2 _ 9.99999999999968e199.
[t1 <= t2]
whileTrue:
[t1 asTrueFraction2.
t1 _ t1 * t3].
t3 _ 5.0.
^ nil
Note the t3 := 5.0 AFTER the loop. Somehow it got moved...
Also, the floating point constants are a bother. Take 1.0e200, select it,
and successively do Command-P. You get a series of numbers like this:
1.0e200
9.99999999999968e199
9.99999999999936e199
9.99999999999904e199
9.99999999999872e199
9.9999999999984e199
Thus, recompiling the decompiled code causes the values to become different.
So, I thought, use printStringBase: to produce a value in hex and output
the decimal value as a comment. This will take the original version's
binary equivalent and faithfully reproduce it.
1.0e200 printStringBase: 16
'1.4E718D7D762Ae166'
This hex result requires a leading '16r', so I added one:
16r1.4E718D7D762Ae166
Evaluating that got:
1.30642017663028
which means that the exponent is being totally ignored.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 26 10:45:39 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Update to asTrueFraction; faster; better comments
All:
Here is an improved asTrueFraction to replace the version of a few weeks
ago. I profiled it on IBM Smalltalk V4 and found several places to increase
its performance. Profiling it on Squeak showed that most of the time (70%)
is spent in #gcd:. I also added comments, hopefully to make it less opaque
for those who don't carry IEEE float formats around intheir heads. :-)
'From Squeak 1.19d of April 13, 1997 on 26 May 1997 at 12:40:59 pm'!
!Float methodsFor: 'converting'!
asTrueFraction2
" Answer a fraction that EXACTLY represents self,
a double precision IEEE floating point number.
Floats are stored in the same form on all platforms.
(Does not handle gradual underflow or NANs.) "
| shifty sign exp fraction result |
" Extract the bits of an IEEE double float "
shifty := ((self basicAt: 1) bitShift: 32) + (self basicAt: 2).
" Extract the sign and the biased exponent "
sign := (shifty bitShift: -63) = 0 ifTrue: [1] ifFalse: [-1].
exp := (shifty bitShift: -52) bitAnd: 16r7FF.
" Extract fractional part; answer 0 if this is a true 0.0 value "
fraction := shifty bitAnd: 16r000FFFFFFFFFFFFF.
( exp=0 and: [(fraction=0) & (self=0.0)] ) ifTrue: [ ^ 0 ].
" Replace omitted leading 1 in fraction; unbias exponent "
fraction := fraction bitOr: 16r0010000000000000.
exp := exp - 16r3FF.
" Form the result; (this is faster than more obvious code) "
result := exp <= 52
ifTrue: [ sign * fraction / (1 bitShift: 52 - exp) ]
ifFalse: [ sign * fraction * (1 bitShift: exp - 52) ].
" Validate the result (low cost; optional); answer result "
result asFloat = self
ifFalse: [self error: 'asTrueFraction validation failed' ].
^ result! !
The timings below are shown for Squeak 1.19d and VW 2.5 on the same
machine. The absolutely horrrible results for 1.0E-200 seem to be due to
very slow long integer support in Squeak, and the necessity of invoking the
fancy #gcd: which aggravates the problem when values are very large. (It's
1/3 the speed of Eucled's algorithm for the fractional components of
1.0e-200, though much faster on, say, Float pi).
Tests and timings on PPC 9600/200, V1.19d
=========================================
New version (asTrueFraction2):
Time millisecondsToRun: [ 1000 timesRepeat: [ Float pi asTrueFraction2 ] ]
9134
Time millisecondsToRun: [ 1000 timesRepeat: [ 3.14159262e200
asTrueFraction2 ] ]
6833
Time millisecondsToRun: [ 1000 timesRepeat: [ 3.14159262e-200
asTrueFraction2 ] ]
317160
Old version (asTrueFraction):
Time millisecondsToRun: [ 1000 timesRepeat: [ Float pi asTrueFraction ] ]
18084
Time millisecondsToRun: [ 1000 timesRepeat: [ 3.14159262e200 asTrueFraction
] ]
60050
Time millisecondsToRun: [ 1000 timesRepeat: [ 3.14159262e-200
asTrueFraction ] ]
641000
Original version (asFraction):
Time millisecondsToRun: [ 1000 timesRepeat: [ Float pi asFraction ] ]
267
Time millisecondsToRun: [ 100 timesRepeat: [ 3.14159262e200 asFraction ] ]
"Runs out of memory"
Time millisecondsToRun: [ 100 timesRepeat: [ 3.14159262e-200 asFraction ] ]
"Runs out of memory"
Tests and timings on PPC 9600/200, VW 2.5
=========================================
Time millisecondsToRun: [ 1000 timesRepeat: [ Double pi asTrueFraction2 ] ]
483
Time millisecondsToRun: [ 1000 timesRepeat: [ 3.14159262d200
asTrueFraction2 ] ]
916
Time millisecondsToRun: [ 1000 timesRepeat: [ 3.14159262d-200
asTrueFraction2 ] ]
933
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 26 11:26:26 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: squeak@create.ucsb.edu
Subject: Profiler & Messed up windows
All:
I used the profiler in squeak for the first time today and:
(1) it worked and I got useful results, but
(2) it left the windowing system in a real mess.
Even after closing the profiler and saving the image and restarting it is
still messed up. It seems to forget what window is active, it leaves
garbage laying around, blacks out overlayed parts of windows, pastes to the
wrong place, etc. One can get a window active by selecting in it several
times and then redrawing the whole screen and things work OK for a while,
until you change windows.
Has anyone else seen this behavior or have I screwed something up? I've not
been messing with windowing nor have I loaded any new stuff. I'm on 1.19d.
Here is the message I evaluated:
MessageTally spyOn: [10 timesRepeat: [ 3.14159262e-200 asTrueFraction2 ]]
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 26 1:45:45 pm
From: Dan Ingalls <DanI@wdi.disney.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v03102807afaf84b2bfba@[129.34.225.178]>
Subject: Re: Profiler & Messed up windows
>All:
>
>I used the profiler in squeak for the first time today and:
>
>(1) it worked and I got useful results, but
>
>(2) it left the windowing system in a real mess.
As far as I know, the profiler (MessageTally) in Squeak works well and=
behaves well, PROVIDED THAT the expression you give it to evaluate=
terminates normally. If it encounters an error, a process switch occurs in=
putting up a debugger, and the pending delays in the profiling process can=
run amok. I have had this happen myself, and experienced a very similar ef=
fect.
The obvious solution is to call the messageTally and arrange for an orderly=
shut-down before scheduling the debugger window. Right now I'm tied up=
doing fun things in Morphic [hope to put out an image for Morphic followers=
to experiment with in a few days], but I'll put this one on my list for the=
next release.
David, by all means let me know again if you experience this behavior with=
well-terminated profiles.
- Dan
Date: 97 May 27 4:07:13 am
From: Ian Piumarta <piumarta@prof.inria.fr>
To: dnsmith@watson.ibm.com, squeak@create.ucsb.edu
Subject: Re: Decompiled code is wrong; more float problems
The decompiler is severely broken in various subtle ways. Try holding
down the shift key while browsing CharacterScanner>>scanCharsFrom:to:...
For a more drastic demonstration, remove your sources file and then try
to recompile the image.
Ian
Date: 97 May 27 8:57:36 am
From: lnotarfr@dc.uba.ar (Luciano Esteban Notarfrancesco)
To: squeak@create.ucsb.edu
Subject: degreeSin
Integer implements
degreeSin
^self asFloat degreesToRadians sin
!
but this fails for big integers.
It's better to do:
degreeSin
^(self \\ 360) asFloat degreesToRadians sin
!
Furthermore, I saw that sqrt is not reimplemented in Integer, but it
should be ("anInteger squared sqrt" must answer "anInteger").
Regards,
--- Luciano.
Date: 97 May 27 7:59:15 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: How to sum fractions 2 times faster
Some messages ago I pointed out how to multiply two Fractions improving =
the speed of calculation in a noticeably factor. Today Luciano and me =
tested the following code for the sum #++
++ aFraction
"Answer the sum of the receiver and aFraction."
| crossProduct denGcd crossGcd leftDen rightDen |
(aFraction isMemberOf: Fraction)
ifTrue: [
denGcd _ denominator gcd: aFraction denominator.
leftDen _ denominator // denGcd.
rightDen _ aFraction denominator // denGcd.
crossProduct _ numerator * rightDen + (aFraction numerator * leftDen).
crossGcd _ crossProduct gcd: denGcd.
^Fraction
numerator: crossProduct // crossGcd
denominator: leftDen * rightDen * (denGcd // crossGcd)]
ifFalse: [^ self retry: #+ coercing: aFraction]
The results of our tests were interesting also in this case. With a =
number of fractions made up of random small integers the sum #++ =
evaluated twice as faster than the traditional #+. With bigger integers =
the velocity was three times faster.
This is the code we used for testing
'From Squeak 1.19d of April 13, 1997 on 27 May 1997 at 4:24:34 pm'!!
Fraction class methodsFor: 'examples'!
testSum
"Compare the implementation of #+ with that of #++"
| delta initial interval random t tt t0 answer |
delta _ 100. initial _ 1000000.
answer _ FillInTheBlank
request: 'Magnitude of the numbers'
initialAnswer: initial printString.
answer isNil ifFalse: [initial _ answer asNumber].
interval _ (initial to: initial + delta).
random _ (1 to: delta) collect: [:each |
(interval atRandom / interval atRandom) asFraction
@ (interval atRandom / interval atRandom) asFraction].
t _ Time millisecondsToRun: [random do: [:each | each x + each y]].
tt _ Time millisecondsToRun: [random do: [:each | each x ++ each y]].
t0 _ Time millisecondsToRun: [random do: [:each | each x. each y]].
^ t - t0 / (tt - t0) asFloat ! !
Saludos,
Leandro
Date: 97 May 27 11:06:46 pm
From: Maloney <johnm@wdi.disney.com>
To: gregory@eng.adaptec.com (Greg Gritton x2386)
Cc: squeak@create.ucsb.edu
In-Reply-To: <9705230556.AA26747@eng.adaptec.com>
Subject: Re: Threaded interpreter
Re:
>There is probably a lot of work that can be done before turning squeak
>into a threaded interpreter.
Yes, we know. Squeak is 50-60 times slower than optimized C on the
PowerPC. Digitalk Smalltalk (a very good interpreter) is 15-20 times
slower than optimized C on a 68020. So, one should be able to get
a factor of three or so without using threaded code.
However, it may be easier to get a similar or greater speedup via
threading. Ian Piumarta has been working on that, as you know. It
may turn out that his context handling improvements give us the
most bang for the buck, in which case we may abandon the threading
idea. I love the fact that he's pursuing the two optimizations
independently.
By the way, what platform have you been doing your profiling on
and what kind of profiler is it (e.g., PC-sampling on clock interrupts).
Also, what benchmarks were you measuring? Your hot list looks pretty
familiar except the fetchClassOf. But my profiler (CodeWarrior on the Mac)
is not very trustworthy; it tries to measure the time per method but
it doesn't properly factor out the cost of the profiler code itself.
-- John
>There is probably a lot of work that can be done before turning squeak
>into a threaded interpreter. There is still a lot of time spent in
>such methods as
>
> - activateNewMethod
> - lookupInMethodCacheSelclass
> - recycleContextIfPossiblemethodContextClass
> - fetchClassOf
> - primitiveAt
>
>Reorganizing the context structure to use stacks, the object format
>to get rid of the special class format where the class is encoded into
>the header word (with a lot of overhead every time a class
>is fetched, which is required for dynamic dispatch),
>combining commonly used bytecodes, etc. We can probably achieve
>a significant speedup by doing these things without sacrificing
>portability. Of course, a threaded interpreter would add
>additional perfoemance.
>
>Greg Gritton
Date: 97 May 28 12:28:53 am
From: "Hal Hildebrand" <horus@pacbell.net>
To: "Greg Gritton x2386" <gregory@eng.adaptec.com>,
"Maloney" <johnm@wdi.disney.com>
Cc: <squeak@create.ucsb.edu>
Subject: Re: Threaded interpreter
John,
>However, it may be easier to get a similar or greater speedup via
>threading. Ian Piumarta has been working on that, as you know. It
>may turn out that his context handling improvements give us the
>most bang for the buck, in which case we may abandon the threading
>idea. I love the fact that he's pursuing the two optimizations
>independently.
Agreed. Building frames faster, with a C-style stack, will do wonders for
the system. It'll be interesting to see what the speed gains are just from
that optimization.
Hal
__
Time is when the day is like a play by Sartre
When it seems that book burning's in perfect order
http://www.hellblazer.com (Web)
mailto:hal@parcplace.com (Business)
mailto:horus@pacbell.net (Personal)
Date: 97 May 28 5:15:32 am
From: Jean Francois Veillette <jfv@hasc.com>
To: squeak@create.ucsb.edu
Subject: Problem with BlockContext.
Sorry if it's a beginner question, but I am.
Why the following code doesn't work ?
| fib |
fib := [:va | va == 1 ifFalse:[ ^ va + ( fib value:va - 1)].
^ 1.].
fib value:5
I'm running it in workspace and squeak finish with a "Message not understood: *" error,
why ?
Thank's !
- jfv
Jean-Francois Veillette
Date: 97 May 28 6:35:16 am
From: Thierry Goubier <Thierry.Goubier@enst-bretagne.fr>
To: squeak@create.ucsb.edu
Subject: File out with shared pools
Hello all,
Trying to file out with squeak (1.19d), I find something which looked like
an error in the code to file out a shared pool variable. I corrected it
with the following, changing an 'asSortedCollection do:' with
'associationsDo:'.
'From Squeak 1.19d of April 13, 1997 on 28 May 1997 at 1:26:05 pm'!
!Class methodsFor: 'fileIn/Out'!
fileOutPool: aPool onFileStream: aFileStream
| aPoolName |
aPoolName _ Smalltalk keyAtValue: aPool.
Transcript cr; show: aPoolName.
aFileStream nextPutAll: 'Transcript show: ''' , aPoolName , '''; cr!!'; cr.
aFileStream nextPutAll: 'Smalltalk at: #' , aPoolName , ' put: Dictionary new!!'; cr.
aPool associationsDo: [ :anItem |
aFileStream nextPutAll: aPoolName , ' at: #' , anItem key asString , ' put: '.
(anItem value isKindOf: Number)
ifTrue: [anItem value printOn: aFileStream]
ifFalse: [aFileStream nextPutAll: '('.
anItem value printOn: aFileStream.
aFileStream nextPutAll: ')'].
aFileStream nextPutAll: '!!'; cr].
aFileStream cr! !
___________________Thierry.Goubier@enst-bretagne.fr__________________
But to look for heaven is to live here in hell [Sting]
http://www-info.enst-bretagne.fr/~goubier/
Date: 97 May 28 12:18:32 pm
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Dan Ingalls <DanI@wdi.disney.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v0300781cafafac2fcbbf@[206.16.10.79]>
Subject: Re: Profiler & Messed up windows
At 18:11 -0400 5/26/97, Dan Ingalls wrote:
>>All:
>>
>>I used the profiler in squeak for the first time today and:
>>
>>(1) it worked and I got useful results, but
>>
>>(2) it left the windowing system in a real mess.
>
> ...SNIP...
>David, by all means let me know again if you experience this behavior with
>well-terminated profiles.
>
> - Dan
Dan:
I must have tried to stop the profiler. I can reproduce the mess by
stopping it and not otherwise.
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 28 1:31:56 pm
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Jean Francois Veillette <jfv@hasc.com>
Cc: squeak@create.ucsb.edu
In-Reply-To: <199705281241.IAA16911@karm.hasc.com>
Subject: Re: Problem with BlockContext. (SYSTEM BUGS FOUND)
At 8:41 -0400 5/28/97, Jean Francois Veillette wrote:
>Sorry if it's a beginner question, but I am.
>
>Why the following code doesn't work ?
>
>| fib |
>fib := [:va | va == 1 ifFalse:[ ^ va + ( fib value:va - 1)].
> ^ 1.].
>fib value:5
>
>
>I'm running it in workspace and squeak finish with a "Message not
>understood: *" error,
>why ?
>
>Thank's !
>
>- jfv
>
>Jean-Francois Veillette
I think there are four problems here:
* Blocks are not closures in Squeak, so the variable va is 'global' to the
method.
* Squeak doesn't support recursive block invocations (I suspect).
* You don't want to use returns. (See below).
* Your algorithm has a bug.
You don't want to use a return since a return from a block returns from the
method and you don't want to do that. You really wanted something like this
(which runs fine on IBM Smalltalk and answers 15, though that's not right):
| fib |
fib := [:va |
va == 1
ifTrue: [ 1 ]
ifFalse:[ va + ( fib value: va - 1)] ].
fib value:5
15
This produces the correct answer:
| fib |
fib := [:va |
va < 3
ifTrue: [ 1 ]
ifFalse:[ (fib value: va - 2) + ( fib value: va -
1)] ].
fib value: 5
5
I tried to rewrite your code to eliminate returns and then show what it
really does with the local variable:
| fib va |
fib := [ va == 1
ifTrue: [ 1 ]
ifFalse:[ va := va - 1. fib value. va := va + va ] ].
va := 5.
fib value
This isn't quie right but it causes Squeak to get a system error (on my PPC
9500 with MacOS 7.5.5) and takes MacOS down. I quit trying! :-)
This still doesn't answer what your code is doing (though I get a plus
operator, not a multiplication). I suspect that Squeak doesn't allow
recursive invocations of blocks either, though someone who knows might let
us know.
I also found a bug in the debugger with your code: when I ask for a full
stack there is no thumb in the scroll bar. This simply means that there are
too many stack levels (though the debugger is wrong). It looks like the
code is in an infinite loop and dies a strange death.
Welcome to Smalltalk! Not all first encounters are like this. :-)
Fib is better implemented as a method. This one returns one term of the series:
fibonacci
" Answer the self'th fibonacci number: 5 fibonacci "
self < 3 ifTrue: [ ^ 1 ].
^ (self - 1) fibonacci + (self - 2) fibonacci
Trying it:
4 fibonacci
3
Then I used #collect: to get a series
(1 to: 20) collect: [ : term | term fibonacci ]
(1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597 2584 4181 6765
)
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 28 2:33:11 pm
From: Dan Ingalls <DanI@wdi.disney.com>
To: "David N. Smith" <dnsmith@watson.ibm.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <v03102800afb2418056cc@[129.34.225.178]>
Subject: Re: Problem with BlockContext. (SYSTEM BUGS FOUND)
> | fib va |
> fib :=3D [ va =3D=3D 1
> ifTrue: [ 1 ]
> ifFalse:[ va :=3D va - 1. fib value. va :=3D va + va ] ].
> va :=3D 5.
> fib value
>
>This isn't quie right but it causes Squeak to get a system error (on my PPC
>9500 with MacOS 7.5.5) and takes MacOS down. I quit trying! :-)
Just to let you know, this problem was reported by the folks at Interval,=
and has been fixed in our working VM and image, and thus will be in the=
next release. [The code to fix it is in my "Three fileIns" message of May=
12, but it requires building a new VM]. I ran your example here and it=
gave a well-behaved interrupt with the message "Attempt to evaluate a block=
that is already active".
Date: 97 May 28 8:41:55 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: Problem with BlockContext. (SYSTEM BUGS FOUND)
David N. Smith wrote
>Fib is better implemented as a method. This one returns one term of the =
series:
>
> fibonacci
> " Answer the self'th fibonacci number: 5 fibonacci "
> self < 3 ifTrue: [ ^ 1 ].
> ^ (self - 1) fibonacci + (self - 2) fibonacci
Dave, your explanation was so clear that I think it would be nice to =
note something interesting about this recursive implementation of =
#fibonacci.
Let me compare the recursive implementation with the following iterative =
version:
#iterativeFibonacci
| prev actual swap |
self < 2 ifTrue: [^self].
prev _ 0.
actual _ 1.
self - 1 timesRepeat: [
swap _ actual.
actual _ actual + prev.
prev _ swap].
^actual
The two methods are equivalent in the sense that both answer the same =
Fibonacci numbers. The recursive version looks simpler than the =
iterative. But, if we look at the speed of calculation, we obtain =
serious differences:
Dividing the speed (time) of evaluation of [n fibonacci] by the speed of =
evaluation of [n iterativeFibonacci], one obtains something like this
n Relative speed
10 8=20
20 470
30 40000 (forty thousand)
35 400000 (four houndred thousand)
Thus, if [30 iterativeFibonacci] takes, say, 1 millisecond to evaluate, =
then [30 fibonacci] takes about 40 seconds.
The recursive Fibonacci is so slow that it makes no sense to use it. In =
fact, for relative small integers all the time of the Universe, counted =
from the Big Bang, is not enough to perform the recursive evaluation.
Saludos,
Leandro
Date: 97 May 28 8:41:51 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: [Windows] arrow keys
Maloney wrote
> Hmm. I think someone fixed the arrow keys; check the mail archive.
> I'm not sure Home, End, Page Up and Page Down have ever worked. But
> it's probably not too hard to add them yourself... :->
My copy of the VM was old. With a newer version now I have the keys working. Thank you.
> Thanks for all the fraction code suggestions, by the way.
It was funny to do that!
Saludos,
Leandro
Date: 97 May 28 8:41:59 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: [Windows] arrow keys
Andreas Raab wrote
> If these values are not correct you should try a newer VM version
> (from the 1.19 directory).
Thank you! With the newer VM the arrow, home and end keys begun to work fine.
Saludos,
Leandro
Date: 97 May 29 5:51:04 am
From: Jean Francois Veillette <jfv@hasc.com>
To: squeak@create.ucsb.edu
In-Reply-To: <v03102800afb2418056cc@[129.34.225.178]> from "David N. Smith" at May 28, 97 04:59:05 pm
Subject: Re: Problem with BlockContext. (SYSTEM BUGS FOUND)
The code fragment suggested that I was trying to implement fibonacci, but I wasn't.
I was just currious about block recursion, and wrote a small example about it.
> I think there are four problems here:
> * Blocks are not closures in Squeak, so the variable va is 'global' to the method.
> * Squeak doesn't support recursive block invocations (I suspect).
> * You don't want to use returns. (See below).
> You don't want to use a return since a return from a block returns from the
> method and you don't want to do that. You really wanted something like this
> (which runs fine on IBM Smalltalk and answers 15, though that's not right):
thank's for all those precision information,
- jfv
Date: 97 May 29 8:37:29 am
From: Joel Lucuik <Joel@ObjectPeople.com>
To: Squeak@create.ucsb.edu
Subject: Squeak on Hand-held machine
Someone spoke a while ago about a port of squeak to, I think, the
Casseopeia (or maybe it was another hand-held machine).
Was the port successful?
What were the memory requirements?
How stripped down was the base system?
What base classes where included?
Joel
Date: 97 May 29 8:37:31 am
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: Leandro Caniglia <caniglia@mate.dm.uba.ar>
Cc: "'Squeak'" <squeak@create.ucsb.edu>
In-Reply-To: <01BC6BCD.169480B0@ts1-bsas-linea12.microstar.com.ar>
Subject: RE: Problem with BlockContext. (SYSTEM BUGS FOUND)
At 21:06 -0400 5/28/97, Leandro Caniglia wrote:
>David N. Smith wrote
>
>>Fib is better implemented as a method. This one returns one term of the
>>series:
>>
>> fibonacci
>> " Answer the self'th fibonacci number: 5 fibonacci "
>> self < 3 ifTrue: [ ^ 1 ].
>> ^ (self - 1) fibonacci + (self - 2) fibonacci
>
>Dave, your explanation was so clear that I think it would be nice to note
>something interesting about this recursive implementation of #fibonacci.
>
>Let me compare the recursive implementation with the following iterative
>version:
>
>#iterativeFibonacci
> | prev actual swap |
> self < 2 ifTrue: [^self].
> prev _ 0.
> actual _ 1.
> self - 1 timesRepeat: [
> swap _ actual.
> actual _ actual + prev.
> prev _ swap].
> ^actual
>
>The two methods are equivalent in the sense that both answer the same
>Fibonacci numbers. The recursive version looks simpler than the iterative.
>But, if we look at the speed of calculation, we obtain serious differences:
>
>Dividing the speed (time) of evaluation of [n fibonacci] by the speed of
>evaluation of [n iterativeFibonacci], one obtains something like this
>
> n Relative speed
> 10 8
> 20 470
> 30 40000 (forty thousand)
> 35 400000 (four houndred thousand)
>
>Thus, if [30 iterativeFibonacci] takes, say, 1 millisecond to evaluate,
>then [30 fibonacci] takes about 40 seconds.
>
>The recursive Fibonacci is so slow that it makes no sense to use it. In
>fact, for relative small integers all the time of the Universe, counted
>>from the Big Bang, is not enough to perform the recursive evaluation.
>
>Saludos,
>Leandro
I agree and I should have noted that.
Aa an aside, an example in my IBM Smalltalk book uses inject:into: to
compute the fibonacci series. It takes 6534 ms (PPC 9500/200) to compute
the first 5000 terms. I wrote it as an example of injecting something
besides a zero!
| nterms |
nterms := 50.
^ (3 to: nterms)
inject: (OrderedCollection with: 1 with: 1)
into: [ :inj :n |
inj addLast: ( (inj at: n - 2) + (inj at: n - 1) ); yourself ]
OrderedCollection (1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597
2584 4181 6765 10946 17711 28657 46368 75025 121393 196418 317811 514229
832040 1346269 2178309 3524578 5702887 9227465 14930352 24157817 39088169
63245986 102334155 165580141 267914296 433494437 701408733 1134903170
1836311903 2971215073 4807526976 7778742049 12586269025 )
Interestingly, yours takes 6150 ms to compute the 5000th term, making them
quite similar; actually surprisingly similar. I expected the inject:into:
to be slower, and the growing of the ordered collection to take more time.
(VW 2.5 takes 484 ms on the same machine.)
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 29 10:46:44 am
From: Dan Ingalls <DanI@wdi.disney.com>
To: Joel Lucuik <Joel@objectpeople.com>
Cc: Squeak@create.ucsb.edu
In-Reply-To: <3.0.32.19970529120548.0090e100@mail.ObjectPeople.com>
Subject: Re: Squeak on Hand-held machine
>Someone spoke a while ago about a port of squeak to, I think, the
>Casseopeia (or maybe it was another hand-held machine).
Yes, it was the Cassiopeia
>Was the port successful?
In my opinion, yes. It was done by Blair McGlashen. At the time he still=
needed permission to release it, and was going to bring it forward to 1.19.=
I think he has been too busy to do that. However, I have been running an=
early 1.19 image on his 1.18 interprter, and it works fine.
>What were the memory requirements?
I've forgotten exactly. The image is about 600k, and the interpreter about=
200k and when I ask for spaceLeft, I get 470k bytes (on a 4M Casio).
>How stripped down was the base system?
>What base classes where included?
See the quote below from my message of April 14.
- Dan
------------------------------------------------
The result is a 644k image which exhibits every normal aspect of Squeak --=
all flavors of code browsers, compiler, text editor with fancy fonts and=
lots of commands, debugger, inspectors, single-step bytecode simulation,=
MessageTally time and counts, Floats and LargeIntegers, full color support,=
WarpBlt and Turtle demos. What is more, that 644k includes my magic=
sources facility, which will gladly cough up some 820k of readable source=
code out of those same bits.
I remember saying last year that, when we got a chance, we would put out a=
Squeak that would run in one megabyte, including the VM. Voila!
- Dan
[What is NOT there, you ask? The interpreter anc C translator, music, and=
change sorters, the formEditor and character recognizer, projects and the=
ClairVaux font set, as well as all comments and class organizations. =
However, full comments and organization are retained for code that you=
subsequently fileIn or write in the system, and all changes file facilities=
are still there, including browsing of old versions]
Date: 97 May 29 12:55:41 pm
From: Travis Griggs <tgriggs@keyww.com>
To: "Squeak@create.ucsb.edu" <Squeak@create.ucsb.edu>
Subject: RE: Squeak on Hand-held machine
>Someone spoke a while ago about a port of squeak to, I think, the
>Casseopeia (or maybe it was another hand-held machine).
Yes, it was the Cassiopeia
>Was the port successful?
In my opinion, yes. It was done by Blair McGlashen. At the time he =
still needed permission to release it, and was going to bring it forward =
to 1.19. I think he has been too busy to do that. However, I have =
been running an early 1.19 image on his 1.18 interprter, and it works =
fine.
>What were the memory requirements?
I've forgotten exactly. The image is about 600k, and the interpreter =
about 200k and when I ask for spaceLeft, I get 470k bytes (on a 4M =
Casio).
>How stripped down was the base system?
>What base classes where included?
Does this mean that squeak could be ported to an E-mate 300? Hmm....
Travis Griggs
KeyTechnology
Date: 97 May 29 1:15:52 pm
From: Maloney <johnm@wdi.disney.com>
To: Leandro Caniglia <caniglia@mate.dm.uba.ar>
Cc: squeak@create.ucsb.edu
In-Reply-To: <01BC6BCD.169480B0@ts1-bsas-linea12.microstar.com.ar>
Subject: RE: Problem with BlockContext
The recursive fibonacci function is so message-send bound that it
is often used as a benchmark of message sending (or procedure calling).
Even in C, the arithmetic performed is trivial compared to the
cost of the two recursive calls.
You'd see a similar ever-widening gap between the iterative and recursive
versions in any Smalltalk implementation. (And most other languages
as well, I believe.)
So, if you need high performance, you'd use the iterative version.
However, the recursive version is nice for demonstrating the elegance
of recursion.
-- John
At 1:06 AM +0000 5/29/97, Leandro Caniglia wrote:
>Let me compare the recursive implementation with the following iterative version:
>
>#iterativeFibonacci
> | prev actual swap |
> self < 2 ifTrue: [^self].
> prev _ 0.
> actual _ 1.
> self - 1 timesRepeat: [
> swap _ actual.
> actual _ actual + prev.
> prev _ swap].
> ^actual
>
>The two methods are equivalent in the sense that both answer the same Fibonacci numbers. The recursive version looks simpler than the iterative. But, if we look at the speed of calculation, we obtain serious differences:
>
>Dividing the speed (time) of evaluation of [n fibonacci] by the speed of evaluation of [n iterativeFibonacci], one obtains something like this
>
> n Relative speed
> 10 8
> 20 470
> 30 40000 (forty thousand)
> 35 400000 (four houndred thousand)
>
>Thus, if [30 iterativeFibonacci] takes, say, 1 millisecond to evaluate, then [30 fibonacci] takes about 40 seconds.
Date: 97 May 30 2:33:40 am
From: "Andreas Raab" <raab@isg.cs.uni-magdeburg.de>
To: squeak@create.ucsb.edu
Subject: Teaching Smalltalk
Hello Smalltalkers,
I need some help to defend "the honour of Smalltalk". We're using ST
(Squeak,VW) for our students in the Computational Visualistics
program. Now, there has been rumour not to use ST anymore but instead C.
The main arguments were that ST would be "to complicated" the
students would not "get much better" and things like that.
I personally completely disagree with the above. However, I'd be
interested in collecting arguments pro ST. In particular, I'm looking
for any published studies, comparing the performance of beginners when
using procedural (i.e. C,Pascal) or object-oriented programming. What
I'm looking for are studies discussing the differences in a way like
* What did people achive after using this programming language
* What time was needed to achieve comparable results
* How well could people describe what they'd done
and things like that.
I'd be happy if you could point me to any literature.
Thanks,
Andreas
--
Linear algebra is your friend - Trigonometry is your enemy.
+===== Andreas Raab ============= (raab@isg.cs.uni-magdeburg.de) =====+
I Department of Simulation and Graphics Phone: +49 391 671 8065 I
I University of Magdeburg, Germany Fax: +49 391 671 1164 I
+=============< http://simsrv.cs.uni-magdeburg.de/~raab >=============+
Date: 97 May 30 6:05:00 am
From: Aaron Rosenzweig <recurve@xombi.wizard.net>
To: "Andreas Raab" <raab@isgnw.cs.Uni-Magdeburg.DE>
Cc: squeak@create.ucsb.edu
Subject: Re: Teaching Smalltalk
The Technical University of Nova Scotia (TUNS) I think the url is
http://www.tuns.edu/
As I understand it they did a lot of research in how people learn to program
and what sorts of things were important in programming. Ultimately "Prograph"
came out of their work.
I'd say they're worth talking to. I haven't done it yet but I plan on
contacting them myself as well.
---
SW Son of Ginger and Harry, Aaron Rosenzweig
SW http://www.wam.umd.edu/~recurve/
SW... recurve@resourceful.com
SWN?
Date: 97 May 30 6:06:52 am
From: Aaron Rosenzweig <recurve@xombi.wizard.net>
To: "Andreas Raab" <raab@isgnw.cs.Uni-Magdeburg.DE>
Cc: squeak@create.ucsb.edu
Subject: Re: Teaching Smalltalk
Sorry, it's:
http://www.tuns.ca/
For some reason I have the following url in OmniWeb's bookmarks:
http://www.tuns.ca/~gradwww/research.html
It might get more specific for what you want faster.
---
SW Son of Ginger and Harry, Aaron Rosenzweig
SW http://www.wam.umd.edu/~recurve/
SW... recurve@resourceful.com
SWN?
Date: 97 May 30 7:04:57 am
From: Tansel <tansel@rase.com>
To: Andreas Raab <raab@isgnw.cs.Uni-Magdeburg.DE>
Cc: squeak@create.ucsb.edu
Subject: Re: Teaching Smalltalk
Andreas Raab wrote:
>
> Hello Smalltalkers,
>
> I need some help to defend "the honour of Smalltalk". We're using ST
> (Squeak,VW) for our students in the Computational Visualistics
> program. Now, there has been rumour not to use ST anymore but instead C.
> The main arguments were that ST would be "to complicated" the
> students would not "get much better" and things like that.
>
> I personally completely disagree with the above. However, I'd be
> interested in collecting arguments pro ST. In particular, I'm looking
> for any published studies, comparing the performance of beginners when
> using procedural (i.e. C,Pascal) or object-oriented programming. What
> I'm looking for are studies discussing the differences in a way like
> * What did people achive after using this programming language
> * What time was needed to achieve comparable results
> * How well could people describe what they'd done
> and things like that.
>
> I'd be happy if you could point me to any literature.
> Thanks,
> Andreas
> --
Andreas,
I had posted some material on the net a few months ago about the state
of OO in general. Parts of that may be relevant.
The URL for the pages is : http://www.rase.com/oodebate/
more relevant pages may be
http://www.rase.com/oodebate/history.htm
http://www.rase.com/oodebate/choices.htm
By the way, does anyone do any work on Squeak with FPGAs?
Tansel
-----------------------------------------------------------------------
RASE Inc. New York NY USA
Voice: (212) 431 5069 mailto:tansel@rase.com
Fax: (212) 334 1846 http://www.rase.com/
----Sufficiently advanced technology is indistinguishable from magic---
-------------------------------A.C. Clarke-----------------------------
Date: 97 May 30 8:12:41 am
From: guzdial@cc.gatech.edu (Mark Guzdial)
To: "Andreas Raab" <raab@isgnw.cs.Uni-Magdeburg.DE>
Cc: squeak@create.ucsb.edu
Subject: Re: Teaching Smalltalk
>In particular, I'm looking
>for any published studies, comparing the performance of beginners when
>using procedural (i.e. C,Pascal) or object-oriented programming. What
>I'm looking for are studies discussing the differences in a way like
>* What did people achive after using this programming language
>* What time was needed to achieve comparable results
>* How well could people describe what they'd done
>and things like that.
In general, this is comparing apples-and-oranges. You can only make this
comparison if you can somehow equivalence the experience of programming
procedural and object-oriented programming language: The *ONLY* difference
is the kind of programming. But you can't do that -- if you switch
paradigms, you switch *EVERYTHING*: The way you analyze, the way you
design, the kinds of tools you use, the syntax of the language, etc.
Similarly, researchers in education have given up on making these kinds of
comparisons with respect to media: Is there a difference between teaching
with video and teaching with text? Yes, because you teach *DIFFERENT*
things with video than with text -- they're not equivalent.
If you want to make this argument (that the answer to the question is
"Mu" -- the question makes no sense), the papers to reference are:
Kozma, R. (1993). Will media influence learning? Reframing the
debate. Educational Technology Research and Development.
Kozma, R. B. (1991). Learning with media. Review of Educational
Research, 61(2), 179-211.
That said, people have tried to make the argument that O-O more naturally
meshes with the way that we think about the world. The best paper that I
know on that is:
Rosson, M. B., & Alpert, S. R. (1990). The cognitive consequences of
object-oriented design. Human-Computer Interaction, 5, 345-379.
ON THE OTHER HAND (it's good to know what ammunition the other side might
use), there are things that we know are really hard to learn in O-O and
Smalltalk:
* Students have a really tough time with class/instance distinctions.
Carroll & Rosson talk about this some in their work with Smalltalk:
Carroll, J. M., Singer, J. A., Bellamy, R. K. E., & Alpert, S. R.
(1990). A View Matcher for learning Smalltalk. In J. C. Chew & J. Whiteside
(Eds.), Proceedings of CHI'90: Human Factors in Computing Systems (Vol.
Seattle, April 1-5, pp. 431-437). New York: ACM Press.
Rosson, M. B., Carroll, J. M., & Sweeney, C. (1991, ).
Demonstrating a view matcher for reusing Smalltalk classes. Paper presented
at the CHI'91: ACM Conference on Human Factors in Computing Systems, New
Orleans.
Rosson, M. B., Carroll, J. M., & Sweeney, C. (1991). A View Matcher
for reusing Smalltalk classes. In S. P. Robertson, G. M. Olson, & J. S.
Olson (Eds.), Proceedings of CHI'91: Human Factors in Computing Systems
(Vol. New Orleans, April 27-May 2, pp. 277-283). New York: ACM Press.
* Students have a really tough time with interactions between objects.
Mitchel Resnick of MIT described this in his MultiLogo paper (appeared in
Journal of the Learning Sciences, but I don't have the ref. at hand), and
he and Michael Eisenberg (at U. Colorado-Boulder) wrote about similar
problems of students moving from a functional to an O-O perspective in one
of the Empirical Studies of Programmer's Workshops.
* Students have a tough time distributing responsibility -- that's the
reason why many C++ programs are actually one huge class. Mitchel called
this the "centralized mindset" and I found that the characteristics he
described were also common to my Smalltalk students.
Guzdial, M. (1995). Centralized mindset: A student problem with
object-oriented programming, ACM SIGCSE Technical Symposium 1995 (pp.
182-185). New York: ACM Press.
Finally, I just had a paper accepted to the OOPSLA Educators' Symposium on
the work I'm doing in my Smalltalk classes to address problems in learning
O-O. I've got a version of that paper linked to my papers page:
http://guzdial.cc.gatech.edu/papers/
Mark
--------------------------
Mark Guzdial : Georgia Tech : College of Computing : Atlanta, GA 30332-0280
(404) 894-5618 : Fax (404) 894-0673 : guzdial@cc.gatech.edu
http://www.cc.gatech.edu/gvu/people/Faculty/Mark.Guzdial.html
Date: 97 May 30 9:51:16 am
From: johnson@cs.uiuc.edu (Ralph E. Johnson)
To: "Andreas Raab" <raab@isgnw.cs.Uni-Magdeburg.DE>, squeak@create.ucsb.edu
Subject: Re: Teaching Smalltalk
The place with the most experience teaching Smalltalk as an intro
language is Carleton University. Their experience is completely
positive. They think it is much, much better than C as an intro
language. I think they teach Smalltalk first, C second.
Talk to John Pugh <70524.3613@CompuServe.COM> about it. He was
one of the ones who started Smalltalk at Carleton, and was head
of the deparment for a while, but now mostly does consulting.
He started the Object People, which is a successful company and
so takes a lot of time.
-Ralph
Date: 97 May 30 3:09:45 pm
From: "David N. Smith" <dnsmith@watson.ibm.com>
To: lnotarfr@dc.uba.ar (Luciano Esteban Notarfrancesco)
Cc: squeak@create.ucsb.edu
In-Reply-To: <m0wWHVv-000j1uC@milagro.dc.uba.ar>
Subject: Re: degreeSin
At 4:21 -0400 5/27/97, Luciano Esteban Notarfrancesco wrote:
>Integer implements
>
>degreeSin
> ^self asFloat degreesToRadians sin
>!
>
>but this fails for big integers.
>It's better to do:
>
>degreeSin
> ^(self \\ 360) asFloat degreesToRadians sin
>!
>
>Furthermore, I saw that sqrt is not reimplemented in Integer, but it
>should be ("anInteger squared sqrt" must answer "anInteger").
>
>Regards,
> --- Luciano.
The problem with large integers seems to be overflow. If the number of bits
in the integer is greater than the exponent size then the answer becomes
1.0000000000000e400 and further operations answer the same value. This
value is not a valid fp number and causes all sorts of trouble when Squeak
tries to operate on it.
I have a workaround which checks the size of the integer first before
trying to convert it. It is not perfect in that there are a few integers
that could convert which this won't convert, but they are all within a few
bits of failing.
There is room for improvement since the high order byte might have unused
bits. The algorithm below assumes all bits are used. Thus, it computes
size*8 as the number of bits (and thus the exponent size) but a better
solution is (size-1)*8 and then add the position of the left most bit in
the high order word.
This algorithm is probably good enough. There is a new variable, size, and
three new lines, starting with the first reference to size.
asFloat2
"Answer a Float that represents the value of the receiver.
Integers that are too big to convert to a IEEE double raise
an error. IEEE doubles will hold integers up to about 308
decimal digits."
| factor sum size |
sum _ 0.0.
factor _ self sign asFloat.
size := self size.
size * 8 > 1022 ifTrue: [
self error: 'Integer too large to convert to Float' ].
1 to: size do:
[:i |
sum _ (self digitAt: i) * factor + sum.
factor _ factor * 256.0].
^sum
Tests: the first one works and the second one fails.
(
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 ) asFloat2
(
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 *
12765127651287651287651287651287651287651287652187656854 ) asFloat2
Testing the limits by computing a value (alternating 1 and 0 bits) which
will just barely convert using asFloat:
| bi n |
n := 0.
bi := 1.
[n <= 1022 ] whileTrue: [
n := n + 1.
bi := (bi<<1) bitOr: (n bitAnd: 1) ].
bi asFloat
1.49807761238524e308
In hex (my printHex method): '1.AAAAAAAAAAAABe3FF'
Dave
_______________________________
David N. Smith
IBM T J Watson Research Center
Hawthorne, NY
_______________________________
Any opinions or recommendations
herein are those of the author
and not of his employer.
Date: 97 May 30 5:54:21 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: Teaching Smalltalk
Andreas Raab wrote
> I need some help to defend "the honour of Smalltalk".
Ten suggestions for the Smalltalk defender*
1. Transmit your own enthusiasm, not only your arguments.
2. Do not communicate only abstract concepts. In Smalltalk it is easy to =
find surprising examples related to the interest of your audience. =
Improvise a simple model and demonstrate how it works.
3. Do no fix your arguments in the facilities of learning Smalltalk, but =
in the possibilities of a Smalltalker.
4. Have at hand some successful experiences on actual projects known to =
you.
5. Take the point of view of someone that wants to diffuse, not to =
convince.
6. Do not forget that the conceptual simplicity of Smalltalk does not =
make it easy. All the Euclidean Geometry is built up from only 5 simple =
axioms, it is clear an beautiful but it is not easy.
7. Give examples on how Smalltalk has influenced other programming =
languages.
8. Cite names, places and dates. Smalltalk has a rich history.
9. Tell about bibliography, user groups, Internet lists and other =
activities that you know. Invite your audience to participate.
10. Open your clothes and show the Smalltalk logo stamped in your =
T-shirt :-)
Saldudos,
Leandro
-----------
*translations to good English are welcome
Date: 97 May 31 9:55:13 am
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: On the #gcd: method
Hi!
I have some remarks on the #gcd: method in the Integer class:
1. [anInteger gcd: 0] and [0 gcd: anInteger] give a division by 0 error =
message when they should answer [anInteger abs]. (This may be considered =
a bug).
2. The method begins with this code:
m _ self abs max: anInteger abs.
n _ self abs min: anInteger abs.
m \\ n =3D 0 ifTrue: [^n].
"easy test, speeds up rest"
but it is better not to forget the remainder m \\ n once it has been =
computed. Instead, one can write:
n _ self abs max: anInteger abs.
m _ self abs min: anInteger abs.
(n _ m \\ m) =3D 0 ifTrue: [^m].
"easy test, speeds up rest"
saving the remainder and replacing with it the maximum of the two =
original values. (Note the swap between n and m). This is not suggested =
by me but by Knuth in the same pages of Vol 2 where the binary algorithm =
used en Squeak is explained.
3. The proofs I've made in Squeak show that this remainder-saving =
version is a 15% faster than the "forgeting" one.
4. Taking into account the "bug" and the saving one should modify the =
begining of the #gcd: method with:
n _ self abs max: anInteger abs.
m _ self abs min: anInteger abs.
m =3D 0 ifTrue: [^n].
(n _ m \\ m) =3D 0 ifTrue: [^m].
"easy test, speeds up rest"
{the original code follows}
Saludos,
Leandro
Date: 97 May 31 1:11:40 pm
From: Jecel Assumpcao Jr <jecel@lsi.usp.br>
To: squeak@create.ucsb.edu
Subject: Re: Teaching Smalltalk
Ralph E. Johnson wrote:
>
> The place with the most experience teaching Smalltalk as an intro
> language is Carleton University. Their experience is completely
> positive. They think it is much, much better than C as an intro
> language. I think they teach Smalltalk first, C second.
>
> Talk to John Pugh <70524.3613@CompuServe.COM> about it. He was
> one of the ones who started Smalltalk at Carleton, and was head
> of the deparment for a while, but now mostly does consulting.
> He started the Object People, which is a successful company and
> so takes a lot of time.
There was an article about this in the Nov/Dec 1990 Journal of
Object Oriented Programming (JOOP) ( Vol 3 No 4 ). I can't
find it right now as things around here are a bit messy, but
I will summarize what they said:
The introduction to programming course became more
enjoyable due to the ability to use various data structure
objects (collections, mainly) as black boxes - this
allowed less trivial programming exercises to be attempted.
These black boxed would be opened in the second year in
the Data Structure course.
One side effect from the move from Pascal to Smalltalk
was that the students with previous experience in programming
paid more attention because the language was as new to
them as to their "novice" classmates.
One problem they had with Smalltalk was its integrated
nature - even a trivial example might lead (by accident)
into an exploration of low level stuff way before the
students are ready for it. The instructors found it
nearly impossible to break the material down into isolated
chunks (special browsers and debuggers can help with
this).
They used C in the middle of the course as an introduction
to computer architecture. Explaining pointers and stuff
was a neat way to approach the hardware level.
If you (Andreas) can find the article, I really recomend
it (though it would be interesting to look at what has
happened since then).
As for using C to teach, I like to compare it to using
a jet fighter to teach how to fly. It is a great way
to lose most of your students. C is a great language for
what it was designed to do. But having a student figure
out that he left out a "*" from that fact that the
screen fills up with little purple dots right before
locking up is not my idea of a good educational method.
-- Jecel
Date: 97 May 31 3:22:56 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: Teaching Smalltalk
Bert wrote
B> LC> Ten suggestions for the Smalltalk defender*
B> =20
B> LC> [... nine "serious" points ...]
B> LC> 10. Open your clothes and show the Smalltalk logo stamped in your =
T-shirt :-)
B> I like the 10th most :-)
B> By logo I assume you mean the balloon from BYTE cover? But I couldn't =
get
B> access to it _without_ the BYTE heading. Do you know any source? All =
other
B> renditions I have seen are, uhmm, rather ugly, I'd say ...
Of course, I did meant the BYTE balloon. I don't know any source without =
the heading. I have read somewhere in the Net form Ralph Johnson that =
"Someone should talk with Robert Tinney about making his cover into a =
poster". Probably that poster exists (in such case please don't forget =
that I WANT MINE!). At any case, I consider the heading as part of a =
testimonial form of art.
Saludos,
Leandro
Date: 97 May 31 3:23:01 pm
From: Leandro Caniglia <caniglia@mate.dm.uba.ar>
To: 'Squeak' <squeak@create.ucsb.edu>
Subject: RE: On the #gcd: method
Ralph E. Jhonson wrote
RJ> LC> n _ self abs max: anInteger abs.
RJ> LC> m _ self abs min: anInteger abs.
RJ> LC> m = 0 ifTrue: [^n].
RJ> LC> (n _ m \\ m) = 0 ifTrue: [^m].
RJ> LC> "easy test, speeds up rest"
RJ> LC> {the original code follows}
RJ> m \\ m is always 1. Shouldn't that be "n _ n \\ m"?
Ralph, you are right. It should be n_ n \\ m. Tanks for your remark!
BTW let me note that m \\ m is never 1, it is always 0 ;-)
Sorry. I repeat the correct form here
gcd: anInteger
| n m d |
n _ self abs max: anInteger abs.
m _ self abs min: anInteger abs.
m = 0 ifTrue: [^n].
(n _ n \\ m) = 0 ifTrue: [^m].
"easy test, speeds up rest"
{the original code follows}
Saludos,
Leandro
Date: 97 May 31 6:51:25 pm
From: Sam Adams <ssadams@us.ibm.com>
To: <squeak@create.ucsb.edu>
Subject: RE: Smalltalk Ballon.....was Teaching Smalltalk
Bert wrote
B> LC> Ten suggestions for the Smalltalk defender*
B>
B> LC> [... nine "serious" points ...]
B> LC> 10. Open your clothes and show the Smalltalk logo stamped in your T-shirt
:-)
B> I like the 10th most :-)
B> By logo I assume you mean the balloon from BYTE cover? But I couldn't get
B> access to it _without_ the BYTE heading. Do you know any source? All other
B> renditions I have seen are, uhmm, rather ugly, I'd say ...
Leandro wrote:
>Of course, I did meant the BYTE balloon. I don't know any source without the
>heading. I have read somewhere in the Net form Ralph Johnson that "Someone
>should talk with Robert Tinney about making his cover into a poster". Probably
>that poster exists (in such case please don't forget that I WANT MINE!). At any
>case, I consider the heading as part of a testimonial form of art.
I have an old catalog from Georg Heeg that has a clean image of the Smalltalk
balloon on the over. It looks like the original artwork sans BYTE heading.
Perhaps they have a source for the art. Anyone over there listening?
On the teaching issue, I always found that a little magic was worth a mountain
of logic when it came to convincing folks about the value of Smalltalk.
Regards,
Sam
stp@create.ucsb.edu]
Created: 1996.11.08; LastEditDate: 1996.11.11