[squeak-dev] self error: 'comment only' (was: The Trunk: Kernel-eem.1316.mcz)

David T. Lewis lewis at mail.msen.com
Tue Mar 17 02:57:56 UTC 2020


On Mon, Mar 16, 2020 at 07:04:29PM +0000, Thiede, Christoph wrote:
> I really appreciate elaborate documentation comments like this. However,
> is it really necessary and seasonable to store them in methods whose only
> purpose is to hold a comment? IMHO, this is a quite abusive way to declare
> methods. Why can't we put this into class comments?
> 

Necessary? No, there are lots of other places in which the documentation
could be stored. But it is nice to have it easily available when reading
class Object and trying to figure out how an "object" actually works.

Reasonable? Yes. Primitive calls apply to all objects, and it it not
intuitively obvious how they work. Documenting them on the class side
of Object is a reasonable thing to do.

Why can't we put this into class comments? It would not be reasonable to
put information like this in the class comment for Object. That would turn
the class comment into a mess, and it is important for class comments to
be clear and focused.

There are lots ways to provide documentation for a system, and most of
them either don't work or don't get maintained. But it is nice when the
documentation for a live, changing, system remain useful and relevant
for years and even decades. If you look at the method history for these
methods, you will see that it dates back to the earliest days of Squeak,
before the introduction of method time stamps with author initials.

These documentation methods are good and useful, and they explain a
not-so-obvious aspect of how objects behave. Read them and be happy :-)

Dave

