Compiler

AssignmentNode
AssignmentNode comment: 'I represent a (var_expr) construct.'
accept:
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
emitCodeForEffect:encoder:
emitCodeForValue:encoder:
emitForEffect:on:
emitForValue:on:
isAssignmentNode
printOn:indent:
If control gets here, avoid recursion loop.
printOn:indent:precedence:
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:precedence:
sizeCodeForEffect:
sizeCodeForValue:
sizeForEffect:
sizeForValue:
toDoIncrement:
Only meant for Messages or Assignments - else return nil
value
variable
variable:value:
variable:value:from:
variable:value:from:sourceRange:
BlockLocalTempCounter
I am a support class for the decompiler that is used to find the number of local temps in a block by finding out what the stack offset is at the end of a block.
blockReturnTop
Return Top Of Stack bytecode.
doDup
Duplicate Top Of Stack bytecode.
doJoin
doPop
Remove Top Of Stack bytecode.
jump:
Unconditional Jump bytecode.
jump:if:
Conditional Jump bytecode.
methodReturnConstant:
Return Constant bytecode.
methodReturnReceiver
Return Self bytecode.
methodReturnTop
Return Top Of Stack bytecode.
popIntoLiteralVariable:
Remove Top Of Stack And Store Into Literal Variable bytecode.
popIntoReceiverVariable:
Remove Top Of Stack And Store Into Instance Variable bytecode.
popIntoRemoteTemp:inVectorAt:
Remove Top Of Stack And Store Into Offset of Temp Vector bytecode.
popIntoTemporaryVariable:
Remove Top Of Stack And Store Into Temporary Variable bytecode.
pushActiveContext
Push Active Context On Top Of Its Own Stack bytecode.
pushClosureCopyNumCopiedValues:numArgs:blockSize:
Push Closure bytecode. Either compute the end of the block if this is
the block we're analysing, or skip it, adjusting the stack as appropriate.
pushConsArrayWithElements:
Push Cons Array of size numElements popping numElements items from the stack into the array bytecode.
pushConstant:
Push Constant, value, on Top Of Stack bytecode.
pushLiteralVariable:
Push Contents Of anAssociation On Top Of Stack bytecode.
pushNewArrayOfSize:
Push New Array of size numElements bytecode.
pushReceiver
Push Active Context's Receiver on Top Of Stack bytecode.
pushReceiverVariable:
Push Contents Of the Receiver's Instance Variable Whose Index
is the argument, offset, On Top Of Stack bytecode.
pushRemoteTemp:inVectorAt:
Push Contents at Offset in Temp Vector bytecode.
pushTemporaryVariable:
Push Contents Of Temporary Variable Whose Index Is the
argument, offset, On Top Of Stack bytecode.
send:super:numArgs:
Send Message With Selector, selector, bytecode. The argument,
supered, indicates whether the receiver of the message is specified with
'super' in the source method. The arguments of the message are found in
the top numArguments locations on the stack and the receiver just
below them.
tempCountForBlockAt:in:
Compute the number of local temporaries in a block.
If the block begins with a sequence of push: nil bytecodes then some of
These could be initializing local temps. We can only reliably disambuguate
them from other uses of nil by parsing the stack and seeing what the offset
of the stack pointer is at the end of the block.
There are short-cuts. The ones we take here are
- if there is no sequence of push nils there can be no local temps
- we follow forward jumps to shorten the amount of scanning
testTempCountForBlockAt:in:
Compute the number of local temporaries in a block.
If the block begins with a sequence of push: nil bytecodes then some of
These could be initializing local temps. We can only reliably disambuguate
them from other uses of nil by parsing the stack and seeing what the offset
of the stack pointer is at the end of the block.There are short-cuts. The only
one we take here is
- if there is no sequence of push nils there can be no local temps
BlockNode
I represent a bracketed block with 0 or more arguments and 1 or more statements. If I am initialized with no statements, I create one. I have a flag to tell whether my last statement returns a value from the enclosing method. My last three fields remember data needed for code generation. I can emit for value in the usual way, in which case I create a literal method (actually a context remotely copied) to be evaluated by sending it value: at run time. Or I can emit code to be evaluated in line; this only happens at the top level of a method and in conditionals and while-loops, none of which have arguments.
accept:
actualScope
Answer the actual scope for the receiver. If this is an unoptimized block then it is its
actual scope, but if this is an optimized block then the actual scope is some outer block.
addArgument:
addHoistedTemps:
<SequenceableCollection>
addRemoteTemp:rootNode:
<MethodNode>
analyseArguments:temporaries:rootNode:
<MethodNode>
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
arguments
arguments:
Decompile.
arguments:statements:returns:from:
Compile.
block
blockExtent
^<Interval>
canBeSpecialArgument
Can I be an argument of (e.g.) ifTrue:?
closureCreationNode
code
computeCopiedValues:
constructClosureCreationNode:
decompileString
Answer a string description of the parse tree whose root is the receiver.
emitCodeExceptLast:encoder:
emitCodeForClosureValue:encoder:
if not supportsClosureOpcodes closureCreationSupportNode is the
node for thisContext closureCopy: numArgs [ copiedValues: { values } ]
emitCodeForEvaluatedClosureValue:encoder:
emitCodeForEvaluatedEffect:encoder:
emitCodeForEvaluatedValue:encoder:
emitCodeForValue:encoder:
emitExceptLast:on:
emitForEvaluatedEffect:on:
emitForEvaluatedValue:on:
emitForValue:on:
firstArgument
generateAsClosure
Answer if we're compiling under the closure regime. If blockExtent has been set by
analyseTempsWithin:rootNode: et al then we're compiling under the closure regime.
ifHasRemoteTempNodeEnsureInitializationStatementExists:
If a remoteTempNode has been added ensure a statement exists to initialize it.
isBlockNode
isComplex
Used for pretty printing to determine whether to start a new line
isJust:
isJustCaseError
isQuick
nArgsSlot
Private for the Encoder to use in bindArg
nArgsSlot:
Private for the Encoder to use in bindArg
noteOptimized
noteSourceRangeStart:end:encoder:
Note two source ranges for this node. One is for the debugger
and is of the last expression, the result of the block. One is for
source analysis and is for the entire block.
numberOfArguments
optimized
optimizedBlockHoistTempsInto:
<BlockNode>
postNumberingProcessTempsWithin:rootNode:
<BlockNode>
printArgumentsOn:indent:
printOn:indent:
statements size <= 1 ifFalse: [aStream crtab: level].
printStatementsOn:indent:
printTemporaries:on:doPrior:
Print any in-scope temporaries. If there are any evaluate aBlock
prior to printing. Answer whether any temporaries were printed.
printWithClosureAnalysisArgumentsOn:indent:
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisStatementsOn:indent:
printWithClosureAnalysisTemporariesOn:indent:
reindexingLocalsDo:encoder:
Evaluate aBlock wih arguments, temporaries and copiedValues reindexed for
their positions within the receiver's block, restoring the correct indices afterwards.
If encoder is not nil remember the temps for this block's extent.
remoteTempNodeName
Answer a useful name for a RemoteTempVectorNode in the receiver.
returnLast
returnNilIfNoOther
returnSelfIfNoOther:
returns
sizeCodeExceptLast:
sizeCodeForClosureValue:
Compute the size for the creation of the block and its code.
sizeCodeForEvaluatedClosureValue:
The closure value primitives push the arguments and the copied values.
The compiler guarantees that any copied values come before all local temps.
So on closure activation we only need to push nils for the remaining temporaries.
sizeCodeForEvaluatedEffect:
sizeCodeForEvaluatedValue:
sizeCodeForValue:
sizeExceptLast:
sizeForEvaluatedEffect:
sizeForEvaluatedValue:
sizeForValue:
startOfLastStatement
startOfLastStatement:
Note the source index of the start of the last full statement. The
last full statement is the value answered by a block and hence the
expression the debugger should display as the value of the block.
statements
statements:
statements:returns:
Decompile.
temporaries
temporaries:
withJust:
BraceNode
Used for compiling and decompiling brace constructs.
These now compile into either a fast short form for 4 elements or less:
Array braceWith: a with: b ...
or a long form of indefinfite length:
(Array braceStream: N) nextPut: a; nextPut: b; ...; braceArray.
The erstwhile brace assignment form is no longer supported.
accept:
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
blockAssociationCheck:
If all elements are MessageNodes of the form [block]->[block], and there is at
least one element, answer true.
Otherwise, notify encoder of an error.
casesForwardDo:
For each case in forward order, evaluate aBlock with three arguments:
the key block, the value block, and whether it is the last case.
casesReverseDo:
For each case in reverse order, evaluate aBlock with three arguments:
the key block, the value block, and whether it is the last case.
elements
elements:
Decompile.
elements:sourceLocations:
Compile.
emitCodeForValue:encoder:
emitForValue:on:
example
matchBraceStreamReceiver:messages:
matchBraceWithReceiver:selector:arguments:
maxElementsForConsArray
Hack; we have no way of knowing how much stack space is available during sizing
numElements
printOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
selectorForShortForm:
sizeCodeForValue:
sizeForValue:
BytecodeAgnosticMethodNode
I am a version of MethodNode that is able to work with different BytecodeEncoders, and is hence able to generate methods using different bytecode sets.
addLocalsToPool:
<Set of: TempVariableNode>
blockExtentsToTempsMap
Answer a Dictionary of blockExtent to temp locations for the current method.
This is used by the debugger to locate temp vars in contexts. A temp map
entry is a pair of the temp's name and its index, where an index is either an
integer for a normal temp or a pair of the index of the indirect temp vector
containing the temp and the index of the temp in its indirect temp vector.
ensureClosureAnalysisDone
generate:
The receiver is the root of a parse tree. Answer a CompiledMethod.
The argument, trailer, is the reference to the source code that is
stored with every CompiledMethod.
hasGeneratedMethod
locationCounter
noteBlockEntry:
Evaluate aBlock with the numbering for the block entry.
noteBlockExit:
Evaluate aBlock with the numbering for the block exit.
printWithClosureAnalysisOn:
Refer to the comment in Object|printOn:.
referencedValuesWithinBlockExtent:
schematicTempNamesString
Answer the temp names for the current method node in a form that captures
temp structure. The temps at each method and block scope level occur
space-separated, with any indirect temps enclosed in parentheses. Each block
level is enclosed in square brackets. e.g.
'method level temps (indirect temp)[block args and temps (indirect)]'
This representation can be reconstituted into a blockExtentsToTempsMap
by a CompiledMethod that has been copied with the schematicTempNamesString.
BytecodeEncoder
I am an abstract superclass for different bytecode set encoders. Subclasses inherit the literal management of Encoder and encapsulate the mapping of opcodes to specific bytecodes.
bindAndJuggle:
This is used to insert a new temp and reorcder temps on editing.
It doesn't really work for closure compilation since we have multiple
locations for temps. Simply signal a reparse is necessary.
bindBlockArg:within:
Read the comment in the superclass's method.
If we have closures we should check the argument
count against the block, not the method.
(Note that this isn't entirely adequate either since optimized blocks
will slip through the cracks (their arguments (i.e. ifNotNil: [:expr|)
are charged against their enclosing block, not themselves)).
bindBlockTemp:within:
Read the comment in the superclass's bindBlockArg:within: method.
If we have closures we should check the argument
count against the block, not the method.
(Note that this isn't entirely adequate either since optimized blocks
will slip through the cracks (their arguments (i.e. ifNotNil: [:expr|)
are charged against their enclosing block, not themselves)).
bindTemp:
Declare a temporary; error not if a field or class variable or out-of-scope temp.
Read the comment in Encoder>>bindBlockArg:within: and subclass implementations.
blockExtentsToTempsMap
Answer a Dictionary of blockExtent to temp locations for the current method.
This is used by the debugger to locate temp vars in contexts. A temp map
entry is a pair of the temp's name and its index, where an index is either an
integer for a normal temp or a pair of the index of the indirect temp vector
containing the temp and the index of the temp in its indirect temp vector.
hasGeneratedMethod
if:isSpecialLiteralForPush:
If code is that of a special literal for push then evaluate aBlock with the special literal
The special literals for push are nil true false -1 0 1 & 2 which have special encodings
in the blue book bytecode set. Answer whether it was a special literal.
if:isSpecialLiteralForReturn:
If code is that of a special literal for return then evaluate aBlock with the special literal.
The special literals for return are nil true false which have special encodings
in the blue book bytecode set. Answer whether it was a special literal.
methodNodeClass
methodStreamPosition
nextPut:
For sizing make the encoder its own stream and
keep track of position with this version of nextPut:
noteBlockExtent:hasLocals:
outOfRangeError:index:range:to:
For now...
printSchematicTempNamesOn:blockExtents:fromIndex:
Print the locals in the blockExtent startIndex, recursing to print any locals in nested blockExtents.
Answer the index of the last blockExtent printed.
rootNode
^<BlockNode>
rootNode:
<BlockNode>
schematicTempNamesOn:blockExtents:fromIndex:
Print the locals in the blockExtent startIndex, recursing to print any locals in nested blockExtents.
Answer the index of the last blockExtent printed.
schematicTempNamesString
Answer the temp names for the current method node in a form that captures
temp structure. The temps at each method and block scope level occurr
space-separated, with any indirect temps enclosed in parentheses. Each block
level is enclosed in square brackets. e.g.
'method level temps (indirect temp)[block args and temps (indirect)]'
This representation can be reconstituted into a blockExtentsToTempsMap
by a CompiledMethod that has been copied with teh schematicTempNamesString.
sizeBranchPopFalse:
sizeBranchPopTrue:
sizeDup
sizeJump:
sizeJumpLong:
sizeOpcodeSelector:withArguments:
sizePop
sizePushClosureCopyNumCopiedValues:numArgs:jumpSize:
sizePushConsArray:
sizePushInstVar:
sizePushInstVarLong:
sizePushLiteral:
sizePushLiteralVar:
sizePushNewArray:
sizePushReceiver
sizePushRemoteTemp:inVectorAt:
sizePushSpecialLiteral:
sizePushTemp:
sizePushThisContext
sizeReturnReceiver
sizeReturnSpecialLiteral:
sizeReturnTop
sizeReturnTopToCaller
sizeSend:numArgs:
sizeSendSuper:numArgs:
sizeStoreInstVar:
sizeStoreInstVarLong:
sizeStoreLiteralVar:
sizeStorePopInstVar:
sizeStorePopInstVarLong:
sizeStorePopLiteralVar:
sizeStorePopRemoteTemp:inVectorAt:
sizeStorePopTemp:
sizeStoreRemoteTemp:inVectorAt:
sizeStoreTemp:
streamToMethod:
supportsClosureOpcodes
Answer if the receiver supports the
genPushNewArray:/genPushConsArray:
genPushRemoteTemp:inVectorAt:
genStoreRemoteTemp:inVectorAt:
genStorePopRemoteTemp:inVectorAt:
genPushClosureCopyCopiedValues:numArgs:jumpSize:
opcodes
CascadeNode
The first message has the common receiver, the rest have receiver == nil, which signifies cascading.
accept:
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
emitCodeForValue:encoder:
emitForValue:on:
messages
printOn:indent:
If control gets here, avoid recursion loop.
printOn:indent:precedence:
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:precedence:
receiver
receiver:messages:
Transcript show: 'abc'; cr; show: 'def'
sizeCodeForValue:
sizeForValue:
ColoredCodeStream
A ColoredCodeStream is xxxxxxxxx.
Instance Variables
colorTable: <Object>
dialect: <Object>
colorTable
- xxxxx
dialect
- xxxxx
colorTable
Answer the table to use to determine colors
contents:
initialize
Subclasses should redefine this method to perform initializations on instance creation
withColor:emphasis:do:
Evaluate the given block with the given color and style text attribute
withStyleFor:do:
Evaluate aBlock with appropriate emphasis and color for the given elementType
CommentNode
A CommentNode is xxxxxxxxx.
Instance Variables
accept:
CompiledMethodWithNode
A CompiledMethodWithNode is xxxxxxxxx.
Instance Variables
method: <Object>
node: <Object>
method
- xxxxx
node
- xxxxx
generateMethodFromNode:trailer:
method
method:
method:node:
node
node:
selector
Compiler
The compiler accepts Smalltalk source code and compiles it with respect to a given class. The user of the compiler supplies a context so that temporary variables are accessible during compilation. If there is an error, a requestor (usually a kind of StringHolderController) is sent the message notify:at:in: so that the error message can be displayed. If there is no error, then the result of compilation is a MethodNode, which is the root of a parse tree whose nodes are kinds of ParseNodes. The parse tree can be sent messages to (1) generate code for a CompiledMethod (this is done for compiling methods or evaluating expressions); (2) pretty-print the code (for formatting); or (3) produce a map from object code back to source code (used by debugger program-counter selection). See also Parser, Encoder, ParseNode.
compile:in:classified:notifying:ifFail:
Answer a MethodNode for the argument, textOrStream. If the
MethodNode can not be created, notify the argument, aRequestor; if
aRequestor is nil, evaluate failBlock instead. The MethodNode is the root
of a parse tree. It can be told to generate a CompiledMethod to be
installed in the method dictionary of the argument, aClass.
compile:in:notifying:ifFail:
compileNoPattern:in:context:notifying:ifFail:
Similar to #compile:in:notifying:ifFail:, but the compiled code is
expected to be a do-it expression, with no message pattern.
compiledMethodFor:in:to:notifying:ifFail:logged:
Compiles the sourceStream into a parse tree, then generates code
into a method, and answers it. If receiver is not nil, then the text can
refer to instance variables of that receiver (the Inspector uses this).
If aContext is not nil, the text can refer to temporaries in that context
(the Debugger uses this). If aRequestor is not nil, then it will receive a
notify:at: message before the attempt to evaluate is aborted.
couldEvaluate:
decompilerClass
evaluate:
evaluate:for:logged:
evaluate:for:notifying:logged:
evaluate:in:to:
evaluate aString in the given context, and return the result. 2/2/96 sw
evaluate:in:to:notifying:ifFail:
evaluate:in:to:notifying:ifFail:logged:
Compiles the sourceStream into a parse tree, then generates code into a
method. This method is then installed in the receiver's class so that it
can be invoked. In other words, if receiver is not nil, then the text can
refer to instance variables of that receiver (the Inspector uses this). If
aContext is not nil, the text can refer to temporaries in that context (the
Debugger uses this). If aRequestor is not nil, then it will receive a
notify:at: message before the attempt to evaluate is aborted. Finally, the
compiled method is invoked from here as DoIt or (in the case of
evaluation in aContext) DoItIn:. The method is subsequently removed
from the class, but this will not get done if the invocation causes an
error which is terminated. Such garbage can be removed by executing:
Smalltalk allBehaviorsDo: [:cl | cl removeSelector: #DoIt; removeSelector:
#DoItIn:].
evaluate:logged:
evaluate:notifying:logged:
format:in:notifying:
Compile a parse tree from the argument, textOrStream. Answer a string containing the original code, formatted nicely. If aBoolean is true, then decorate the resulting text with color and hypertext actions
format:in:notifying:contentsSymbol:
Compile a parse tree from the argument, textOrStream.
Answer a string containing the original code, formatted nicely.
format:in:notifying:decorated:
format:noPattern:ifFail:
from:class:classified:context:notifying:
from:class:context:notifying:
interactive
new
notify:
Refer to the comment in Object|notify:.
notify:at:
Refer to the comment in Object|notify:.
parse:in:notifying:
Compile the argument, textOrStream, with respect to the class, aClass, and
answer the MethodNode that is the root of the resulting parse tree. Notify the
argument, req, if an error occurs. The failBlock is defaulted to an empty block.
parser
parser:
parserClass
parserClass:
recompileAll
recompileAllFrom:
translate:noPattern:ifFail:
translate:noPattern:ifFail:parser:
Decompiler
I decompile a method in three phases:
Reverser: postfix byte codes -> prefix symbolic codes (nodes and atoms)
Parser: prefix symbolic codes -> node tree (same as the compiler)
Printer: node tree -> text (done by the nodes)

instance vars:
constructor
method
instVars
tempVars
constTable
stack
statements
lastPc
exit
caseExits - stack of exit addresses that have been seen in the branches of caseOf:'s
lastJumpPc
lastReturnPc
limit
hasValue
blockStackBase
numLocaltemps - number of temps local to a block; also a flag indicating decompiling a block
blockForCaseTo:
Decompile a range of code as in statementsForCaseTo:, but return a block node.
blockReturnTop
No action needed
blockScopeRefersOnlyOnceToTemp:
blockTo:
Decompile a range of code as in statementsTo:, but return a block node.
case:
statements = keyStmts CascadeFlag keyValueBlock ... keyStmts
checkForBlock:selector:arguments:
checkForBlockCopy:
We just saw a blockCopy: message. Check for a following block.
checkForClosureCopy:arguments:
We just saw a closureCopy:copiedValues: message. Check for and construct a following block.
constructorForMethod:
convertToDoLoop
If statements contains the pattern
var := startExpr.
[var <= limit] whileTrue: [...statements... var := var + incConst]
then replace this by
startExpr to: limit by: incConst do: [:var | ...statements...]
decompile:in:
See Decompiler|decompile:in:method:. The method is found by looking up
the message, aSelector, in the method dictionary of the class, aClass.
decompile:in:method:
Answer a MethodNode that is the root of the parse tree for the
argument, aMethod, which is the CompiledMethod associated with the
message, aSelector. Variables are determined with respect to the
argument, aClass.
decompile:in:method:using:
decompileBlock:
Decompile aBlock, returning the result as a BlockNode.
Show temp names from source if available.
doClosureCopyCopiedValues:numArgs:blockSize:
doDup
doPop
doStore:
Only called internally, not from InstructionStream. StackOrBlock is stack
for store, statements for storePop.
initSymbols:
initialize
Subclasses should redefine this method to perform initializations on instance creation
interpretNextInstructionFor:
Change false here will trace all state in Transcript.
jump:
jump:if:
mapFromBlockStartsIn:toTempVarsFrom:constructor:
methodRefersOnlyOnceToTemp:
methodReturnConstant:
methodReturnReceiver
methodReturnTop
popIntoLiteralVariable:
popIntoReceiverVariable:
popIntoRemoteTemp:inVectorAt:
popIntoTemporaryVariable:
popTo:
pushActiveContext
pushClosureCopyNumCopiedValues:numArgs:blockSize:
pushConsArrayWithElements:
pushConstant:
pushLiteralVariable:
pushNewArrayOfSize:
pushReceiver
pushReceiverVariable:
pushRemoteTemp:inVectorAt:
pushTemporaryVariable:
quickMethod
recompileAllTest
sawBlueBookBlock
sawClosureBytecode
scanBlockScopeFor:from:to:with:scanner:
send:super:numArgs:
statementsForCaseTo:
Decompile the method from pc up to end and return an array of
expressions. If at run time this block will leave a value on the stack,
set hasValue to true. If the block ends with a jump or return, set exit
to the destination of the jump, or the end of the method; otherwise, set
exit = end. Leave pc = end.
Note that stack initially contains a CaseFlag which will be removed by
a subsequent Pop instruction, so adjust the StackPos accordingly.
statementsTo:
Decompile the method from pc up to end and return an array of
expressions. If at run time this block will leave a value on the stack,
set hasValue to true. If the block ends with a jump or return, set exit
to the destination of the jump, or the end of the method; otherwise, set
exit = end. Leave pc = end.
storeIntoLiteralVariable:
storeIntoReceiverVariable:
storeIntoRemoteTemp:inVectorAt:
storeIntoTemporaryVariable:
tempAt:
Needed by BraceConstructor<PopIntoTemporaryVariable
withTempNames:
<Array|String>
DecompilerConstructor
I construct the node tree for a Decompiler.
accept:
I am not really a ParseNode. Only here to access constants defined in parseNode.
codeAnyLitInd:
codeAnyLiteral:
codeAnySelector:
codeArguments:block:
codeArguments:temps:block:
codeAssignTo:value:
codeBlock:returns:
codeBrace:
codeCascade:messages:
codeCascadedMessage:arguments:
codeConstants
Answer with an array of the objects representing self, true, false, nil,
-1, 0, 1, 2.
codeEmptyBlock
codeInst:
codeMessage:selector:arguments:
codeMethod:block:tempVars:primitive:class:
codeSelector:code:
codeSuper
codeTemp:
codeTemp:named:
codeThisContext
decodeIfNilWithReceiver:selector:arguments:
isForClosures
method:class:literals:
DecompilerConstructorForClosures
A DecompilerConstructorForClosures is xxxxxxxxx.
Instance Variables
tempNameCounter: <Object>
tempNameCounter
- xxxxx
codeMethod:block:tempVars:primitive:class:
codeRemoteTemp:remoteTemps:
isForClosures
Encoder
I encode names and literals into tree nodes with byte codes for the compiler. Byte codes for literals are not assigned until the tree-sizing pass of the compiler, because only then is it known which literals are actually needed. I also keep track of sourceCode ranges during parsing and code generation so I can provide an inverse map for the debugger.
accept:
I am not really a ParseNode. Only here to access constants defined in parseNode.
allLiterals
associationForClass
autoBind:
Declare a block argument as a temp if not already declared.
bindAndJuggle:
bindArg:
Declare an argument.
bindBlockArg:within:
With standard Smalltalk-80 (BlueBook) blocks it used to be legal to use a
method temp as a block argument. This shouldn't be the case with the
current compiler, which checks for temp names already being used as
block arguments. But it is easily fooled by local block temps in optimized
blocks, e.g.
false
ifTrue: [| temp |]
ifFalse:[[:temp|]]
Rather than fix this we keep the semantics and fix it in the closure compiler.
bindBlockTemp:
Declare a temporary block variable; complain if it's not a field or class variable.
bindBlockTemp:within:
The BlockContext compiler (the Smalltalk-80 BlueBook compiler)
does provide support for ANSI block syntax, but not for ANSI block
semantics. Here all temps live at the same level, the method level.
The approach taken to two block-local temps in different blocks is to
merge them into a single temp. e.g.
expr
ifTrue: [|temp| self statementOne]
ifFalse: [|temp| self statementTwo]
is effectvely transformed into
| temp |
expr
ifTrue: [self statementOne]
ifFalse: [self statementTwo]
and
expr do: [:each| | temp | ...].
expr do: [:each| | temp | ...].
is also effectively transformed into
| temp |
expr do: [:each| ...].
expr do: [:each| ...].
The closure compiler treats the former similarly, but not the latter.
The indirection through #bindBlockTemp:within: allows the closure encoder to do this.
bindTemp:
Declare a temporary; error not if a field or class variable.
bindTemp:in:
Declare a temporary; error not if a field or class variable.
cantStoreInto:
classEncoding
This is a hack so that the parser may findout what class it was parsing for when it wants to create a syntax error view.
doItInContextName
encodeLiteral:
encodeSelector:
encodeVariable:
encodeVariable:ifUnknown:
encodeVariable:sourceRange:ifUnknown:
environment
Answer the environment of the current compilation context,
be it in a class or global (e.g. a workspace)
fillDict:with:mapping:to:
fixTemp:
floatTemp:
global:name:
globalSourceRanges
init:context:notifying:
initScopeAndLiteralTables
interactive
litIndex:
literals
Should only be used for decompiling primitives
lookupInPools:ifFound:
maxTemp
methodNodeClass
nTemps:literals:class:
Decompile.
name:key:class:type:set:
newTemp:
noteSourceRange:forNode:
noteSuper
notify:
Put a separate notifier on top of the requestor's window
notify:at:
Create and schedule a Notifier with the argument as the message in
order to request confirmation before a process can proceed. Subclasses can
override this and insert an error message at location within aString.
possibleNamesFor:
possibleVariablesFor:
rawSourceRanges
reallyBind:
release
Remove references to objects that may refer to the receiver. This message
should be overridden by subclasses with any cycles, in which case the
subclass should also include the expression super release.
requestor:
Often the requestor is a BrowserCodeController
selector
selector:
sharableLitIndex:
Special access prevents multiple entries for post-allocated super send special selectors
sourceMap
Answer with a sorted set of associations (pc range).
sourceRangeFor:
tempNames
tempNodes
temps:literals:class:
Decompile.
tempsAndBlockArgs
undeclared:
unusedTempNames
warnAboutShadowed:
EncoderForLongFormV3
I am an alternate to EncoderForV3 that tries to use thje longest forms of bytecodes possible so as to avoid using as many bytecode as possible to allow for the unused portions of the bytecode set this makes available to be reassigned.
I do not use the following ranges
0 through 111
0- 15 0000iiii Push Receiver Variable #iiii
16- 31 0001iiii Push Temporary Location #iiii
32- 63 001iiiii Push Literal Constant #iiiii
64- 95 010iiiii Push Literal Variable #iiiii
96-103 01100iii Pop and Store Receiver Variable #iii
104-111 01101iii Pop and Store Temporary Location #iii
138-159
138-143 Unused.
144-151 10010iii Jump iii + 1 (i.e., 1 through 8).
152-159 10011iii Pop and Jump 0n False iii +1 (i.e., 1 through 8).
176-255
176-191 1011iiii Send Arithmetic Message #iiii
192-207 1100iiii Send Special Message #iiii
208-223 1101iiii Send Literal Selector #iiii With No Arguments
224-239 1110iiii Send Literal Selector #iiii With 1 Argument
240-255 1111iiii Send Literal Selector #iiii With 2 Arguments
= 112 + (160 - 138) + (256 - 176) = 214, or 84% of the bytecodes
genBranchPopFalse:
See BlueBook page 596
genBranchPopTrue:
See BlueBook page 596
genDup
See BlueBook page 596
genJump:
See BlueBook page 596
genJumpLong:
See BlueBook page 596
genPop
See BlueBook page 596
genPushInstVar:
See BlueBook page 596
genPushInstVarLong:
See BlueBook page 596
genPushLiteral:
See BlueBook page 596
genPushLiteralVar:
See BlueBook page 596
genPushReceiver
See BlueBook page 596
genPushSpecialLiteral:
112-119 01110iii Push (receiver, true, false, nil, -1, 0, 1, 2) [iii]
genPushTemp:
See BlueBook page 596
genPushThisContext
See BlueBook page 596
genReturnReceiver
See BlueBook page 596
genReturnSpecialLiteral:
120-123 011110ii Return (receiver, true, false, nil) [ii] From Message
genReturnTop
See BlueBook page 596
genReturnTopToCaller
See BlueBook page 596
genSend:numArgs:
See BlueBook page 596 (with exceptions for 132 & 134)
genSendSuper:numArgs:
See BlueBook page 596 (with exceptions for 132 & 134)
genStoreInstVar:
See BlueBook page 596
genStoreInstVarLong:
See BlueBook page 596
genStoreLiteralVar:
See BlueBook page 596
genStorePopInstVar:
See BlueBook page 596
genStorePopInstVarLong:
See BlueBook page 596
genStorePopLiteralVar:
See BlueBook page 596
genStorePopTemp:
See BlueBook page 596
genStoreTemp:
See BlueBook page 596
initScopeAndLiteralTables
EncoderForLongFormV3PlusClosures
An encoder for the V3 bytecode set augmented with the following bytecodes that are part of the full closure implementation.
138 10001010 jkkkkkkk Push (Array new: kkkkkkk) (j = 0)
or Pop kkkkkkk elements into: (Array new: kkkkkkk) (j = 1)
140 10001100 kkkkkkkk jjjjjjjj Push Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
141 10001101 kkkkkkkk jjjjjjjj Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
142 10001110 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
143 10001111 llllkkkk jjjjjjjj iiiiiiii Push Closure Num Copied llll Num Args kkkk BlockSize jjjjjjjjiiiiiiii
This is an exact duplicate of EncoderForV3PlusClosures.
Could be a trait (or in Newspeak, a Mixin).
For now we impose upon you to synchronise any and all changes between these two classes.
genPushClosureCopyNumCopiedValues:numArgs:jumpSize:
143 10001111 llllkkkk jjjjjjjj iiiiiiii Push Closure Num Copied llll Num Args kkkk BlockSize jjjjjjjjiiiiiiii
genPushConsArray:
genPushNewArray:
genPushRemoteTemp:inVectorAt:
genStorePopRemoteTemp:inVectorAt:
142 10001110 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
genStoreRemoteTemp:inVectorAt:
141 10001101 kkkkkkkk jjjjjjjj Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
supportsClosureOpcodes
Answer if the receiver supports the
genPushNewArray:/genPushConsArray:
genPushRemoteTemp:inVectorAt:
genStoreRemoteTemp:inVectorAt:
genStorePopRemoteTemp:inVectorAt:
genPushClosureCopyCopiedValues:numArgs:jumpSize:
opcodes
EncoderForV3
I add behaviour to Encoder to size and emit bytecodes for the Squeak V3.x VM bytecode set. The intention is for another subclass to restrict the range of bytecodes used to long forms only, allowing the bytecode set to be redefined by avoiding using the many short forms. The short forms may then be reassigned.
genBranchPopFalse:
See BlueBook page 596
genBranchPopTrue:
See BlueBook page 596
genDup
See BlueBook page 596
genJump:
See BlueBook page 596
genJumpLong:
See BlueBook page 596
genPop
See BlueBook page 596
genPushInstVar:
See BlueBook page 596
genPushInstVarLong:
See BlueBook page 596
genPushLiteral:
See BlueBook page 596
genPushLiteralVar:
See BlueBook page 596
genPushReceiver
See BlueBook page 596
genPushSpecialLiteral:
112-119 01110iii Push (receiver, true, false, nil, -1, 0, 1, 2) [iii]
genPushTemp:
See BlueBook page 596
genPushThisContext
See BlueBook page 596
genReturnReceiver
See BlueBook page 596
genReturnSpecialLiteral:
120-123 011110ii Return (receiver, true, false, nil) [ii] From Message
genReturnTop
See BlueBook page 596
genReturnTopToCaller
See BlueBook page 596
genSend:numArgs:
See BlueBook page 596 (with exceptions for 132 & 134)
genSendSuper:numArgs:
See BlueBook page 596 (with exceptions for 132 & 134)
genStoreInstVar:
See BlueBook page 596
genStoreInstVarLong:
See BlueBook page 596
genStoreLiteralVar:
See BlueBook page 596
genStorePopInstVar:
See BlueBook page 596
genStorePopInstVarLong:
See BlueBook page 596
genStorePopLiteralVar:
See BlueBook page 596
genStorePopTemp:
See BlueBook page 596
genStoreTemp:
See BlueBook page 596
EncoderForV3PlusClosures
An encoder for the V3 bytecode set augmented with the following bytecodes that are part of the full closure implementation.
138 10001010 jkkkkkkk Push (Array new: kkkkkkk) (j = 0)
or Pop kkkkkkk elements into: (Array new: kkkkkkk) (j = 1)
140 10001100 kkkkkkkk jjjjjjjj Push Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
141 10001101 kkkkkkkk jjjjjjjj Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
142 10001110 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
143 10001111 llllkkkk jjjjjjjj iiiiiiii Push Closure Num Copied llll Num Args kkkk BlockSize jjjjjjjjiiiiiiii
This is an exact duplicate of EncoderForLongFormV3PlusClosures.
Could be a trait (or in Newspeak, a Mixin).
For now we impose upon you to synchronise any and all changes between these two classes.
genPushClosureCopyNumCopiedValues:numArgs:jumpSize:
143 10001111 llllkkkk jjjjjjjj iiiiiiii Push Closure Num Copied llll Num Args kkkk BlockSize jjjjjjjjiiiiiiii
genPushConsArray:
genPushNewArray:
genPushRemoteTemp:inVectorAt:
genStorePopRemoteTemp:inVectorAt:
142 10001110 kkkkkkkk jjjjjjjj Pop and Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
genStoreRemoteTemp:inVectorAt:
141 10001101 kkkkkkkk jjjjjjjj Store Temp At kkkkkkkk In Temp Vector At: jjjjjjjj
supportsClosureOpcodes
Answer if the receiver supports the
genPushNewArray:/genPushConsArray:
genPushRemoteTemp:inVectorAt:
genStoreRemoteTemp:inVectorAt:
genStorePopRemoteTemp:inVectorAt:
genPushClosureCopyCopiedValues:numArgs:jumpSize:
opcodes
FieldNode
FileNode handles field access in Tweak, e.g. self fieldName := foo => self fieldName: foo.
accept:
assignmentCheck:at:
For messageNodes masquerading as variables for the debugger.
For now we let this through - ie we allow stores ev
into args. Should check against numArgs, though.
emitCodeForEffect:encoder:
emitCodeForLoad:encoder:
Do nothing
emitCodeForStore:encoder:
emitCodeForStorePop:encoder:
emitCodeForValue:encoder:
emitForEffect:on:
emitForValue:on:
emitLoad:on:
Do nothing
emitStore:on:
emitStorePop:on:
encodeReceiverOn:
encode the receiver node
fieldDef
fieldDefinition:
name:key:index:type:
Only used for initting global (litInd) variables
sizeCodeForEffect:
sizeCodeForStore:
sizeCodeForStorePop:
sizeCodeForValue:
sizeForEffect:
sizeForStore:
sizeForStorePop:
sizeForValue:
InstanceVariableNode
An InstanceVariableNode is xxxxxxxxx.
Instance Variables
accept:
emitCodeForStore:encoder:
emitCodeForStorePop:encoder:
emitCodeForValue:encoder:
name:index:
sizeCodeForStore:
sizeCodeForStorePop:
sizeCodeForValue:
LeafNode
I represent a leaf node of the compiler parse tree. I am abstract.

Types (defined in class ParseNode):
1 LdInstType (which uses class VariableNode)
2 LdTempType (which uses class VariableNode)
3 LdLitType (which uses class LiteralNode)
4 LdLitIndType (which uses class VariableNode)
5 SendType (which uses class SelectorNode).
Note that Squeak departs slightly from the Blue Book bytecode spec.
In order to allow access to more than 63 literals and instance variables,
bytecode 132 has been redefined as DoubleExtendedDoAnything:
byte2 byte3 Operation
(hi 3 bits) (lo 5 bits)
0 nargs lit index Send Literal Message 0-255
1 nargs lit index Super-Send Lit Msg 0-255
2 ignored rcvr index Push Receiver Variable 0-255
3 ignored lit index Push Literal Constant 0-255
4 ignored lit index Push Literal Variable 0-255
5 ignored rcvr index Store Receiver Variable 0-255
6 ignored rcvr index Store-pop Receiver Variable 0-255
7 ignored lit index Store Literal Variable 0-255
This has allowed bytecode 134 also to be redefined as a second extended send
that can access literals up to 64 for nargs up to 3 without needing three bytes.
It is just like 131, except that the extension byte is aallllll instead of aaalllll,
where aaa are bits of argument count, and lll are bits of literal index.
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
code
code:type:
emitCodeForEffect:encoder:
emitCodeForLoad:encoder:
Default is to do nothing.
Subclasses may need to override.
emitForEffect:on:
emitLong:on:
Emit extended variable access.
key
key:code:
key:index:type:
name:key:code:
reserve:
If this is a yet unused literal of type -code, reserve it.
sizeCodeForEffect:
sizeCodeForLoad:
Default is to do nothing.
Subclasses may need to override.
sizeCodeForValue:
sizeForEffect:
sizeForValue:
veryDeepFixupWith:
If fields were weakly copied, fix them here. If they were in the tree being copied, fix them up, otherwise point to the originals!!
veryDeepInner:
Copy all of my instance variables. Some need to be not copied at all, but shared. Warning!! Every instance variable defined in this class must be handled. We must also implement veryDeepFixupWith:. See DeepCopier class comment.
LiteralDictionary
A LiteralDictionary, like an IdentityDictionary, has a special test for equality. In this case it is simple equality between objects of like class. This allows equal Float or String literals to be shared without the possibility of erroneously sharing, say, 1 and 1.0
literalEquality:and:
Check if two literals should be considered equal and reduced to a single literal.
Delegate this task to the literal themselves, they are aware of their peculiarities and know how to behave.
scanFor:
Scan the key array for the first slot containing either a nil (indicating an empty slot) or an element that matches anObject. Answer the index of that slot or zero if no slot is found. This method will be overridden in various subclasses that have different interpretations for matching elements.
LiteralNode
I am a parse tree leaf representing a literal string or number.
accept:
emitCodeForValue:encoder:
emitForValue:on:
eval
When everything in me is a constant, I can produce a value. This is only used by the Scripting system (TilePadMorph tilesFrom:in:)
isConstantNumber
Overridden in LiteralNode
isLiteral
Answer whether the receiver has a literal text form recognized by the
compiler.
isSpecialConstant
literalValue
name:key:index:type:
For compatibility with Encoder>>name:key:class:type:set:
printOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
sizeCodeForValue:
LiteralVariableNode
A LiteralVariableNode is xxxxxxxxx.
Instance Variables
readNode: <Object>
writeNode: <Object>
readNode
- xxxxx
writeNode
- xxxxx
accept:
emitCodeForLoad:encoder:
Do nothing
emitCodeForStore:encoder:
emitCodeForStorePop:encoder:
emitCodeForValue:encoder:
emitForValue:on:
emitLoad:on:
Do nothing
emitStore:on:
emitStorePop:on:
sizeCodeForLoad:
Default is to do nothing.
Subclasses may need to override.
sizeCodeForStore:
sizeCodeForStorePop:
sizeCodeForValue:
sizeForStore:
sizeForStorePop:
sizeForValue:
MaybeContextInstanceVariableNode
This class conspires to arrange that inst var access for contexts is done exclusively using the long-form instance variabl;e access bytecodes. See InstructionStream class>>variablesAndOffsetsDo:.
A virtual machine can benefit in performance by organizing method and block activations using a more conventional stack organization than by using first-class activation records (contexts). But such a virtual machine is also cabable of hiding the stack and making it appear as if contexts are still used. This means the system has better performance but still has all the benefits of first-class activation records. To pull this off the VM needs to intercept any and all accesses to context objects so that it can make contexts function as proxy objects for stack frames.
Without help from the image such a virtual machine based on an interpreter would have to perform an expensive check on all instance variable accesses to determine if the instance variable was that of a context serving as a proxy for a stack frame. A simple hack is to take advantage of the short and long forms of instance variable access bytecodes. The BlueBook instruction set (and likely any bytecode set evolved from it) has short form bytecodes for fetching and storing the first few bytecodes (BlueBook fetch first 16, store first 8). Contexts typically have at most 6 instance variables. If we arrange to use the long-form bytecodes for all context inst var accesses then we only have to check for context inst var access in long-form bytecodes, and then only if the index is within the context inst var range. This effectively makes the check free because on modern processors checking an index fetched from memory into a register against a constant costs far less than the memry read to fetch the index.
code
Answer a bogus code to avoid creating quick methods.
See MethodNode>>generate:ifQuick:
emitCodeForStore:encoder:
emitCodeForStorePop:encoder:
emitCodeForValue:encoder:
sizeCodeForStore:
sizeCodeForStorePop:
sizeCodeForValue:
MessageAsTempNode
This node represents accesses to temporary variables for do-its in the debugger. Since they execute in another context, they must send a message to the original context to access the value of the temporary variable in that context.
asStorableNode:
This node is a message masquerading as a temporary variable.
It currently has the form {homeContext tempAt: offset}.
We need to generate code for {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack.
This, in turn will get turned into {homeContext tempAt: offset put: expr}
at runtime if nobody disturbs storeAt:inTempFrame: in Object (not clean)
code
Allow synthetic temp nodes to be sorted by code
emitCodeForStorePop:encoder:
This node has the form {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack.
emitStorePop:on:
This node has the form {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack.
sizeCodeForStorePop:
This node has the form {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack.
sizeForStorePop:
This node has the form {expr storeAt: offset inTempFrame: homeContext},
where the expr, the block argument, is already on the stack.
store:from:
ctxt tempAt: n -> ctxt tempAt: n put: expr (see Assignment).
For assigning into temps of a context being debugged.
MessageNode
I represent a receiver and its message.

Precedence codes:
1 unary
2 binary
3 keyword
4 other

If special>0, I compile special code in-line instead of sending messages with literal methods as remotely copied contexts.
accept:
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
arguments
arguments:
argumentsInEvaluationOrder
Answer the receivers arguments in evaluation order.
If the receiver is a transformed to:do: node this will undo the misordering done by the transformation.
canCascade
cascadeReceiver
Nil out rcvr (to indicate cascade) and return what it had been.
checkBlock:as:from:
checkBlock:as:from:maxArgs:
vb: #canBeSpecialArgument for blocks hardcodes 0 arguments as the requirement for special blocks. We work around that here by further checking the number of arguments for blocks..
emitCase:on:value:
emitCodeForCase:encoder:value:
emitCodeForEffect:encoder:
For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly.
emitCodeForIf:encoder:value:
emitCodeForIfNil:encoder:value:
emitCodeForToDo:encoder:value:
var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2:
emitCodeForValue:encoder:
For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly.
emitCodeForWhile:encoder:value:
L1: ... Bfp(L2)|Btp(L2) ... Jmp(L1) L2:
emitForEffect:on:
For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly.
emitForValue:on:
For #ifTrue:ifFalse: and #whileTrue: / #whileFalse: style messages, the pc is set to the jump instruction, so that mustBeBoolean exceptions can be shown correctly.
emitIf:on:value:
emitIfNil:on:value:
emitToDo:on:value:
var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2:
emitWhile:on:value:
L1: ... Bfp(L2)|Btp(L2) ... Jmp(L1) L2:
eval
When everything in me is a constant, I can produce a value. This is only used by the Scripting system (TilePadMorph tilesFrom:in:)
ifNilReceiver
assuming this object is the receiver of an ifNil:, what object is being asked about?
initialize
Subclasses should redefine this method to perform initializations on instance creation
isComplex
Used for pretty printing to determine whether to start a new line
isMessage
isMessage:receiver:arguments:
Answer whether selector is selSymbol, and the predicates rcvrPred and argsPred
evaluate to true with respect to receiver and the list of arguments. If selSymbol or
either predicate is nil, it means 'don't care'. Note that argsPred takes numArgs
arguments. All block arguments are ParseNodes.
isMessageNode
isNilIf
isOptimized
isOptimizedLoop
isReturningIf
macroPrinter
noteSpecialSelector:
special > 0 denotes specially treated (potentially inlined) messages.
precedence
printCaseOn:indent:
receiver caseOf: {[key]->[value]. ...} otherwise: [otherwise]
printIfNil:indent:
printIfNilNotNil:indent:
printIfOn:indent:
printKeywords:arguments:on:indent:
printOn:indent:
may not need this check anymore - may be fixed by the #receiver: change
printOn:indent:precedence:
printParenReceiver:on:indent:
printReceiver:on:indent:
printToDoOn:indent:
printWhileOn:indent:
printWithClosureAnalysisCaseOn:indent:
receiver caseOf: {[key]->[value]. ...} otherwise: [otherwise]
printWithClosureAnalysisIfNil:indent:
printWithClosureAnalysisIfNilNotNil:indent:
printWithClosureAnalysisIfOn:indent:
printWithClosureAnalysisKeywords:arguments:on:indent:
printWithClosureAnalysisOn:indent:
may not need this check anymore - may be fixed by the #receiver: change
printWithClosureAnalysisOn:indent:precedence:
printWithClosureAnalysisParenReceiver:on:indent:
printWithClosureAnalysisReceiver:on:indent:
printWithClosureAnalysisToDoOn:indent:
printWithClosureAnalysisWhileOn:indent:
pvtCheckForPvtSelector:
If the code being compiled is trying to send a private message (e.g. 'pvtCheckForPvtSelector:') to anyone other than self, then complain to encoder.
receiver
receiver:
14 feb 2001 - removed return arrow
receiver:arguments:precedence:
receiver:selector:arguments:precedence:
Decompile.
receiver:selector:arguments:precedence:from:
Compile.
receiver:selector:arguments:precedence:from:sourceRange:
Compile.
selector
selector:
selectorIs:
sizeCase:value:
sizeCodeForCase:value:
sizeCodeForEffect:
sizeCodeForIf:value:
sizeCodeForIfNil:value:
sizeCodeForToDo:value:
var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2:
sizeCodeForValue:
sizeCodeForWhile:value:
L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only);
justStmt, wholeLoop, justJump.
sizeForEffect:
sizeForValue:
sizeIf:value:
sizeIfNil:value:
sizeToDo:value:
var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc] Jmp(L1) L2:
sizeWhile:value:
L1: ... Bfp(L2) ... Jmp(L1) L2: nil (nil for value only);
justStmt, wholeLoop, justJump.
test
toDoFromWhileWithInit:
Return nil, or a to:do: expression equivalent to this whileTrue:
toDoIncrement:
Only meant for Messages or Assignments - else return nil
toDoLimit:
transform:
transformAnd:
transformBoolean:
transformCase:
transformIfFalse:
transformIfFalseIfTrue:
transformIfNil:
vb: Removed the original transformBoolean: which amounds to a test we perform in each of the branches below.
transformIfNilIfNotNil:
vb: Changed to support one-argument ifNotNil: branch. In the 1-arg case we
transform the receiver to
(var := receiver)
which is further transformed to
(var := receiver) == nil ifTrue: .... ifFalse: ...
This does not allow the block variable to shadow an existing temp, but it's no different
from how to:do: is done.
transformIfNotNilIfNil:
vb: Changed to support one-argument ifNotNil: branch. In the 1-arg case we
transform the receiver to
(var := receiver)
which is further transformed to
(var := receiver) == nil ifTrue: .... ifFalse: ...
This does not allow the block variable to shadow an existing temp, but it's no different
from how to:do: is done.
transformIfTrue:
transformIfTrueIfFalse:
transformOr:
transformToDo:
var := rcvr. L1: [var <= arg1] Bfp(L2) [block body. var := var + inc]
Jmp(L1) L2:
transformWhile:
MethodNode
I am the root of the parse tree.
accept:
arguments
For transformations etc, not used in compilation
arguments:
For transformations etc, not used in compilation
asColorizedSmalltalk80Text
Answer a colorized Smalltalk-80-syntax string description of the parse tree whose root is the receiver.
block
body
decompileString
Answer a string description of the parse tree whose root is the receiver.
encoder
generate
The receiver is the root of a parse tree. Answer a CompiledMethod. The
argument, trailer, is the references to the source code that is stored with
every CompiledMethod.
generate:
The receiver is the root of a parse tree. Answer a CompiledMethod. The
argument, trailer, is the references to the source code that is stored with
every CompiledMethod.
generate:ifQuick:
methodClass
parserClass
Which parser produces this class of parse node
primitiveErrorVariableName
Answer the primitive error code temp name, or nil if none.
printOn:
Refer to the comment in Object|printOn:.
printPragmasOn:
printPrimitiveOn:
Print the primitive on aStream
printPropertiesOn:
printWithClosureAnalysisOn:
Refer to the comment in Object|printOn:.
properties
rawSourceRanges
rawSourceRangesAndMethodDo:
Evaluate aBinaryBlock with the rawSourceRanges and method generated from the receiver.
removeAndRenameLastTempIfErrorCode
removeProperty:
selector
Answer the message selector for the method represented by the receiver.
selector:
selector:arguments:precedence:temporaries:block:encoder:primitive:
Initialize the receiver with respect to the arguments given.
selector:arguments:precedence:temporaries:block:encoder:primitive:properties:
Initialize the receiver with respect to the arguments given.
selectorNode
Answer a SelectorNode for the message selector of the method represented by the receiver.
sourceText
sourceText:
tempNames
temporaries
For transformations etc, not used in compilation
temporaries:
For transformations etc, not used in compilation
MethodTempsNode
A MethodTempsNode is xxxxxxxxx.
Instance Variables
temporaries: <Object>
temporaries
- xxxxx
NewArrayNode
I represent a node for the genPushNewArray: opcode.
accept:
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
emitCodeForValue:encoder:
numElements
numElements:
sizeCodeForValue:
ParseNode
This superclass of most compiler/decompiler classes declares common class variables, default messages, and the code emitters for jumps. Some of the class variables are initialized here; the rest are initialized in class VariableNode.
accept:
asReturnNode
assignmentCheck:at:
For messageNodes masquerading as variables for the debugger.
For now we let this through - ie we allow stores ev
into args. Should check against numArgs, though.
blockReturnCode
canBeSpecialArgument
Can I be an argument of (e.g.) ifTrue:?
canCascade
comment
comment:
currentValueIn:
emitBranchOn:dist:pop:on:
emitCodeForBlockValue:encoder:
Generate code for evaluating the last statement in a block
emitCodeForBranchOn:dist:pop:encoder:
emitCodeForEffect:encoder:
emitCodeForJump:encoder:
emitCodeForReturn:encoder:
emitForEffect:on:
emitForReturn:on:
emitJump:on:
emitLong:code:on:
Force a two-byte jump.
emitShortOrLong:code:on:
encodeSelector:
ifNilReceiver
assuming this object is the receiver of an ifNil:, what object is being asked about?
initialize
Subclasses should redefine this method to perform initializations on instance creation
isArg
isAssignmentNode
isBlockNode
isComplex
Used for pretty printing to determine whether to start a new line
isConstantNumber
Overridden in LiteralNode
isDoIt
polymorphic with RBNodes; called by debugger
isFutureNode
isJust:
isLiteral
Answer whether the receiver has a literal text form recognized by the
compiler.
isMessage
isMessage:receiver:arguments:
See comment in MessageNode.
isMessageNode
isReturnSelf
isReturningIf
isSelfPseudoVariable
Overridden in VariableNode.
isSpecialConstant
isTemp
isUndefTemp
isUnusedTemp
isVariableNode
isVariableReference
nextWordFrom:setCharacter:
nodePrintOn:indent:
Show just the sub nodes and the code.
nodesDo:
notYetImplemented
nowHasDef
Ignored in all but VariableNode
nowHasRef
Ignored in all but VariableNode
optimizedBlockHoistTempsInto:
<BlockNode>
pc
Used by encoder source mapping.
pc:
Used by encoder source mapping.
popCode
printCommentOn:indent:
printOn:
Refer to the comment in Object|printOn:.
printOn:indent:
If control gets here, avoid recursion loop.
printOn:indent:precedence:
printSingleComment:on:indent:
Print the comment string, assuming it has been indented indent tabs.
Break the string at word breaks, given the widths in the default
font, at 450 points.
printWithClosureAnalysis
printWithClosureAnalysisOn:
Refer to the comment in Object|printOn:.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:precedence:
pushNilCode
selectorIs:
shortPrintOn:
sizeBranchOn:dist:
sizeCode:forBranchOn:dist:
sizeCode:forJump:
sizeCodeForBlockValue:
Answer the size for evaluating the last statement in a block
sizeCodeForEffect:
sizeCodeForReturn:
sizeForEffect:
sizeForReturn:
sizeJump:
sizeShortOrLong:
tempSortBlock
toDoIncrement:
Only meant for Messages or Assignments - else return nil
ParseNodeEnumerator
self superclass selectors do:
[:s|
self compile: (String streamContents:
[:str| | arg |
arg := 'a', (s allButFirst: 5) allButLast.
str nextPutAll: s, ' ', arg; crtab;
nextPutAll: 'theBlock value: '; nextPutAll: arg; nextPut: $.; crtab;
nextPutAll: '^super '; nextPutAll: s, ' ', arg])]
ofBlock:
visitAssignmentNode:
N.B. since assigment happens after the value is evaluated the value is visited first.
visitBlockNode:
visitBraceNode:
visitCascadeNode:
visitCommentNode:
visitFieldNode:
visitFutureNode:
visitInstanceVariableNode:
visitLiteralNode:
visitLiteralVariableNode:
visitMessageNode:
visitMessageNodeInCascade:
receiver is nil for cascades
visitMethodNode:
visitNewArrayNode:
visitRemoteTempVectorNode:
visitReturnNode:
visitSelectorNode:
visitTempVariableNode:
visitVariableNode:
ParseNodeVisitor
I am an abstract superclass for ParseNode visitors that functions as a null visitor. Here's the code that defines my interface:
(SystemNavigation default allImplementorsOf: #accept: localTo: ParseNode) do:
[:methodReference|
methodReference compiledMethod messages do:
[:sel|
((sel beginsWith: 'visit')
and: [sel numArgs = 1]) ifTrue:
[ParseNodeVisitor
compile: (String streamContents:
[:str|
str nextPutAll: sel;
space;
nextPut: $a.
methodReference classSymbol first isVowel ifTrue:
[str nextPut: $n].
str nextPutAll: methodReference classSymbol])
classified: 'visiting']]]
visitAssignmentNode:
N.B. since assigment happens after the value is evaluated the value is visited first.
visitBlockNode:
visitBraceNode:
visitCascadeNode:
visitCommentNode:
visitFieldNode:
visitFutureNode:
visitInstanceVariableNode:
visitLiteralNode:
visitLiteralVariableNode:
visitMessageNode:
visitMessageNodeInCascade:
receiver is nil for cascades
visitMethodNode:
visitNewArrayNode:
visitRemoteTempVectorNode:
visitReturnNode:
visitSelectorNode:
visitTempVariableNode:
visitVariableNode:
ParseStack
I keep track of the current and high position of the stack that will be needed by code being compiled.
init
pop:
position
position:
printOn:
Append to the argument, aStream, a sequence of characters that
identifies the receiver.
push:
size
Primitive. Answer the number of indexable variables in the receiver.
This value is the same as the largest legal subscript. Essential. See Object
documentation whatIsAPrimitive.
Parser
I parse Smalltalk syntax and create a MethodNode that is the root of the parse tree. I look one token ahead.
addComment
addPragma:
addWarning:
ignored by the default compiler.
advance
allocateLiteral:
argumentName
assignment:
var ':=' expression => AssignmentNode.
bindArg:
bindTemp:
bindTemp:in:
blockExpression
[ ({:var} |) (| {temps} |) (statements) ] => BlockNode.
braceExpression
{ elements } => BraceNode.
canDeclareClassVariable
cascade
{; message} => CascadeNode.
correctSelector:wordIntervals:exprInterval:ifAbort:
Correct the proposedKeyword to some selector symbol, correcting the original text if such action is indicated. abortAction is invoked if the proposedKeyword couldn't be converted into a valid selector. Spots is an ordered collection of intervals within the test stream of the for each of the keyword parts.
correctVariable:interval:
Correct the proposedVariable to a known variable, or declare it as a new
variable if such action is requested. We support declaring lowercase
variables as temps or inst-vars, and uppercase variables as Globals or
ClassVars, depending on whether the context is nil (class=UndefinedObject).
Spot is the interval within the test stream of the variable.
rr 3/4/2004 10:26 : adds the option to define a new class.
declareClassVar:
declareGlobal:
declareInstVar:
Declare an instance variable. Since the variable will get added after any existing
inst vars its index is the instSize.
declareTempAndPaste:
defineClass:
prompts the user to define a new class,
asks for it's category, and lets the users edit further
the definition
doNotWarnUser
encoder
encoderClass:
endOfLastToken
expected:
Notify a problem at token 'here'.
expression
externalFunctionDeclaration
Parse the function declaration for a call to an external library.
externalType:
Parse an return an external type
fail
init:notifying:failBlock:
initPattern:notifying:return:
initialize
Subclasses should redefine this method to perform initializations on instance creation
interactive
match:
Answer with true if next tokens type matches.
matchReturn
matchToken:
Matches the token, not its type.
messagePart:repeat:
method:context:encoder:
pattern [ | temporaries ] block => MethodNode.
newMethodNode
notify:
Notify problem at token before 'here'.
notify:at:
Create and schedule a Notifier with the argument as the message in
order to request confirmation before a process can proceed. Subclasses can
override this and insert an error message at location within aString.
offEnd:
Notify a problem beyond 'here' (in lookAhead token). Don't be offEnded!
parse:class:
parse:class:category:noPattern:context:notifying:ifFail:
Answer a MethodNode for the argument, sourceStream, that is the root of
a parse tree. Parsing is done with respect to the argument, class, to find
instance, class, and pool variables; and with respect to the argument,
ctxt, to find temporary variables. Errors in parsing are reported to the
argument, req, if not nil; otherwise aBlock is evaluated. The argument
noPattern is a Boolean that is true if the the sourceStream does not
contain a method header (i.e., for DoIts).
parse:class:noPattern:context:notifying:ifFail:
parse:class:noPattern:notifying:ifFail:
parseArgsAndTemps:notifying:
Parse the argument, aString, notifying req if an error occurs. Otherwise,
answer a two-element Array containing Arrays of strings (the argument
names and temporary variable names).
parseMethodComment:setPattern:
Answer the method comment for the argument, aString. Evaluate aBlock
with the message pattern in the form #(selector, arguments, precedence).
parseSelector:
Answer the message selector for the argument, aString, which should
parse successfully up to the temporary declaration or the end of the
method header.
pattern:inContext:
unarySelector | binarySelector arg | keyword arg {keyword arg} =>
{selector, arguments, precedence}.
possibleVariablesFor:
pragmaLiteral
Read a pragma literal.
pragmaLiteral:
Read a pragma literal. As a nicety we allow a variable name (rather
than a literal string) as the second argument to primitive:error:
pragmaPrimitives
pragmaSequence
Parse a sequence of method pragmas.
pragmaStatement
Read a single pragma statement. Parse all generic pragmas in the form of: <key1: val1 key2: val2 ...> and remember them, including primitives.
primaryExpression
primitive:
Create indexed primitive.
primitive:error:
Create indexed primitive with optional error code.
primitive:error:module:
Create named primitive with optional error code.
primitive:module:
Create named primitive.
primitive:module:error:
Create named primitive with optional error code.
primitivePragmaSelectors
queryUndefined
removeUnusedTemps
Scan for unused temp names, and prompt the user about the prospect of removing each one found
silent
startOfNextToken
Return starting position in source of next token.
statements:innerBlock:
statements:innerBlock:blockNode:
give initial comment to block, since others trail statements
substituteSelector:wordIntervals:
Substitute the correctSelector into the (presuamed interactive) receiver.
substituteVariable:atInterval:
substituteWord:wordInterval:offset:
Substitute the correctSelector into the (presuamed interactive) receiver.
temporaries
[ '|' (variable)* '|' ]
temporariesIn:
[ '|' (variable)* '|' ]
temporaryBlockVariablesFor:
Scan and answer temporary block variables.
variable
warnUser
warns
self new warns
ParserNotification
A ParserNotification is xxxxxxxxx.
Instance Variables
name: <Object>
name
- xxxxx
defaultAction
No action is taken. The value nil is returned as the value of the message that signaled the exception.
name:
openMenuIn:
setName:
RemoteTempVectorNode
I am a node for a vector of remote temps, created to share temps between closures when those temps are written to in closures other than their defining ones.
accept:
addRemoteTemp:encoder:
emitCodeForIndexOf:stack:encoder:
emitCodeForLoadFor:stack:encoder:
emitCodeForStoreInto:stack:encoder:
emitCodeForStorePopInto:stack:encoder:
emitCodeForValueOf:stack:encoder:
isIndirectTempVector
nodeToInitialize:
printDefinitionForClosureAnalysisOn:
referenceScopesAndIndicesDo:
Evaluate aBinaryBlock with all read or write scopes and locations.
This is used to copy the reference information into RemoteTempVectorNodes
remoteTemps
remoteTemps:
scope
Answer scope of temporary variables.
Currently only the following distinctions are made:
0 outer level: args and user-declared temps
1 block args and doLimiT temps
-1 a block temp that is no longer active
-2 a block temp that held limit of to:do:
-3 an indirect temp vector
sizeCodeForIndexOf:encoder:
sizeCodeForLoadFor:encoder:
sizeCodeForStoreInto:encoder:
sizeCodeForStorePopInto:encoder:
sizeCodeForValueOf:encoder:
ReparseAfterSourceEditing
A ReparseAfterSourceEditing is xxxxxxxxx.
Instance Variables
ReturnNode
I represent an expression of the form ^expr.
accept:
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
asReturnNode
code
emitCodeForReturn:encoder:
emitCodeForValue:encoder:
emitForReturn:on:
emitForValue:on:
expr
expr:
expr:encoder:sourceRange:
isReturnSelf
isSpecialConstant
isVariableReference
printOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
sizeCodeForReturn:
sizeCodeForValue:
sizeForReturn:
sizeForValue:
Scanner
I scan a string or text, picking out Smalltalk syntactic tokens. I look one character ahead. I put each token found into the instance variable, token, and its type (a Symbol) into the variable, tokenType. At the end of the input stream, I pretend to see an endless sequence of special characters called doits.
advance
checkpoint
Return a copy of all changeable state. See revertToCheckpoint:
errorMultibyteCharacter
initScanner
initScannerForTokenization
Use a version of typeTable that doesn't raise xIllegal when enocuntering an _
initialize
Subclasses should redefine this method to perform initializations on instance creation
inviolateInstanceVariableNames
isLegalInstVarName:
isLiteralSymbol:
new
nextLiteral
Same as advance, but -4 comes back as a number instead of two tokens
notify:
Refer to the comment in Object|notify:.
offEnd:
Parser overrides this
scan:
Bind the input stream, fill the character buffers and first token buffer.
scanAllTokenPositionsInto:
Evaluate aBlock with the start and end positions of all separate non-white-space tokens, including comments.
scanFieldNames:
Answer an Array of Strings that are the identifiers in the input string,
stringOrArray. If passed an Array, just answer with that Array, i.e.,
assume it has already been scanned.
scanLitByte
scanLitVec
scanLitWord
Accumulate keywords and asSymbol the result.
scanMessageParts:
Return an array of the form (comment keyword comment arg comment keyword comment arg comment) for the message pattern of this method. Courtesy of Ted Kaehler, June 1999
scanStringStruct
scanStringStruct:
The input is a string whose elements are identifiers and parenthesized
groups of identifiers. Answer an array reflecting that structure, representing
each identifier by an uninterned string.
scanToken
scanTokenPositionsIn:into:
Evaluate aBlock with the start and end positions of all separate non-white-space tokens, including comments, in textOrString.
scanTokens:
Answer an Array that has been tokenized as though the input text,
textOrString, had appeared between the array delimitors #( and ) in a
Smalltalk literal expression.
step
typeTableAt:
typedScanTokens:
Answer an Array that has been tokenized with literals mapped to literals,
special characters mapped to symbols and variable names and keywords
to strings. This methiod accepts _ (underscore) as an assignment token
irrespective of whether the system prefers := as the assignment token.
wellFormedInstanceVariableNameFrom:
xBinary
xColon
Allow := for assignment
xDelimiter
Ignore blanks, etc.
xDigit
Form a number.
xDollar
Form a Character literal.
xDoubleQuote
Collect a comment.
xIllegal
An illegal character was encountered
xLetter
Form a word or keyword.
xLitQuote
Symbols and vectors: #(1 (4 5) 2 3) #ifTrue:ifFalse: #'abc'.
xSingleQuote
String.
xUnderscore
xUnderscoreForTokenization
SelectorNode
I am a parse tree leaf representing a selector.
accept:
emit:args:on:
emit:args:on:super:
emitCode:args:encoder:
emitCode:args:encoder:super:
emitCodeForEffect:encoder:
emitCodeForValue:encoder:
emitForEffect:on:
emitForValue:on:
isForFFICall
isPvtSelector
Answer if this selector node is a private message selector.
key:
This is for printing of FFI selectors.
name:key:index:type:
For compatibility with Encoder>>name:key:class:type:set:
printAsFFICallWithArguments:on:indent:
printOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
reserve:
If this is a yet unused literal of type -code, reserve it.
size:args:super:
sizeCode:args:super:
sizeCodeForEffect:
sizeCodeForValue:
sizeForEffect:
sizeForValue:
TempVariableNode
I am a parse tree leaf representing a temporary variable
accept:
addReadWithin:at:
<BlockNode>
addWriteWithin:at:
<BlockNode>
analyseClosure:
<MethodNode>
analyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
assignmentCheck:at:
For messageNodes masquerading as variables for the debugger.
For now we let this through - ie we allow stores ev
into args. Should check against numArgs, though.
beBlockArg
beMethodArg
beingAssignedToAnalyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
cleanUpForRegeneration
definingScope
definingScope:
<BlockNode>
emitCodeForLoad:encoder:
Do nothing
emitCodeForStore:encoder:
emitCodeForStorePop:encoder:
emitCodeForValue:encoder:
index:
For renumbering temps in the closure compiler.
isArg
isBlockArg
isDefinedWithinBlockExtent:
isIndirectTempVector
isMethodArg
isReferencedWithinBlockExtent:
isRemote
isTemp
isUndefTemp
isUnusedTemp
name:index:type:scope:
Only used for initting temporary variables
nowHasDef
Ignored in all but VariableNode
nowHasRef
Ignored in all but VariableNode
printDefinitionForClosureAnalysisOn:
printOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
referenceScopesAndIndicesDo:
Evaluate aBinaryBlock with all read or write scopes and locations.
This is used to copy the reference information into RemoteTempVectorNodes
remoteNode
remoteNode:
scope
Answer scope of temporary variables.
Currently only the following distinctions are made:
0 outer level: args and user-declared temps
1 block args and doLimiT temps
-1 a block temp that is no longer active
-2 a block temp that held limit of to:do:
scope:
Note scope of temporary variables.
Currently only the following distinctions are made:
0 outer level: args and user-declared temps
1 block args and doLimiT temps
-1 a block temp that is no longer active
-2 a block temp that held limit of to:do:
sizeCodeForLoad:
Default is to do nothing.
Subclasses may need to override.
sizeCodeForStore:
sizeCodeForStorePop:
sizeCodeForValue:
UndeclaredVariable
An UndeclaredVariable is xxxxxxxxx.
Instance Variables
interval: <Object>
parser: <Object>
interval
- xxxxx
parser
- xxxxx
openMenuIn:
setParser:name:range:
signalFor:name:inRange:
UndeclaredVariableReference
An UndeclaredVariableReference is xxxxxxxxx.
Instance Variables
parser: <Object>
varEnd: <Object>
varName: <Object>
varStart: <Object>
parser
- xxxxx
varEnd
- xxxxx
varName
- xxxxx
varStart
- xxxxx
UndeclaredVariableWarning
An UndeclaredVariableWarning is xxxxxxxxx.
Instance Variables
class: <Object>
name: <Object>
selector: <Object>
class
- xxxxx
name
- xxxxx
selector
- xxxxx
defaultAction
The user should be notified of the occurrence of an exceptional occurrence and
given an option of continuing or aborting the computation. The description of the
occurrence should include any text specified as the argument of the #signal: message.
name:selector:class:
UndefinedVariable
An UndefinedVariable is xxxxxxxxx.
Instance Variables
openMenuIn:
UnknownSelector
An UnknownSelector is xxxxxxxxx.
Instance Variables
openMenuIn:
UnusedVariable
An UnusedVariable is xxxxxxxxx.
Instance Variables
openMenuIn:
VariableNode
I am a parse tree leaf representing a variable. Note that my name and key are different for pool variables: the key is the Object Reference.
accept:
asStorableNode:
assignmentCheck:at:
For messageNodes masquerading as variables for the debugger.
For now we let this through - ie we allow stores ev
into args. Should check against numArgs, though.
beingAssignedToAnalyseTempsWithin:rootNode:assignmentPools:
<BlockNode>
canBeSpecialArgument
Can I be an argument of (e.g.) ifTrue:?
currentValueIn:
emitCodeForLoad:encoder:
Do nothing
emitCodeForReturn:encoder:
emitCodeForStore:encoder:
emitCodeForStorePop:encoder:
emitCodeForValue:encoder:
emitForReturn:on:
emitForValue:on:
emitLoad:on:
Do nothing
emitStore:on:
emitStorePop:on:
fieldOffset
Return temp or instVar offset for this variable
index
This code attempts to reconstruct the index from its encoding in code.
initialize
Subclasses should redefine this method to perform initializations on instance creation
isSelfPseudoVariable
Answer if this ParseNode represents the 'self' pseudo-variable.
isVariableNode
isVariableReference
name
Answer a name for the receiver. This is used generically in the title of certain inspectors, such as the referred-to inspector, and specificially by various subsystems. By default, we let the object just print itself out..
name:
Change name
name:index:type:
Only used for initting instVar refs
name:key:code:
Only used for initting std variables, nil, true, false, self, etc.
name:key:index:type:
Only used for initting global (litInd) variables
printOn:indent:
If control gets here, avoid recursion loop.
printWithClosureAnalysisOn:indent:
If control gets here, avoid recursion loop.
returns
sizeCodeForReturn:
sizeCodeForStore:
sizeCodeForStorePop:
sizeCodeForValue:
sizeForReturn:
sizeForStore:
sizeForStorePop:
type
This code attempts to reconstruct the type from its encoding in code.
This allows one to test, for instance, (aNode type = LdInstType).
variableGetterBlockIn: