问题描述
我知道一切都是对象,您可以在 Smalltalk 中向对象发送消息以执行几乎所有操作.现在我们如何实现一个对象(内存表示和基本操作)来表示原始数据类型?例如整数的 +
是如何实现的?
I know that everything is an object and you send messages to objects in Smalltalk to do almost everything.Now how can we implement an object (memory representation and basic operations) to represent a primitive data type? For example how +
for integers is implemented?
我查看了 Smalltalk 的源代码,并在 Smallint.st
中找到了它.有人能解释一下这段代码吗?
I looked at the source code for Smalltalk and found this in Smallint.st
. Can someone explain this piece of code?
+ arg [
"Sum the receiver and arg and answer another Number"
<category: 'built ins'>
<primitive: VMpr_SmallInteger_plus>
^self generality == arg generality
ifFalse: [self retrySumCoercing: arg]
ifTrue: [(LargeInteger fromInteger: self) + (LargeInteger fromInteger: arg)]
]
推荐答案
从概念上讲,原始方法是由虚拟机 (VM) 而非常规 Smalltalk 代码实现的行为(例程).
Conceptually speaking primitive methods are pieces of behavior (routines) implemented by the Virtual Machine (VM), not by regular Smalltalk code.
当 Smalltalk 编译器找到语句 <primitive: ...>
时,它会将其解释为一种特殊类型的方法,其参数(在您的情况下为 VMpr_SmallInteger_plus
)表示VM内目标例程的整数索引.
When the Smalltalk compiler finds the statement <primitive: ...>
it interprets this as an special type of method whose argument (in your case VMpr_SmallInteger_plus
) indicates the integer index of the target routine within the VM.
在这个意义上,原语是一个全局例程,不绑定到任何特定类的MethodDictionary
.原始逻辑旨在用于某些类的接收器和参数,这就是为什么它必须检查接收器和参数(如果有)是否符合其要求.如果不是,则原语失败,在这种情况下,控制流向 <primitive: ...>
语句后面的 Smalltalk 代码.否则,原语成功并且下面的 Smalltalk 代码不会被执行.另请注意,除了 语句上方出现的临时声明之外,编译器将不允许任何 Smalltalk 代码.
In this sense a primitive is a global routine not bound to the MethodDictionary
of any particular class. The primitive logic is intended for a receiver and arguments of certain classes and that's why it must check that the receiver and the arguments (if any) conform its requirements. If not, the primitive fails and in that case the control flows to the Smalltalk code that follows the <primitive: ...>
statement. Otherwise the primitive succeeds and the Smalltalk code below is not executed. Note also that the compiler will not allow for any Smalltalk code other than temporary declaration occurring above the <primitive:...>
sentence.
在您的示例中,如果参数 arg
不是预期的类(大概是 SmallInteger
),则例程放弃尝试将其求和给接收器并委托将操作解析为 Smalltalk 代码.
In your example, if the argument arg
is not of the expected class (presumably a SmallInteger
) the routine gives up trying to sum it to the receiver and delegates the resolution of the operation to the Smalltalk code.
如果参数恰好是 SmallInteger
,原语将计算结果(使用 VM 中的例程)并用它回答.
If the argument happens to be a SmallInteger
, the primitive will compute the result (using the routine held in the VM) and answer with it.
我还没有看到这个原语的代码,但如果总和的结果不适合 SmallInteger
,也可能发生原语失败,在这种情况下,接收者和参数将被转换为 LargeInteger
s 并且添加将在适当类的 #+
方法中进行(LargePositiveInteger
或 LargeNegativeInteger
).
I haven't seen the code of this primitive but it could also happen that the primitive fails if the result of the sum does not fit in a SmallInteger
, in which case both the receiver and the argument would be cast to LargeInteger
s and the addition would take place in the #+
method of the appropriate class (LargePositiveInteger
or LargeNegativeInteger
).
Smalltalk 代码的另一个分支允许在 SmallInteger
和任何其他类型的对象之间实现多态和.例如,如果您对 3 + 4.0
求值,这部分 Smalltalk 代码就会发生,因为在这种情况下,参数是 Float
.如果您评估 3 + (4/3)
等,则会发生类似的情况.
The other branch of the Smalltalk code allows for the implementation of a polymorphic sum between a SmallInteger
and any other type of object. For instance this part of the Smalltalk code would take place if you evaluate 3 + 4.0
because in this case the argument is a Float
. Something similar happens if you evaluate 3 + (4 / 3)
, etc.
这篇关于Smalltalk:原语是如何实现的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!