I'm guessing the reason is more involved than "because nobody asked", but such a capability would be nice for my dinky little LazyObject class. I suppose a reasonable workaround would be to force my SmallInteger into a Large(Positive|Negative)Integer, or make a wrapper for the SmallInteger.
"All I need to know about Smalltalk I learned from Sesame Street" magicianMumford become: PeanutButterSandwich new.
Because a SmallInteger is a manifest constant and the oop _is_ the value. #become: swaps the values refered to by the oop - if the oop is the value, it can't be swapped.
You could concievably get the results you want by making a large integer (which is not a manifest constant) but remember that largeintegers work quite hard to become SmallIntegers any time you send them any sort of arithmetic message. You'd probably want to implement a WordInteger class to get around this, or you could try living with an ugly hack like simply using a size 4 ByteArray.
tim
On Sunday 31 March 2002 10:27 am, Tim Rowledge wrote:
You'd probably want to implement a WordInteger class to get around this, or you could try living with an ugly hack like simply using a size 4 ByteArray.
Who said that Java wasn't inspirational?
[ note to those fortunate enough to have not used Java: there is a class Integer that exists solely to wrap integer ("int") values, which aren't objects. This wrapping is needed (for instance) if you want to have integers in collections, since collections store only Objects. ]
On Sun, 31 Mar 2002, Tim Rowledge wrote:
Because a SmallInteger is a manifest constant and the oop _is_ the value. #become: swaps the values refered to by the oop - if the oop is the value, it can't be swapped.
Yes, but he's talking about #becomeForward:, not #become:
So, there is a good question why it doesn't/can't work.
Scott
Yes, but he's talking about #becomeForward:, not #become:
So, there is a good question why it doesn't/can't work.
Same issue in both cases. SmallIntegers are not referenced - they are always used 'by value'. Thus, whenever you 'use' or 'reference' a SmallInteger you are actually creating a copy of that SmallInteger (just in the most efficient way possible). Which effectively means that #becomeForward: could (at best) be a no-op, since what you're really getting is something like 1 copy becomeForward: 2 copy. However, since we give users the illusion that there is only a single SmallInteger '1' in system (by implementing identity comparison appropriately; e.g., '3+1 == 5-1' => true) the meaning of #become:/#becomeForward: would have to be to change _all_ instances of the SmallInteger in question. And that's something you _definitely_ do not want (believe me).
Cheers, - Andreas
On Sun, 31 Mar 2002, Andreas Raab wrote:
Yes, but he's talking about #becomeForward:, not #become:
So, there is a good question why it doesn't/can't work.
Same issue in both cases. SmallIntegers are not referenced - they are always used 'by value'. Thus, whenever you 'use' or 'reference' a SmallInteger you are actually creating a copy of that SmallInteger (just in the most efficient way possible). Which effectively means that #becomeForward: could (at best) be a no-op, since what you're really getting is something like 1 copy becomeForward: 2 copy.
Read the subject of this thread - the original question, which everyone has been ignoring, is, why can't I do
'foo' becomeForward: 3.
The original poster clearly understood why you can't becomeForward: a small integer into something else, but nobody's given a good reason yet why you can't becomeForward: something else into a small integer.
Avi Bryant wrote:
Read the subject of this thread - the original question, which everyone has been ignoring, is, why can't I do
'foo' becomeForward: 3.
The pragmatic answer is that as you go through the code involved in becomeForward you get to ObjectMemory>containsOnlyOops:and: which carefully makes the prim fail if any items in the two arrays are SmallIntegers - since you can't become SmallIntegers :-) I'd hazard a guess that the implementor made use of existing code and simply never considered that SmallIntegers could in fact be reasonable arguments for becomeForward. Without spending a lot more time looking at the prim code than I have to spare (I have varnish drying and needing some work) I can't say for certain how much change would be needed, but I'm guessing it might be complicated since it is not likely to be very clsoe to the current code.
If you really need it, send me an RFQ and I'll get back to you :-)
tim
Tim Rowledge wrote:
Avi Bryant wrote:
Read the subject of this thread - the original question, which everyone has been ignoring, is, why can't I do
'foo' becomeForward: 3.
The pragmatic answer is that as you go through the code involved in becomeForward you get to ObjectMemory>containsOnlyOops:and: which carefully makes the prim fail if any items in the two arrays are SmallIntegers - since you can't become SmallIntegers :-)
Thanks! I just might have found that myself, if primitive: weren't such a dead end. ([REQ] some comments in primitive calls to show where to trace from here). So, step 1, I refactor out the and: part of containsOnlyOops.
I'd hazard a guess that the implementor made use of existing code and simply never considered that SmallIntegers could in fact be reasonable arguments for becomeForward.
My understanding of become(Foward): was that there would be an (ever so dainty) full GC-ish walk through memory, doing s/oldref/newref/ on each object's (variable=reference=pointer=literal SmallInteger) list. Under this assumption, the only thing really preventing 3 become: 4 would be your own sense of sanity. Such a capability would actually be quite useful to various government agencies, such as the Ministry of Truth. However, with such scary methods as prepareForwardingTableForBecoming:with:twoWay:, and their talk about fowarding blocks, I fear that that web page about squeak 2.x just may be out of date. This would be a good time for me to actually read NuBlue.
Without spending a lot more time looking at the prim code than I have to spare (I have varnish drying and needing some work) I can't say for certain how much change would be needed, but I'm guessing it might be complicated since it is not likely to be very clsoe to the current code.
At this point, I'm starting to suspect that the fix for ObjectMemory would have exactly the same effect as making a SmallInteger wrapper (that normalize-s like Large(+-)Integers). It probably depends on what a "fowarding block" is (a symlink object?).
If you really need it, send me an RFQ and I'll get back to you :-)
tim
It's not that important, this is just a toy project I'm working on.
Buy one, get one free sig -
"By opening this term paper, you consent to the following.." - The private hell of law school teachers
One thing I never liked about lisp, was having to take off my shoes to count parenthesis.
On Mon, 1 Apr 2002, Brian Keefer wrote: [snip]
Thanks! I just might have found that myself, if primitive: weren't such a dead end. ([REQ] some comments in primitive calls to show where to trace from here). So, step 1, I refactor out the and: part of containsOnlyOops.
[snip]
<CSTOD> Browser fullOnClass: Interpreter selector: (Interpreter primitiveTable at: 2).
"Or whatever the primative number is - 1." </CSTOD>
This will open a browser on the numbered primative's source code. (Well, not for plugins...exercise for the reader.)
Modifying the pretty printer to make this a hyperlink for where it sees <primitive: 3> is also left as an exercise for the reader :)
Hmm. Browsing with colorPrint already does a bit of this:
SmallInteger>>*
With source: ... <primitive: 9> ^ super * aNumber
With colorPrettyPrinting (ok, any pretty printing):
<primitive: 9> "primitiveMultiply" ^ super * aNumber
So, perhaps messing with MethodNode>>printPrimitiveOn: will help.
(It's not *so* terrible, but it will require a changeset, not a CSTOD.)
Cheers, Bijan Parsia.
Bijan Parsia wrote:
<CSTOD> Browser fullOnClass: Interpreter selector: (Interpreter primitiveTable at: 2).
"Or whatever the primative number is - 1."
</CSTOD>
This will open a browser on the numbered primative's source code. (Well, not for plugins...exercise for the reader.)
That would be kind of nice. I wonder if we could persuade the 'implementors of' code to add the appropriate method to the menu? <primitive: number> would dig out the stuff from above, <primitive: string [module: string2> would extract just the string as a symbol...it's already there in the literal frame. Hmm.
tim
Tim Rowledge wrote:
That would be kind of nice. I wonder if we could persuade the 'implementors of' code to add the appropriate method to the menu?
Well the basic part is simple enough; some extra is needed to compensate for the name munging used in TestInterpreterPlugin and its subclasses. See attached.
tim
'From Squeak3.2gamma of 24 January 2002 [latest update: #4743] on 1 April 2002 at 9:25:13 pm'! "Change Set: namedprimfinder Date: 1 April 2002 Author: tim@sumeru.stanford.edu
Extremely quick hack to add the name of a primitive called by a method to the list used by implementors and senders.
It doesn't attempt to deal with FFI calls, nor does it work well with primitives defined in subclasses of TestInterpreterPlugin - their names are munged in such a way as to confuse things. I expect somebody can work out a way around this. Still, it does work for 'ordinary' prims, which is a start"!
!CompiledMethod methodsFor: 'scanning' stamp: 'tpr 4/1/2002 21:16'! messages "Answer a Set of all the message selectors sent by this method." | scanner aSet prim | aSet _ Set new. scanner _ InstructionStream on: self. scanner scanFor: [:x | scanner addSelectorTo: aSet. false "keep scanning"]. prim _ self primitive. (prim > 0 and: [(prim between: 255 and: 519) not]) ifTrue: [prim = 117 ifTrue: [aSet add: (self literalAt: 1) second] ifFalse: [aSet add: (Interpreter primitiveTable at: prim + 1)]]. ^ aSet! !
Brian Keefer wrote:
My understanding of become(Foward): was that there would be an (ever so dainty) full GC-ish walk through memory, doing s/oldref/newref/ on each object's (variable=reference=pointer=literal SmallInteger) list. Under this assumption, the only thing really preventing 3 become: 4 would be your own sense of sanity.
Ah, tricky.
The oop of SmallInteger 3 is fixed absolutely (in fact, it's 5 :-).
The semantics of #become always used to be to swap the _value_ of the oops involved. With an ObjectTable this is usually trivial, and you do little more than swapping the data pointers of the two involved objects. When you do a no-OT implementation you get to twist things a little and it changes to be an exchange of oops rather like you assumed. The partiicular implementation then becomes the arbiter of what you can do and in the current squeak vm the use of forwarding blocks & a mild perversion of the gc prevents SmallIntegers from being swappable. A more naive implementation that really did just scan memory & swap oops would be able to swap SmallInts. I think my brain is going to explode now.....
Perhaps you could use a float as your value for the WordInteger class, then coerce it when needed.
Cheers,
Alan
-----
At 10:27 AM -0800 3/31/02, Tim Rowledge wrote:
Because a SmallInteger is a manifest constant and the oop _is_ the value. #become: swaps the values refered to by the oop - if the oop is the value, it can't be swapped.
You could concievably get the results you want by making a large integer (which is not a manifest constant) but remember that largeintegers work quite hard to become SmallIntegers any time you send them any sort of arithmetic message. You'd probably want to implement a WordInteger class to get around this, or you could try living with an ugly hack like simply using a size 4 ByteArray.
tim
--
Brian Keefer mgomes21@cox.net wrote...
I'm guessing the reason is more involved than "because nobody asked", but such a capability would be nice for my dinky little LazyObject class. I suppose a reasonable workaround would be to force my SmallInteger into a Large(Positive|Negative)Integer, or make a wrapper for the SmallInteger.
My take on this is that there is no practical reason that this would not work the way I hear it being asked, namely that every reference to aNonSmallInteger would be replaced by a reference to aSmallInteger.
I think it's a reasonable request, but I can imagine uses of it that would be in questionable taste.
The concern that I hear in the other replies is that it doesn't quite feel like a become, since those references are now to an immutable object, and can't therefore experience any further change.
But it IS a forward change of identity, and it would NOT break anything. It's not that different from mapping to nil, true, or false, concerning which I'd give the same answer.
So my answer to the original question is that, in fact, there is not much more involved than "because nobody asked".
- Dan
squeak-dev@lists.squeakfoundation.org