■
test | a b | a := 16rFFFFFFFF. b := 4294967295. ^ a == b.
とかいうやつを作ってみる。
バイトコードを見てみると
9 <20> pushConstant: 4294967295 10 <68> popIntoTemp: 0 11 <20> pushConstant: 4294967295 12 <69> popIntoTemp: 1 13 <10> pushTemp: 0 14 <11> pushTemp: 1 15send: == 16 <7C> returnTop
となっている。
9バイト目も11バイト目も同じバイトコードなので、明らかに4294967295は同じ4294967295ということが分かる。
一応念のために調べてみると、バイトコード 16r20 は pushLiteralConstantBytecode だそうです。
これまた念のために確認しておくと、
Interpreter>>pushLiteralConstantBytecode self fetchNextBytecode. "this bytecode will be expanded so that refs to currentBytecode below will be constant" self pushLiteralConstant: (currentBytecode bitAnd: 16r1F).
らしいので、要するに、16r20は「リテラルフレームの0番目をスタックにプッシュせよ」ということになる。
勿論、リテラルフレームは #(4294967295)です。
というような見方も出来るようになりました、と何となく報告。
で、それはそうと、ではこのリテラルフレームがどう作られるのか?
という元々の疑問を、id:sumimさんの助言を参考にして追ってる。
リテラルなトークンを実際にオブジェクトに変換すという作業はScannerのレベルでそうなっている。
で、Parserはコードをパースする過程でリテラルに出くわすたびに、それをLiteralDictionaryに詰め込んでいる。
LiteralDictionaryはDictionaryの一種なので、ここで同値なオブジェクトが同一なオブジェクトになる。
なるほど。