@@ -57,169 +57,171 @@ def emit_to(out: CWriter, tkn_iter: Iterator[Token], end: str) -> None:
5757 parens -= 1
5858 out .emit (tkn )
5959
60+ ReplacementFunctionType = Callable [
61+ [Token , Iterator [Token ], Uop , Stack , Instruction | None ], None
62+ ]
6063
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 :
7965
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 ]
11568
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
11680
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 " )
12998
99+ exit_if = deopt_if
130100
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 " )
155129 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 " )
157136
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 )
158149
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 " )
172176
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 )
186177
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 )
187190
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- ]
201191
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 )
202205
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 )
222222
223+ def emit (self , txt : str | Token ) -> None :
224+ self .out .emit (txt )
223225
224226def cflags (p : Properties ) -> str :
225227 flags : list [str ] = []
0 commit comments