Clone wiki

stx:goodies/petitparser / PortabilityHowTo

How to Write Portable Code

This page contains hints on how to write a portable code to make sure the code will run on both Pharo and Smalltalk/X without significant effort when merging.

  • make sure no method refers to instance variables that are undeclared. Smalltalk/X refuses to commit and compile such methods for a very good reason. In Pharo, please do use UndeclaredChaser (see below) to check for undeclared variables.
  • do not use Object>>asString. Not all Smalltalks implement it.
  • do not use Object>>name. Not all Smalltalks implement it.
  • do not use Dictionary>>keysAndValuesRemove:. Not all Smalltalks implement it.
  • do not use Class>>methods The semantics is different among Smalltalks. Use Class methodDictionary values instead.
  • when a class implements instance #initialize, make sure the class side method new sends it (or it inherits it from it's superclass in the same package). Do not depend on the fact that Pharo sends #initialize automatically - not all Smalltalks do this.
  • do not pass parameters to ifNil:[ ... ] ifNotNil: [ ... ] blocks.

Avoid:

^(self computeSomeObject) ifNotNil:[ :object | object ] ifNil:[ NullObject new ]

Use:

| object |
object := self computeSomeObject.
^ object notNil ifTrue:[ object ] ifFalse:[ NullObject new ].

Smalltalk/X stc compiler cannot compile ifNotNil:ifNil with parameters. Moreover, better use notNil ifTrue:[ ... ] ifFalse: [ ... ] - stc optimizes this better...

Using a UndeclaredChaser in Pharo

...specially crafted for Jan :-)

Install UndeclaredChaser:

Gofer new
    url: 'http://smalltalkhub.com/mc/JanVrany/Misc/main';
    package: 'UndeclaredChaser';
    load.

Run chaser on packages, especially on PetitCompiler package. To do so, inspect result of following expression:

UndeclaredChaser new chaseIn: 'PetitCompiler'

If it's an empty collection, there are no undeclared. If not, there's a problem. The collection contains associations from a CompiledMethod to name of the undeclared variable, i.e., if if contains PEGFsaTransition>>#accepts:->#characterSet then it means that method #accepts: in class PEGFsaTransition refer to variable characterSet which is actually not declared (neither local var, neither instvar).

Updated