vieweditattachhistoryswikistopchangessearchhelp

Smalltalk で i++ を実現する

Smalltalk/Squeak の変数はオブジェクトではないのでメッセージを受け取ることができません(当然、それへのメッセージ送信は、その変数が束縛しているオブジェクトへのメッセージ送信と解釈される)。そんなわけで、C 言語などでおなじみの i++ 、つまり変数 i に束縛されているオブジェクトを、インクリメントしたオブジェクトに置き換えるような機能は Smalltalk にはありません。ただ、コンテキストから情報をたぐり寄せることで、似たようなことは実現可能なように思えたので(残念ながら、++ というセレクタは使えないので、#inc として)実装を実験的に試みてみました。
Object >> inc
	| context method type byte offset receiver value newValue |
	context _ (thisContext stackOfSize: 2) last.
	method _ context method.
	byte _ method at: context pc - 2.
	type _ byte // 16.
	offset _ byte \\ 16.
	receiver _ context receiver.
	newValue _ nil.
	(#(0 1 4) includes: type) ifFalse: [self error: 'receiver should be a variable'].
	type = 0 ifTrue: [
		value _ receiver instVarAt: offset + 1.
		receiver instVarAt: offset + 1 put: (newValue _ value + 1)].
	type = 1 ifTrue: [
		value _ context tempAt: offset + 1.
		context tempAt: offset + 1 put: (newValue _ value + 1)].
	type = 4 ifTrue: [
		value _ method literalAt: (offset + 1).
		value value: (newValue _ value value + 1)].
	^ newValue
これを定義してたとえば次のように、テンポラリ変数に束縛された 1 に inc を送信すると、
| temp |
temp := 1.
temp inc.
^ temp
=> 2
のように、当該テンポラリ変数には改めて 2 が束縛された状態、つまり temp++、あるいは temp := temp + 1 をしたのと同じ状態になります。テンポラリ変数の他に、グローバル変数、ワークスペース変数、インスタンス変数での動作が確認できました。--sumim

このページを編集 (1685 bytes)


Congratulations! 以下の 1 ページから参照されています。

This page has been visited 2627 times.