我知道一切都是对象,您可以向 Smalltalk 中的对象发送消息来执行几乎所有操作。
现在我们如何实现一个对象(内存表示和基本操作)来表示原始数据类型?例如如何+
对于整数的实现?
我查看了 Smalltalk 的源代码并发现了这个Smallint.st
。有人可以解释一下这段代码吗?
+ 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)]
]
这是上面代码的链接:https://github.com/gnu-smalltalk/smalltalk/blob/62dab58e5231909c7286f1e61e26c9f503b2b3df/kernel/SmallInt.st https://github.com/gnu-smalltalk/smalltalk/blob/62dab58e5231909c7286f1e61e26c9f503b2b3df/kernel/SmallInt.st
从概念上来说原始方法是由虚拟机 (VM) 而不是常规 Smalltalk 代码实现的行为(例程)片段。
当Smalltalk编译器发现该语句时<primitive: ...>
它将其解释为一种特殊类型的方法,其参数(在您的情况下)VMpr_SmallInteger_plus
) 表示VM内目标例程的整数索引。
从这个意义上说,原语是一个全局例程,不受约束MethodDictionary
任何特定类别的。原始逻辑适用于某些类的接收者和参数,这就是为什么它必须检查接收者和参数(如果有)是否符合其要求。如果不是,则原始fails在这种情况下,控制流向以下的 Smalltalk 代码<primitive: ...>
陈述。否则是原始的succeeds并且下面的 Smalltalk 代码不会被执行。另请注意,编译器不允许除临时声明之外的任何 Smalltalk 代码出现在<primitive:...>
句子。
在你的例子中,如果参数arg
不属于预期的类别(大概是SmallInteger
)例程放弃尝试将其求和到接收器,并将操作的解析委托给 Smalltalk 代码。
如果参数碰巧是SmallInteger
,原语将计算结果(使用虚拟机中保存的例程)并用它来回答。
我还没有看到这个原语的代码,但如果总和的结果不适合原语,也可能会发生原语失败的情况。SmallInteger
,在这种情况下,接收者和参数都将被转换为LargeInteger
s 并且添加将发生在#+
适当类的方法(LargePositiveInteger
or LargeNegativeInteger
).
Smalltalk 代码的另一个分支允许在SmallInteger
以及任何其他类型的对象。例如,如果您评估,Smalltalk 代码的这一部分将会发生3 + 4.0
因为在这种情况下,参数是Float
。如果您评估,也会发生类似的情况3 + (4 / 3)
, etc.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)