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 " ] { #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 " "Modified: / 01-06-2015 / 21:03:39 / Jan Vrany " ] { #category : 'code generation' } PPCCodeBlock >> code: aStringOrBlockOrRBParseNode [ self codeNl. self codeOnLine: aStringOrBlockOrRBParseNode "Created: / 01-06-2015 / 21:07:10 / Jan Vrany " "Modified: / 03-06-2015 / 05:52:39 / Jan Vrany " ] { #category : 'code generation' } PPCCodeBlock >> codeIndent [ self codeIndent:indentation "Created: / 01-06-2015 / 22:58:00 / Jan Vrany " ] { #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 " ] { #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 " ] { #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 " "Modified (comment): / 18-06-2015 / 06:04:21 / Jan Vrany " ] { #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 " ]