|
1 "{ Package: 'stx:goodies/petitparser/compiler' }" |
|
2 |
|
3 "{ NameSpace: Smalltalk }" |
|
4 |
|
5 Object subclass:#PPCCodeBlock |
|
6 instanceVariableNames:'buffer indentation temporaries' |
|
7 classVariableNames:'' |
|
8 poolDictionaries:'' |
|
9 category:'PetitCompiler-Compiler-Codegen' |
|
10 ! |
|
11 |
|
12 !PPCCodeBlock class methodsFor:'instance creation'! |
|
13 |
|
14 new |
|
15 "return an initialized instance" |
|
16 |
|
17 ^ self basicNew initialize. |
|
18 ! ! |
|
19 |
|
20 !PPCCodeBlock methodsFor:'as yet unclassified'! |
|
21 |
|
22 add: string |
|
23 self nl. |
|
24 self codeIndent. |
|
25 self addOnLine: string. |
|
26 |
|
27 "Modified: / 01-06-2015 / 22:58:42 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
28 ! |
|
29 |
|
30 addOnLine: string |
|
31 buffer nextPutAll: string. |
|
32 ! |
|
33 |
|
34 nl |
|
35 ^ buffer nextPut: Character cr |
|
36 ! ! |
|
37 |
|
38 !PPCCodeBlock methodsFor:'code generation'! |
|
39 |
|
40 code: aStringOrBlockOrRBParseNode |
|
41 aStringOrBlockOrRBParseNode isString ifTrue:[ |
|
42 self emitCodeAsString: aStringOrBlockOrRBParseNode |
|
43 ] ifFalse:[ |
|
44 (aStringOrBlockOrRBParseNode isKindOf: RBProgramNode) ifTrue:[ |
|
45 self emitCodeAsRBNode: aStringOrBlockOrRBParseNode. |
|
46 ] ifFalse:[ |
|
47 self emitCodeAsBlock: aStringOrBlockOrRBParseNode |
|
48 ]. |
|
49 ]. |
|
50 |
|
51 "Created: / 01-06-2015 / 21:07:10 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
52 "Modified: / 03-06-2015 / 05:52:39 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
53 ! |
|
54 |
|
55 codeIndent |
|
56 self codeIndent:indentation |
|
57 |
|
58 "Created: / 01-06-2015 / 22:58:00 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
59 ! |
|
60 |
|
61 codeIndent: level |
|
62 ((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[ |
|
63 level * 4 timesRepeat: [ buffer nextPut: Character space ]. |
|
64 ] ifFalse:[ |
|
65 level timesRepeat: [ buffer nextPut: Character tab ]. |
|
66 ]. |
|
67 |
|
68 "Created: / 01-06-2015 / 22:58:07 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
69 ! ! |
|
70 |
|
71 !PPCCodeBlock methodsFor:'code generation - variables'! |
|
72 |
|
73 allocateTemporaryVariableNamed:preferredName |
|
74 "Allocate a new variable with (preferably) given name. |
|
75 Returns a real variable name that should be used." |
|
76 |
|
77 (temporaries includes:preferredName) ifFalse:[ |
|
78 temporaries add:preferredName. |
|
79 ^ preferredName |
|
80 ] ifTrue:[ |
|
81 | name | |
|
82 |
|
83 name := preferredName , '_' , (temporaries size + 1) printString. |
|
84 temporaries add:name. |
|
85 ^ name |
|
86 ]. |
|
87 |
|
88 "Created: / 23-04-2015 / 17:37:55 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
89 "Modified: / 01-06-2015 / 21:03:39 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
90 ! ! |
|
91 |
|
92 !PPCCodeBlock methodsFor:'indentation'! |
|
93 |
|
94 dedent |
|
95 indentation := indentation - 1 |
|
96 ! |
|
97 |
|
98 indent |
|
99 indentation := indentation + 1 |
|
100 ! |
|
101 |
|
102 indentationLevel |
|
103 ^ indentation |
|
104 ! |
|
105 |
|
106 indentationLevel: value |
|
107 indentation := value |
|
108 ! ! |
|
109 |
|
110 !PPCCodeBlock methodsFor:'initialization'! |
|
111 |
|
112 initialize |
|
113 "Invoked when a new instance is created." |
|
114 |
|
115 buffer := String new writeStream. |
|
116 indentation := 1. |
|
117 temporaries := OrderedCollection new. |
|
118 |
|
119 "Modified: / 01-06-2015 / 20:57:08 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
120 "Modified (comment): / 18-06-2015 / 06:04:21 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
121 ! ! |
|
122 |
|
123 !PPCCodeBlock methodsFor:'printing and storing'! |
|
124 |
|
125 codeOn: aStream |
|
126 "Dumps generated code on given stream" |
|
127 |
|
128 temporaries notEmpty ifTrue:[ |
|
129 ((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[ |
|
130 indentation * 4 timesRepeat: [ aStream nextPut: Character space ]. |
|
131 ] ifFalse:[ |
|
132 indentation timesRepeat: [ aStream nextPut: Character tab ]. |
|
133 ]. |
|
134 aStream nextPut: $|. |
|
135 temporaries do:[:e | aStream space; nextPutAll: e ]. |
|
136 aStream space. |
|
137 aStream nextPut: $|. |
|
138 self nl. |
|
139 "In Smalltalk/X, there should be a blank line after temporaries" |
|
140 ((Smalltalk respondsTo:#isSmalltalkX) and:[ Smalltalk isSmalltalkX ]) ifTrue:[ |
|
141 self nl. |
|
142 ]. |
|
143 ]. |
|
144 aStream nextPutAll: buffer contents |
|
145 |
|
146 "Created: / 01-06-2015 / 21:26:03 / Jan Vrany <jan.vrany@fit.cvut.cz>" |
|
147 ! ! |
|
148 |
|
149 !PPCCodeBlock methodsFor:'private'! |
|
150 |
|
151 emitCodeAsBlock: aBlock |
|
152 aBlock value |
|
153 ! |
|
154 |
|
155 emitCodeAsRBNode: anRBNode |
|
156 anRBNode isSequence ifTrue:[ |
|
157 anRBNode temporaries do:[:e | |
|
158 (temporaries includes: e name) ifFalse:[ |
|
159 temporaries add: e name |
|
160 ]. |
|
161 ]. |
|
162 anRBNode statements do:[:e| |
|
163 self add: (self formatRBNode: e); |
|
164 addOnLine: '.'. |
|
165 ]. |
|
166 ] ifFalse:[ |
|
167 buffer nextPutAll: anRBNode formattedCode. |
|
168 ]. |
|
169 |
|
170 ! |
|
171 |
|
172 emitCodeAsString: aString |
|
173 buffer nextPutAll: aString |
|
174 ! |
|
175 |
|
176 formatRBNode: anRBNode |
|
177 | formatter | |
|
178 formatter := anRBNode formatterClass new. |
|
179 formatter indent: indentation. |
|
180 ^ formatter format: anRBNode |
|
181 ! ! |
|
182 |