@@ -57,169 +57,171 @@ def emit_to(out: CWriter, tkn_iter: Iterator[Token], end: str) -> None:
57
57
parens -= 1
58
58
out .emit (tkn )
59
59
60
+ ReplacementFunctionType = Callable [
61
+ [Token , Iterator [Token ], Uop , Stack , Instruction | None ], None
62
+ ]
60
63
61
- def replace_deopt (
62
- out : CWriter ,
63
- tkn : Token ,
64
- tkn_iter : Iterator [Token ],
65
- uop : Uop ,
66
- unused : Stack ,
67
- inst : Instruction | None ,
68
- ) -> None :
69
- out .emit_at ("DEOPT_IF" , tkn )
70
- out .emit (next (tkn_iter ))
71
- emit_to (out , tkn_iter , "RPAREN" )
72
- next (tkn_iter ) # Semi colon
73
- out .emit (", " )
74
- assert inst is not None
75
- assert inst .family is not None
76
- out .emit (inst .family .name )
77
- out .emit (");\n " )
78
-
64
+ class Emitter :
79
65
80
- def replace_error (
81
- out : CWriter ,
82
- tkn : Token ,
83
- tkn_iter : Iterator [Token ],
84
- uop : Uop ,
85
- stack : Stack ,
86
- inst : Instruction | None ,
87
- ) -> None :
88
- out .emit_at ("if " , tkn )
89
- out .emit (next (tkn_iter ))
90
- emit_to (out , tkn_iter , "COMMA" )
91
- label = next (tkn_iter ).text
92
- next (tkn_iter ) # RPAREN
93
- next (tkn_iter ) # Semi colon
94
- out .emit (") " )
95
- c_offset = stack .peek_offset ()
96
- try :
97
- offset = - int (c_offset )
98
- except ValueError :
99
- offset = - 1
100
- if offset > 0 :
101
- out .emit (f"goto pop_{ offset } _" )
102
- out .emit (label )
103
- out .emit (";\n " )
104
- elif offset == 0 :
105
- out .emit ("goto " )
106
- out .emit (label )
107
- out .emit (";\n " )
108
- else :
109
- out .emit ("{\n " )
110
- stack .flush_locally (out )
111
- out .emit ("goto " )
112
- out .emit (label )
113
- out .emit (";\n " )
114
- out .emit ("}\n " )
66
+ out : CWriter
67
+ _replacers : dict [str , ReplacementFunctionType ]
115
68
69
+ def __init__ (self , out : CWriter ):
70
+ self ._replacers = {
71
+ "EXIT_IF" : self .exit_if ,
72
+ "DEOPT_IF" : self .deopt_if ,
73
+ "ERROR_IF" : self .error_if ,
74
+ "ERROR_NO_POP" : self .error_no_pop ,
75
+ "DECREF_INPUTS" : self .decref_inputs ,
76
+ "CHECK_EVAL_BREAKER" : self .check_eval_breaker ,
77
+ "SYNC_SP" : self .sync_sp ,
78
+ }
79
+ self .out = out
116
80
117
- def replace_error_no_pop (
118
- out : CWriter ,
119
- tkn : Token ,
120
- tkn_iter : Iterator [Token ],
121
- uop : Uop ,
122
- stack : Stack ,
123
- inst : Instruction | None ,
124
- ) -> None :
125
- next (tkn_iter ) # LPAREN
126
- next (tkn_iter ) # RPAREN
127
- next (tkn_iter ) # Semi colon
128
- out .emit_at ("goto error;" , tkn )
81
+ def deopt_if (
82
+ self ,
83
+ tkn : Token ,
84
+ tkn_iter : Iterator [Token ],
85
+ uop : Uop ,
86
+ unused : Stack ,
87
+ inst : Instruction | None ,
88
+ ) -> None :
89
+ self .out .emit_at ("DEOPT_IF" , tkn )
90
+ self .out .emit (next (tkn_iter ))
91
+ emit_to (self .out , tkn_iter , "RPAREN" )
92
+ next (tkn_iter ) # Semi colon
93
+ self .out .emit (", " )
94
+ assert inst is not None
95
+ assert inst .family is not None
96
+ self .out .emit (inst .family .name )
97
+ self .out .emit (");\n " )
129
98
99
+ exit_if = deopt_if
130
100
131
- def replace_decrefs (
132
- out : CWriter ,
133
- tkn : Token ,
134
- tkn_iter : Iterator [Token ],
135
- uop : Uop ,
136
- stack : Stack ,
137
- inst : Instruction | None ,
138
- ) -> None :
139
- next (tkn_iter )
140
- next (tkn_iter )
141
- next (tkn_iter )
142
- out .emit_at ("" , tkn )
143
- for var in uop .stack .inputs :
144
- if var .name == "unused" or var .name == "null" or var .peek :
145
- continue
146
- if var .size :
147
- out .emit (f"for (int _i = { var .size } ; --_i >= 0;) {{\n " )
148
- out .emit (f"PyStackRef_CLOSE({ var .name } [_i]);\n " )
149
- out .emit ("}\n " )
150
- elif var .condition :
151
- if var .condition == "1" :
152
- out .emit (f"PyStackRef_CLOSE({ var .name } );\n " )
153
- elif var .condition != "0" :
154
- out .emit (f"PyStackRef_XCLOSE({ var .name } );\n " )
101
+ def error_if (
102
+ self ,
103
+ tkn : Token ,
104
+ tkn_iter : Iterator [Token ],
105
+ uop : Uop ,
106
+ stack : Stack ,
107
+ inst : Instruction | None ,
108
+ ) -> None :
109
+ self .out .emit_at ("if " , tkn )
110
+ self .out .emit (next (tkn_iter ))
111
+ emit_to (self .out , tkn_iter , "COMMA" )
112
+ label = next (tkn_iter ).text
113
+ next (tkn_iter ) # RPAREN
114
+ next (tkn_iter ) # Semi colon
115
+ self .out .emit (") " )
116
+ c_offset = stack .peek_offset ()
117
+ try :
118
+ offset = - int (c_offset )
119
+ except ValueError :
120
+ offset = - 1
121
+ if offset > 0 :
122
+ self .out .emit (f"goto pop_{ offset } _" )
123
+ self .out .emit (label )
124
+ self .out .emit (";\n " )
125
+ elif offset == 0 :
126
+ self .out .emit ("goto " )
127
+ self .out .emit (label )
128
+ self .out .emit (";\n " )
155
129
else :
156
- out .emit (f"PyStackRef_CLOSE({ var .name } );\n " )
130
+ self .out .emit ("{\n " )
131
+ stack .flush_locally (self .out )
132
+ self .out .emit ("goto " )
133
+ self .out .emit (label )
134
+ self .out .emit (";\n " )
135
+ self .out .emit ("}\n " )
157
136
137
+ def error_no_pop (
138
+ self ,
139
+ tkn : Token ,
140
+ tkn_iter : Iterator [Token ],
141
+ uop : Uop ,
142
+ stack : Stack ,
143
+ inst : Instruction | None ,
144
+ ) -> None :
145
+ next (tkn_iter ) # LPAREN
146
+ next (tkn_iter ) # RPAREN
147
+ next (tkn_iter ) # Semi colon
148
+ self .out .emit_at ("goto error;" , tkn )
158
149
159
- def replace_sync_sp (
160
- out : CWriter ,
161
- tkn : Token ,
162
- tkn_iter : Iterator [Token ],
163
- uop : Uop ,
164
- stack : Stack ,
165
- inst : Instruction | None ,
166
- ) -> None :
167
- next (tkn_iter )
168
- next (tkn_iter )
169
- next (tkn_iter )
170
- stack .flush (out )
171
-
150
+ def decref_inputs (
151
+ self ,
152
+ tkn : Token ,
153
+ tkn_iter : Iterator [Token ],
154
+ uop : Uop ,
155
+ stack : Stack ,
156
+ inst : Instruction | None ,
157
+ ) -> None :
158
+ next (tkn_iter )
159
+ next (tkn_iter )
160
+ next (tkn_iter )
161
+ self .out .emit_at ("" , tkn )
162
+ for var in uop .stack .inputs :
163
+ if var .name == "unused" or var .name == "null" or var .peek :
164
+ continue
165
+ if var .size :
166
+ self .out .emit (f"for (int _i = { var .size } ; --_i >= 0;) {{\n " )
167
+ self .out .emit (f"PyStackRef_CLOSE({ var .name } [_i]);\n " )
168
+ self .out .emit ("}\n " )
169
+ elif var .condition :
170
+ if var .condition == "1" :
171
+ self .out .emit (f"PyStackRef_CLOSE({ var .name } );\n " )
172
+ elif var .condition != "0" :
173
+ self .out .emit (f"PyStackRef_XCLOSE({ var .name } );\n " )
174
+ else :
175
+ self .out .emit (f"PyStackRef_CLOSE({ var .name } );\n " )
172
176
173
- def replace_check_eval_breaker (
174
- out : CWriter ,
175
- tkn : Token ,
176
- tkn_iter : Iterator [Token ],
177
- uop : Uop ,
178
- stack : Stack ,
179
- inst : Instruction | None ,
180
- ) -> None :
181
- next (tkn_iter )
182
- next (tkn_iter )
183
- next (tkn_iter )
184
- if not uop .properties .ends_with_eval_breaker :
185
- out .emit_at ("CHECK_EVAL_BREAKER();" , tkn )
186
177
178
+ def sync_sp (
179
+ self ,
180
+ tkn : Token ,
181
+ tkn_iter : Iterator [Token ],
182
+ uop : Uop ,
183
+ stack : Stack ,
184
+ inst : Instruction | None ,
185
+ ) -> None :
186
+ next (tkn_iter )
187
+ next (tkn_iter )
188
+ next (tkn_iter )
189
+ stack .flush (self .out )
187
190
188
- REPLACEMENT_FUNCTIONS = {
189
- "EXIT_IF" : replace_deopt ,
190
- "DEOPT_IF" : replace_deopt ,
191
- "ERROR_IF" : replace_error ,
192
- "ERROR_NO_POP" : replace_error_no_pop ,
193
- "DECREF_INPUTS" : replace_decrefs ,
194
- "CHECK_EVAL_BREAKER" : replace_check_eval_breaker ,
195
- "SYNC_SP" : replace_sync_sp ,
196
- }
197
-
198
- ReplacementFunctionType = Callable [
199
- [CWriter , Token , Iterator [Token ], Uop , Stack , Instruction | None ], None
200
- ]
201
191
192
+ def check_eval_breaker (
193
+ self ,
194
+ tkn : Token ,
195
+ tkn_iter : Iterator [Token ],
196
+ uop : Uop ,
197
+ stack : Stack ,
198
+ inst : Instruction | None ,
199
+ ) -> None :
200
+ next (tkn_iter )
201
+ next (tkn_iter )
202
+ next (tkn_iter )
203
+ if not uop .properties .ends_with_eval_breaker :
204
+ self .out .emit_at ("CHECK_EVAL_BREAKER();" , tkn )
202
205
203
- def emit_tokens (
204
- out : CWriter ,
205
- uop : Uop ,
206
- stack : Stack ,
207
- inst : Instruction | None ,
208
- replacement_functions : Mapping [
209
- str , ReplacementFunctionType
210
- ] = REPLACEMENT_FUNCTIONS ,
211
- ) -> None :
212
- tkns = uop .body [1 :- 1 ]
213
- if not tkns :
214
- return
215
- tkn_iter = iter (tkns )
216
- out .start_line ()
217
- for tkn in tkn_iter :
218
- if tkn .kind == "IDENTIFIER" and tkn .text in replacement_functions :
219
- replacement_functions [tkn .text ](out , tkn , tkn_iter , uop , stack , inst )
220
- else :
221
- out .emit (tkn )
206
+ def emit_tokens (
207
+ self ,
208
+ uop : Uop ,
209
+ stack : Stack ,
210
+ inst : Instruction | None ,
211
+ ) -> None :
212
+ tkns = uop .body [1 :- 1 ]
213
+ if not tkns :
214
+ return
215
+ tkn_iter = iter (tkns )
216
+ self .out .start_line ()
217
+ for tkn in tkn_iter :
218
+ if tkn .kind == "IDENTIFIER" and tkn .text in self ._replacers :
219
+ self ._replacers [tkn .text ](tkn , tkn_iter , uop , stack , inst )
220
+ else :
221
+ self .out .emit (tkn )
222
222
223
+ def emit (self , txt : str | Token ) -> None :
224
+ self .out .emit (txt )
223
225
224
226
def cflags (p : Properties ) -> str :
225
227
flags : list [str ] = []
0 commit comments