Smalltalk: How primitives are implemented?

為{幸葍}努か 提交于 2020-08-05 06:47:29

问题


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?

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)]
    ]

Here is the link of above code: https://github.com/gnu-smalltalk/smalltalk/blob/62dab58e5231909c7286f1e61e26c9f503b2b3df/kernel/SmallInt.st


回答1:


Conceptually speaking primitive methods are pieces of behavior (routines) implemented by the Virtual Machine (VM), not by regular Smalltalk code.

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.

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.

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.

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.

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 LargeIntegers and the addition would take place in the #+ method of the appropriate class (LargePositiveInteger or LargeNegativeInteger).

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.



来源:https://stackoverflow.com/questions/39321776/smalltalk-how-primitives-are-implemented

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!