232 lines
5.5 KiB
Smalltalk
232 lines
5.5 KiB
Smalltalk
|
Class {
|
||
|
#name : 'PPCCodeBlock',
|
||
|
#superclass : 'Object',
|
||
|
#instVars : [
|
||
|
'buffer',
|
||
|
'indentation',
|
||
|
'temporaries'
|
||
|
],
|
||
|
#category : 'PetitCompiler-Compiler-Codegen'
|
||
|
}
|
||
|
|
||
|
{ #category : 'instance creation' }
|
||
|
PPCCodeBlock class >> new [
|
||
|
"return an initialized instance"
|
||
|
|
||
|
^ self basicNew initialize.
|
||
|
]
|
||
|
|
||
|
{ #category : 'adding' }
|
||
|
PPCCodeBlock >> add: string [
|
||
|
self nl.
|
||
|
self codeIndent.
|
||
|
self addOnLine: string.
|
||
|
|
||
|
"Modified: / 01-06-2015 / 22:58:42 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'adding' }
|
||
|
PPCCodeBlock >> addOnLine: string [
|
||
|
buffer nextPutAll: string.
|
||
|
]
|
||
|
|
||
|
{ #category : 'code generation - variables' }
|
||
|
PPCCodeBlock >> allocateTemporaryVariableNamed:preferredName [
|
||
|
"Allocate a new variable with (preferably) given name.
|
||
|
Returns a real variable name that should be used."
|
||
|
|
||
|
(temporaries includes:preferredName) ifFalse:[
|
||
|
temporaries add:preferredName.
|
||
|
^ preferredName
|
||
|
] ifTrue:[
|
||
|
| name |
|
||
|
|
||
|
name := preferredName , '_' , (temporaries size + 1) printString.
|
||
|
temporaries add:name.
|
||
|
^ name
|
||
|
].
|
||
|
|
||
|
"Created: / 23-04-2015 / 17:37:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
"Modified: / 01-06-2015 / 21:03:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'code generation' }
|
||
|
PPCCodeBlock >> code: aStringOrBlockOrRBParseNode [
|
||
|
self codeNl.
|
||
|
self codeOnLine: aStringOrBlockOrRBParseNode
|
||
|
|
||
|
"Created: / 01-06-2015 / 21:07:10 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
"Modified: / 03-06-2015 / 05:52:39 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'code generation' }
|
||
|
PPCCodeBlock >> codeIndent [
|
||
|
self codeIndent:indentation
|
||
|
|
||
|
"Created: / 01-06-2015 / 22:58:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'code generation' }
|
||
|
PPCCodeBlock >> codeIndent: level [
|
||
|
((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
|
||
|
level * 4 timesRepeat: [ buffer nextPut: Character space ].
|
||
|
] ifFalse:[
|
||
|
level timesRepeat: [ buffer nextPut: Character tab ].
|
||
|
].
|
||
|
|
||
|
"Created: / 01-06-2015 / 22:58:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'code generation' }
|
||
|
PPCCodeBlock >> codeNl [
|
||
|
self add: ''.
|
||
|
]
|
||
|
|
||
|
{ #category : 'printing and storing' }
|
||
|
PPCCodeBlock >> codeOn: aStream [
|
||
|
"Dumps generated code on given stream"
|
||
|
|
||
|
temporaries notEmpty ifTrue:[
|
||
|
((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
|
||
|
indentation * 4 timesRepeat: [ aStream nextPut: Character space ].
|
||
|
] ifFalse:[
|
||
|
indentation timesRepeat: [ aStream nextPut: Character tab ].
|
||
|
].
|
||
|
aStream nextPut: $|.
|
||
|
temporaries do:[:e | aStream space; nextPutAll: e ].
|
||
|
aStream space.
|
||
|
aStream nextPut: $|.
|
||
|
self nl.
|
||
|
"In Smalltalk/X, there should be a blank line after temporaries"
|
||
|
((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
|
||
|
self nl.
|
||
|
].
|
||
|
].
|
||
|
aStream nextPutAll: buffer contents
|
||
|
|
||
|
"Created: / 01-06-2015 / 21:26:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'code generation' }
|
||
|
PPCCodeBlock >> codeOnLine: aStringOrBlockOrRBParseNode [
|
||
|
aStringOrBlockOrRBParseNode isString ifTrue:[
|
||
|
self emitCodeAsString: aStringOrBlockOrRBParseNode
|
||
|
] ifFalse:[
|
||
|
(aStringOrBlockOrRBParseNode isKindOf: RBProgramNode) ifTrue:[
|
||
|
self emitCodeAsRBNode: aStringOrBlockOrRBParseNode.
|
||
|
] ifFalse:[
|
||
|
self emitCodeAsBlock: aStringOrBlockOrRBParseNode
|
||
|
].
|
||
|
].
|
||
|
]
|
||
|
|
||
|
{ #category : 'indentation' }
|
||
|
PPCCodeBlock >> dedent [
|
||
|
indentation := indentation - 1
|
||
|
]
|
||
|
|
||
|
{ #category : 'private' }
|
||
|
PPCCodeBlock >> emitCodeAsBlock: aBlock [
|
||
|
aBlock value
|
||
|
|
||
|
]
|
||
|
|
||
|
{ #category : 'private' }
|
||
|
PPCCodeBlock >> emitCodeAsRBNode: anRBNode [
|
||
|
anRBNode isSequence ifTrue:[
|
||
|
anRBNode temporaries do:[:e |
|
||
|
(temporaries includes: e name) ifFalse:[
|
||
|
temporaries add: e name
|
||
|
].
|
||
|
].
|
||
|
anRBNode statements do:[:e|
|
||
|
self add: (self formatRBNode: e);
|
||
|
addOnLine: '.'.
|
||
|
].
|
||
|
] ifFalse:[
|
||
|
buffer nextPutAll: anRBNode formattedCode.
|
||
|
].
|
||
|
|
||
|
|
||
|
|
||
|
]
|
||
|
|
||
|
{ #category : 'private' }
|
||
|
PPCCodeBlock >> emitCodeAsString: aString [
|
||
|
self addOnLine: aString
|
||
|
|
||
|
]
|
||
|
|
||
|
{ #category : 'private' }
|
||
|
PPCCodeBlock >> formatRBNode: anRBNode [
|
||
|
| formatter |
|
||
|
formatter := anRBNode formatterClass new.
|
||
|
formatter indent: indentation.
|
||
|
^ formatter format: anRBNode
|
||
|
]
|
||
|
|
||
|
{ #category : 'indentation' }
|
||
|
PPCCodeBlock >> indent [
|
||
|
indentation := indentation + 1
|
||
|
]
|
||
|
|
||
|
{ #category : 'indentation' }
|
||
|
PPCCodeBlock >> indentationLevel [
|
||
|
^ indentation
|
||
|
]
|
||
|
|
||
|
{ #category : 'indentation' }
|
||
|
PPCCodeBlock >> indentationLevel: value [
|
||
|
indentation := value
|
||
|
]
|
||
|
|
||
|
{ #category : 'initialization' }
|
||
|
PPCCodeBlock >> initialize [
|
||
|
"Invoked when a new instance is created."
|
||
|
|
||
|
buffer := String new writeStream.
|
||
|
indentation := 1.
|
||
|
temporaries := OrderedCollection new.
|
||
|
|
||
|
"Modified: / 01-06-2015 / 20:57:08 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
"Modified (comment): / 18-06-2015 / 06:04:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|
||
|
|
||
|
{ #category : 'indent-dedent' }
|
||
|
PPCCodeBlock >> nl [
|
||
|
^ buffer nextPut: Character cr
|
||
|
]
|
||
|
|
||
|
{ #category : 'printing and storing' }
|
||
|
PPCCodeBlock >> sourceOn:aStream [
|
||
|
"Dumps generated code on given stream"
|
||
|
|
||
|
temporaries notEmpty ifTrue:[
|
||
|
((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
|
||
|
indentation * 4 timesRepeat:[
|
||
|
aStream nextPut:Character space
|
||
|
].
|
||
|
] ifFalse:[
|
||
|
indentation timesRepeat:[
|
||
|
aStream nextPut:Character tab
|
||
|
].
|
||
|
].
|
||
|
aStream nextPut:$|.
|
||
|
temporaries do:[:e |
|
||
|
aStream
|
||
|
space;
|
||
|
nextPutAll:e
|
||
|
].
|
||
|
aStream space.
|
||
|
aStream nextPut:$|.
|
||
|
self nl.
|
||
|
"In Smalltalk/X, there should be a blank line after temporaries"
|
||
|
((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[
|
||
|
self nl.
|
||
|
].
|
||
|
].
|
||
|
aStream nextPutAll:buffer contents
|
||
|
|
||
|
"Created: / 01-06-2015 / 21:26:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
|
||
|
]
|