Automatic Generation of Glue for Named Primitives

Andrew C. Greenberg werdna at gate.net
Sun Sep 5 07:04:41 UTC 1999


Attached is a changefile with a working first cut at a tool for
automatically generating named (pluggable) primitives glue.  After
filing in the changeset, one can create a subclass of
InterpreterPlugin, as usual, but instead of manually coding the glue,
one may instead generates a "specification" in a #gluespecification
method in the class side of the plugin.

Several examples can be found after filing in by browsing in category
PPGen-Demo.

For example, the following is a sample specification for the "Foo"
example found in my Swiki discussion of named primitives:

glueSpecification

     ^super glueSpecification
        primitive: 'primFooIntegerSeventeen' on: nil returns: SmallInteger;
            code: #('result _ 17');
        primitive: 'primFooIntegerIdentity' on: nil returns: SmallInteger;
            parameter: 'anInteger' as: SmallInteger;
            code: #('result _ anInteger');
        primitive: 'primFooIntegerSumAnd' on: nil returns: SmallInteger;
            parameter: 'firstInteger' as: SmallInteger;
            parameter: 'secondInteger' as: SmallInteger;
            code: #('result _ firstInteger + secondInteger');
        primitive: 'primFooIntegerSumWith' on: Foo returns: SmallInteger;
            parameter: 'anInteger' as: SmallInteger;
            instVar: 'myInteger' as: SmallInteger;
            code: #('result _ anInteger + myInteger')

After building the gluespecification, one can generate the glue with
a doit along the following lines.

	YourPrimitiveNameHere generateGlue

This doIt performs the following:

A.  Adjust the Plugin's definition, as necessary, to assure that all
global instance variables are defined as plugin instance variables.
B.  Automatically generate a #declareCVarsIn: method in the class
side (in category 'glue'), consistent with the specification.
C.  Automatically generate a primitive glue method for each primitive
specified in the glueSpecification, consistent with each
specification.  Each method does the following:

	1. loads parameters into temporary variables, with or without
validation as specified in the glueSpecification;
	2. loads receiver instance variables into either temporary
variables or global variables, with or without validation, as
specified in the glueSpecification;
	3. return if the primitive failed validation, or if not,
execute the specified code;
	4. return if the primitive failed validation, or if not,
validate and save those instance variables identified for saving in
the specification.
	4. pop the stack and return a value, as appropriate.

Detailed for the specification methods will be forthcoming once I
have a stable, solid version of the tool.  In the meanwhile, one can
scry the basics from a review of class PluginSpecifiction.  A summary
follows:

I. Major Sections of the Specification

>>gInstVarsFrom: aReceiver (zero or more of these)

	Subsequent gInstVar: definitions will be treated as
specifying a global instance variable to be loaded from the specified
receiver object.

>>primitive: pName on: rcvrClass returns: resultClass (zero or more of these)

	Subsequent specifications will relate to the definition of
primitive method pName, which will expect to be called by an object
with the general "shape" (see below) of rcvrClass, and return an
object with the general "shape" of resultClass.

II. Specifying a method.  Further defining a primitive method
comprises specifying all parameters, instance variables actually
loaded or saved from the receiver.  These can be specified as follows:

	>>parameter: pString as: pClass

This specifies a parameter named pString, which will be loaded and
validated for having the "general shape" of class pClass.  Otherwise
the primitive will fail.

	>>parameter: pString kindOf: pClass

This specifies a parameter named pString, which will be loaded and
validated only if it is a member of pClass or of a subclass of
pClass.  Otherwise the primitive will fail.

	>>parameter: pString memberOf: pClass

This specifies a parameter named pString, which will be loaded and
validated only if the actual parameter is a member of pClass.
Otherwise the primitive will fail.

	>>parameter: pString asNoCheck: pClass

Same as #parameter:as:, except that no validation is done.


	>>instVar: pString as: pClass
	>>instVar: pString kindOf: pClass
	>>instVar: pString memberOf: pClass
	>>instVar: pString asNoCheck: pClass

This loads an instance variable from the receiver into a temporary
variable or variables of the method.  Note that the receiver must be
a member of the specified receiver class or a subclass thereof, and
pString must be the name of an instance variable of that reciever. or
else an error will be reported.  instVars can be loaded with as:,
kindOf, memberOf and asNoCheck variants, similar to those described
above.

	>>instVar: pString declareC: aString

This defines a programmer's temporary variable, which will be
declared in the C-module as specified in aString.  All loading to or
storing from these variables must be done in the user's code -- the
generator will only declare these variables.


	>>gInstVar: pString
	>>loadAllGVars

This loads the named instance variable into the global variable
specified (or all global variables defined above), provided that
pString had been defined in an earlier gInstVar definition and
further provided that pString is defined as an instance variable of
the method's reported receiver class or a subclass thereof.

	>>saveInstVar: pName
	>>saveAllInstVars

This directs the generator to generate code to assign the specified
instance variables back to the receiver upon the successful execution
of the primitive.

	>>code: aCollectionOfStrings

The collection of strings will be inserted into the code after the
parameters and instance variables are loaded, in #do: order.

III. Specfying global instance variables.

	>>gInstVar: iName as: iClass
	>>gInstVar: iName kindOf: iClass
	>>gInstVar: iName memberOf: iClass
	>>gInstVar: iName asNoCheck: iClass
	>>gInstVar: iName declareC: aString

Specifies a for loading receiver instance variables into the
primitive plugin's instance (and the C-module's global) variables.
The shape definitions are set forth as for primitives and temporary
instance variables.

IV. Notion of "shape"

Smalltalk doesn't have classes, per se, but instances of Smalltalk
classes have measurable and discernable representations in the
computer.  SmallIntegers, for example, are 30-bit values stored in a
specially munged way to be distinguishable from object pointers.
Other objects may have zero or more instance variables and zero or
more indexable variables.  The indexable variables might themselves
contain pointers to other objects, or might merely be 8- or 32-bit
quantities.  I refer to this collective information as the "shape" of
a Smalltalk object.

For these reasons, the manner in which a C-language program can load,
store and/or manipulate this information depends upon knowledge of
the shape of the object.  Later documentation will elaborate further
upon this notion and how it is used by the plugin generator.



Attachment converted: Anon:PrimPluginSupport.5Sept213a (TEXT/R*ch) (00013031)





More information about the Squeak-dev mailing list