> 
> Best,
> 
> Christoph
> 
> ________________________________
> Von: Squeak-dev <squeak-dev-bounces at lists.squeakfoundation.org> im Auftrag von commits at source.squeak.org <commits at source.squeak.org>
> Gesendet: Mittwoch, 11. M?rz 2020 21:03 Uhr
> An: squeak-dev at lists.squeakfoundation.org; packages at lists.squeakfoundation.org
> Betreff: [squeak-dev] The Trunk: Kernel-eem.1316.mcz
> 
> Eliot Miranda uploaded a new version of Kernel to project The Trunk:
> http://source.squeak.org/trunk/Kernel-eem.1316.mcz
> 
> ==================== Summary ====================
> 
> Name: Kernel-eem.1316
> Author: eem
> Time: 11 March 2020, 1:02:37.986482 pm
> UUID: daa453eb-09f1-446b-bc64-6f6c0298daf2
> Ancestors: Kernel-nice.1315
> 
> Improve Object class-side documentation for primtiives.
> 
> =============== Diff against Kernel-nice.1315 ===============
> 
> Item was changed:
>   ----- Method: Object class>>howToModifyPrimitives (in category 'documentation') -----
>   howToModifyPrimitives
>          "You are allowed to write methods which specify primitives, but please use
>          caution.  If you make a subclass of a class which contains a primitive method,
>          the subclass inherits the primitive.  The message which is implemented
>          primitively may be overridden in the subclass (E.g., see at:put: in String's
>          subclass Symbol).  The primitive behavior can be invoked using super (see
>          Symbol string:).
> 
>          A class which attempts to mimic the behavior of another class without being
>          its subclass may or may not be able to use the primitives of the original class.
>          In general, if the instance variables read or written by a primitive have the
>          same meanings and are in the same fields in both classes, the primitive will
>          work.
> 
>          For certain frequently used 'special selectors', the compiler emits a
>          send-special-selector bytecode instead of a send-message bytecode. Special
>          selectors were created because they offer two advantages.  First, code which
>          sends special selectors compiles into fewer bytes than normal. Second, for
>          some pairs of receiver classes and special selectors, the interpreter jumps
>          directly to a primitive routine without looking up the method in the class,
>          and the just-in-time (JIT) compiler (if in use) may emit code to directly execute
> +        the primitive.  At least in the interpreter this is much faster than a normal
> -        the primitive.  At least in the interpeeter this is much faster than a normal
>          message lookup. In both the interpreter and the JIT send-special-selector,
> +        conditional branch pairs are short-circuited for the comparison selectors when
> +        applied to SmallIntegers or Floats.
> -        conditional branch pairs are short-circuited for the comparison selectors.
> 
> +        A selector which is a special selector solely in order to save space has
> -        A selector which is a special selector solely in order to save space has a
>          normal behavior.  Methods whose selectors are special in order to
> +        gain speed contain the comment, 'No Lookup'.  When the virtual machine
> -        gain speed contain the comment, 'No Lookup'.  When the interpreter
>          encounters a send-special-selector bytecode, it checks the class of the
>          receiver and the selector.  If the class-selector pair is a no-lookup pair,
>          then the interpreter swiftly jumps to the routine which implements the
>          corresponding primitive.  (A special selector whose receiver is not of the
>          right class to make a no-lookup pair, is looked up normally).  The pairs are
>          listed below.  No-lookup methods contain a primitive number specification,
>          <primitive: xx>, which is redundant.  Since the method is not normally looked
>          up, deleting the primitive number specification cannot prevent this
>          primitive from running.  If a no-lookup primitive fails, the method is looked
>          up normally, and the expressions in it are executed.
> 
>          No Lookup pairs of (class, selector)
> 
>          SmallInteger and Float with any of      + - * /
>          SmallInteger with any of                        \\  bitOr: bitShift: bitAnd:  // @
>          SmallInteger and Float with any of      =  ~=  >  <  >=  <=
>          Any class with                                          == ~~ class
>          Point with either of                                    x y                             (interpreter only)
>          BlockClosure with either of                      value value:    (interpreter only)
>          "
> 
>          self error: 'comment only'!
> 
> Item was changed:
>   ----- Method: Object class>>whatIsAPrimitive (in category 'documentation') -----
>   whatIsAPrimitive
>          "Some messages in the system are responded to primitively. A primitive
> +         response is performed directly by the virtual machine rather than by
> +         evaluating expressions in a method. The methods for these messages
> +         indicate the presence of a primitive response by including one of
> +                <primitive: N>
> +                <primitive: N error: errorCode>
> +                <primitive: 'primitiveName' module: 'module name'>
> +                <primitive: 'primitiveName' module: 'module name' error: errorCode>
> +         before the first expression in the method.
> -        response is performed directly by the interpreter rather than by evaluating
> -        expressions in a method. The methods for these messages indicate the
> -        presence of a primitive response by including <primitive: xx> before the
> -        first expression in the method.
> 
> +        Primitives exist for several reasons. Certain basic or 'primitive' operations
> +        cannot be performed in any other way. Smalltalk without primitives can
> +        move values from one variable to another, but cannot add two SmallIntegers
> +        together. Many methods for arithmetic and comparison between numbers
> +        are primitives. Some primitives allow Smalltalk to communicate with I/O
> +        devices such as the disk, the display, and the keyboard. Some primitives
> +        exist only to make the system run faster; each does the same thing as a
> +        certain Smalltalk method, and its implementation as a primitive is optional.
> +
> +        When the Smalltalk virtual machine begins to execute a method which
> +        specifies a primitive response, it tries to perform the primitive action and to
> +        return a result. If the routine in the virtual machine for this primitive is
> +        successful, it will return a value and the expressions in the method will not
> +        be evaluated. If the primitive routine is not successful, the primitive 'fails',
> +        and the Smalltalk expressions in the method are executed instead. These
> +        expressions are evaluated as though the primitive routine had not been called.
> +
> +        The Smalltalk code that is evaluated when a primitive fails usually anticipates
> +        why that primitive might fail. If the primitive is optional, the expressions in the
> +        method do exactly what the primitive would have done (See Number @). If the
> +        primitive only works on certain classes of arguments, the Smalltalk code tries
> +        to coerce the argument or appeals to a superclass to find a more general way
> +        of doing the operation (see SmallInteger +). If the primitive is never supposed
> +        to fail, the expressions signal an error (see e.g. SmallInteger asFloat).
> +
> -        Primitives exist for several reasons. Certain basic or 'primitive'
> -        operations cannot be performed in any other way. Smalltalk without
> -        primitives can move values from one variable to another, but cannot add two
> -        SmallIntegers together. Many methods for arithmetic and comparison
> -        between numbers are primitives. Some primitives allow Smalltalk to
> -        communicate with I/O devices such as the disk, the display, and the keyboard.
> -        Some primitives exist only to make the system run faster; each does the same
> -        thing as a certain Smalltalk method, and its implementation as a primitive is
> -        optional.
> -
> -        When the Smalltalk interpreter begins to execute a method which specifies a
> -        primitive response, it tries to perform the primitive action and to return a
> -        result. If the routine in the interpreter for this primitive is successful,
> -        it will return a value and the expressions in the method will not be evaluated.
> -        If the primitive routine is not successful, the primitive 'fails', and the
> -        Smalltalk expressions in the method are executed instead. These
> -        expressions are evaluated as though the primitive routine had not been
> -        called.
> -
> -        The Smalltalk code that is evaluated when a primitive fails usually
> -        anticipates why that primitive might fail. If the primitive is optional, the
> -        expressions in the method do exactly what the primitive would have done (See
> -        Number @). If the primitive only works on certain classes of arguments, the
> -        Smalltalk code tries to coerce the argument or appeals to a superclass to find
> -        a more general way of doing the operation (see SmallInteger +). If the
> -        primitive is never supposed to fail, the expressions signal an error (see
> -        SmallInteger asFloat).
> -
>          Each method that specifies a primitive has a comment in it. If the primitive is
>          optional, the comment will say 'Optional'. An optional primitive that is not
> +        implemented always fails, and the Smalltalk expressions do the work instead.
> -        implemented always fails, and the Smalltalk expressions do the work
> -        instead.
> 
> +        If a primitive is not optional, the comment will say, 'Essential'. If the primitive is
> +        so required, the comment will say 'Do not override in a subclass'. Some methods
> +        will have the comment, 'No Lookup'. See Object howToModifyPrimitives for an
> +        explanation of special selectors which are not looked up.
> -        If a primitive is not optional, the comment will say, 'Essential'. Some
> -        methods will have the comment, 'No Lookup'. See Object
> -        howToModifyPrimitives for an explanation of special selectors which are
> -        not looked up.
> 
> +        The comments in the SmallInteger primitives say 'Fails if result is not a SmallInteger',
> +        even though the implementor has the option to construct a LargePositiveInteger.
> +        For further information on primitives, see the 'Primitive Methods' part of the
> +        chapter on the formal specification of the virtual machine in
> +        Smalltalk-80: The Language and its Implementation."
> -        For the primitives for +, -, *, and bitShift: in SmallInteger, and truncated
> -        in Float, the primitive constructs and returns a 16-bit
> -        LargePositiveInteger when the result warrants it. Returning 16-bit
> -        LargePositiveIntegers from these primitives instead of failing is
> -        optional in the same sense that the LargePositiveInteger arithmetic
> -        primitives are optional. The comments in the SmallInteger primitives say,
> -        'Fails if result is not a SmallInteger', even though the implementor has the
> -        option to construct a LargePositiveInteger. For further information on
> -        primitives, see the 'Primitive Methods' part of the chapter on the formal
> -        specification of the interpreter in the Smalltalk book."
> 
>          self error: 'comment only'!
> 
> 

> 



More information about the Squeak-dev mailing list