foo: -> foo_() Naming convention for generated C code

Paul Fernhout pdfernhout at kurtz-fernhout.com
Wed Jul 19 14:15:27 UTC 2000


Michael Lucas-Smith wrote:
> I like this. It gives the chance to be able to FileIn C/Pascal code back in
> to Smalltalk.. as long as the C/Pascal code follows the right coding
> 'rules'

Wow. I hadn't thought of this. Excellent point. Round trip!

> Perhaps you can write about the implications of including the
> currentClassName_ in the method name for the generated code.
> 
> Michael.

Well, since you asked...

I made a subclass of TMethod and related changes to store the class in
it. I think this is an oversight that TMethod doesn't know its class. 

Once you have the class, you can automatically prepend "MyClass_" (or
whatever) to functions, and add a pointer to "MyClass* myClassInstance"
into the function prototype (where MyClass is a struct with fields). You
also need to follow that up with inserting an argument to calls to such
functions (passing the pseudo class around to other functions that need
it). This gives you something a bit more object oriented. 

Good support for this when outputting a set of Smalltalk classes to C
would include knowing what methods went with what classes (if they were
uniquely named) and thus prepending the correct class name and inserting
the correct first argument (aWhateverClassName) in the function call if
the receiver was a variable (hopefully appropriately named to give an
indication of the type, like "aThisClass whatever" ->
"ThisClass_whatever(aThisClass);").

You would also need to in C reference variables through the struct, or
in Pascal do a "with" at the beginning of the function. Note that I
don't yet have code to do the automatic referencing of what are global
variables through the struct... I'm willing to tolerate some required
hand conversion post processing.

I did a lot of this rewriting by hand for the [never finished]
Squeak->Newton port attempt, but this time three years later after
looking at how the code generator worked again, it seems so much clearer
how to do this more automatically. The Newton C/C++ compiler doesn't
support globals, and so the VM has to be passed around if it were to
work -- either as a struct -- or by making the VM a C++ class, which is
actually what I did in the Newton port attempt. This approach could of
course also be modified to output C++ code or generate funciton calls to
variables with that convention, thus "aMyClass->whatever()" instead of
"MyClass_whatever(aMyClass)".

Example output of my current approach (after having substituted by hand
"PR" for "PointrelRepository"):

struct PR {
  int baseFileName;
  int conceptCache;
  int definesSymbolNodeConcept;
  int indexFile;
  ...
  }

int PR_triadForConcept_(PR* aPR, const char* name);

int PR_triadForConcept_(PR* aPR, const char* name) {
  int conceptNode;
  int cachedConcept;
  
  cachedConcept = PR_conceptFromCache_(aPR, name);
  if (cachedConcept != null) {
    return cachedConcept;
    }
  conceptNode = PR_triadForConceptUncached_(aPR, name);
  PR_addToCacheConcept_node_(aPR, name, conceptNode);
  return conceptNode;
  }

Note that this sort of code would "swig" very nicely for Python.
  http://www.swig.org

Here is the original Smalltalk for reference (comments removed):
triadForConcept: name 
	| conceptNode cachedConcept |
	cachedConcept := self conceptFromCache: name.
	cachedConcept notNil ifTrue: [^cachedConcept].
	conceptNode := self triadForConceptUncached: name.
	"print triadForConcept: added concept , name, conceptNode"
	self addToCacheConcept: name node: conceptNode.
	^ conceptNode

-Paul Fernhout
Kurtz-Fernhout Software 
=========================================================
Developers of custom software and educational simulations
Creators of the Garden with Insight(TM) garden simulator
http://www.kurtz-fernhout.com





More information about the Squeak-dev mailing list