@@ -49,47 +49,26 @@ impl<'a> Code<'a> {
4949 fn lower_statement ( & mut self , stmnt : & Statement ) {
5050 match stmnt {
5151 Statement :: If { condition, then_body, else_body } => {
52- let mut state = RegsState :: new ( self ) ;
53- let condition = self . lower_expr ( condition) ;
54- let label_then = self . following_instr ( 1 ) ;
55- let if_label = self . bc . emit ( Instruction :: Branch ( (
56- condition. to_mi ( ) ,
57- label_then,
58- Label ( 0 ) ,
59- ) ) ) ;
60- condition. free ( self ) ;
61- self . lower_body ( then_body) ;
62- let next = self . following_instr ( 0 ) ;
63- self . bc . nth ( if_label) . set_label ( next) ;
52+ let state = RegsState :: new ( self ) ;
53+ let ( if_label, _) = self . emit_branch ( condition, |this| this. lower_body ( then_body) ) ;
6454
6555 if let Some ( else_body) = else_body {
66- state. reg_pointer =
67- state. reg_pointer . checked_add ( 1 ) . expect ( "register overflow" ) ;
68- self . bc . nth ( if_label) . push_start_label ( ) ;
69- let end_label = self . bc . emit ( Instruction :: Jump ( Label ( 0 ) ) ) ;
70- state. scope_hwm ( self , |c| c. lower_body ( else_body) ) ;
71- let next = self . following_instr ( 0 ) ;
72- self . bc . nth ( end_label) . set_label ( next) ;
56+ self . bc . nth ( if_label) . push_end_label ( ) ;
57+ self . emit_jump ( |this| state. scope_hwm ( this, |this| this. lower_body ( else_body) ) ) ;
7358 }
7459 }
7560 Statement :: While { condition, then_body } => {
7661 let cond_label = self . following_instr ( 0 ) ;
77- let condition = self . lower_expr ( condition) ;
78- let while_label = self . bc . emit ( Instruction :: Branch ( (
79- condition. to_mi ( ) ,
80- self . following_instr ( 1 ) ,
81- Label ( 0 ) ,
82- ) ) ) ;
83- condition. free ( self ) ;
84- self . lower_body ( then_body) ;
85- self . bc . emit ( Instruction :: Jump ( cond_label) ) ;
86- let next = self . following_instr ( 0 ) ;
87- self . bc . nth ( while_label) . set_label ( next) ;
62+ self . emit_branch ( condition, |this| {
63+ this. lower_body ( then_body) ;
64+ this. bc . emit ( Instruction :: Jump ( cond_label) ) ;
65+ } ) ;
8866 }
8967 Statement :: DoWhile { then_body, condition } => {
9068 let do_label = self . following_instr ( 0 ) ;
9169 self . lower_body ( then_body) ;
9270 let condition = self . lower_expr ( condition) ;
71+
9372 self . bc . emit ( Instruction :: Branch ( (
9473 condition. to_mi ( ) ,
9574 do_label,
@@ -99,39 +78,28 @@ impl<'a> Code<'a> {
9978 }
10079 Statement :: For { init, condition, update, body } => {
10180 if let Some ( SimpleStatement :: Expression ( expr) ) = init {
102- let value = self . lower_expr ( expr) ;
103- value. free ( self ) ;
81+ self . lower_expr ( expr) . free ( self ) ;
10482 }
83+
10584 let cond_label = self . following_instr ( 0 ) ;
10685 if let Some ( condition) = condition {
107- let condition = self . lower_expr ( condition) ;
108- let body_label = self . following_instr ( 1 ) ;
109- let while_label = self . bc . emit ( Instruction :: Branch ( (
110- condition. to_mi ( ) ,
111- body_label,
112- Label ( 0 ) ,
113- ) ) ) ;
114- condition. free ( self ) ;
115- self . lower_body ( body) ;
116- if let Some ( SimpleStatement :: Expression ( expr) ) = update {
117- let value = self . lower_expr ( expr) ;
118- value. free ( self ) ;
119- }
120- self . bc . emit ( Instruction :: Jump ( cond_label) ) ;
121- let next = self . following_instr ( 0 ) ;
122- self . bc . nth ( while_label) . set_label ( next) ;
86+ self . emit_branch ( condition, |this| {
87+ this. lower_body ( body) ;
88+ if let Some ( SimpleStatement :: Expression ( expr) ) = update {
89+ this. lower_expr ( expr) . free ( this) ;
90+ }
91+ this. bc . emit ( Instruction :: Jump ( cond_label) ) ;
92+ } ) ;
12393 } else {
12494 self . lower_body ( body) ;
12595 if let Some ( SimpleStatement :: Expression ( expr) ) = update {
126- let value = self . lower_expr ( expr) ;
127- value. free ( self ) ;
96+ self . lower_expr ( expr) . free ( self ) ;
12897 }
12998 self . bc . emit ( Instruction :: Jump ( cond_label) ) ;
13099 }
131100 }
132101 Statement :: Simple ( SimpleStatement :: Expression ( expr) ) => {
133- let value = self . lower_expr ( expr) ;
134- value. free ( self ) ;
102+ self . lower_expr ( expr) . free ( self ) ;
135103 }
136104 Statement :: Simple ( SimpleStatement :: Command { name, args, redirection } ) => {
137105 let ( call_start, call_end, redir) = self . gen_call_convention ( args, |this| {
@@ -231,32 +199,21 @@ impl<'a> Code<'a> {
231199 lhs. free ( self ) ;
232200 rhs. free ( self ) ;
233201 }
234- ExprNode :: Ternary ( cond, true_then, false_then) => {
235- let cond = self . lower_expr ( cond) ;
236- let branch = self . bc . emit ( Instruction :: Branch ( (
237- cond. to_mi ( ) ,
238- self . following_instr ( 1 ) ,
239- Label ( 0 ) ,
240- ) ) ) ;
241- cond. free ( self ) ;
242-
243- let mut state = RegsState :: new ( self ) ;
244- state = state
245- . scope ( self , |c| {
246- c. lower_expr_into ( true_then, dest) ;
247- } )
248- . 0 ;
249-
250- let jump = self . bc . emit ( Instruction :: Jump ( Label ( 0 ) ) ) ;
251- let label = self . following_instr ( 0 ) ;
252-
253- state. scope_hwm ( self , |c| {
254- c. lower_expr_into ( false_then, dest) ;
202+ ExprNode :: Ternary ( condition, true_then, false_then) => {
203+ let ( if_label, state) = self . emit_branch ( condition, |this| {
204+ RegsState :: new ( this)
205+ . scope ( this, |this| {
206+ this. lower_expr_into ( true_then, dest) ;
207+ } )
208+ . 0
255209 } ) ;
256210
257- self . bc . nth ( branch) . set_label ( label) ;
258- let next = self . following_instr ( 0 ) ;
259- self . bc . nth ( jump) . set_label ( next) ;
211+ self . bc . nth ( if_label) . push_end_label ( ) ;
212+ self . emit_jump ( |this| {
213+ state. scope_hwm ( this, |this| {
214+ this. lower_expr_into ( false_then, dest) ;
215+ } ) ;
216+ } ) ;
260217 }
261218 ExprNode :: BinaryPlaceOperation ( op, place, expr) => {
262219 let val = self . lower_expr ( expr) ;
@@ -334,12 +291,9 @@ impl<'a> Code<'a> {
334291 }
335292 Place :: Index ( var, index) => {
336293 let ( start, end, _) = self . gen_call_convention ( index, |_| ( ) ) ;
337- self . bc . emit ( Instruction :: LoadBuiltinArray ( (
338- dest,
339- start,
340- end,
341- var_index ( var) ,
342- ) ) ) ;
294+ let index = var_index ( var) ;
295+ self . bc
296+ . emit ( Instruction :: LoadBuiltinArray ( ( dest, start, end, index) ) ) ;
343297 MaybeImm :: Reg ( dest)
344298 }
345299 Place :: ChainedIndex ( _, _) => todo ! ( ) ,
@@ -355,15 +309,13 @@ impl<'a> Code<'a> {
355309 rec. free ( self ) ;
356310 }
357311 Place :: Variable ( Variable :: User ( ident) ) => {
358- self . bc . emit ( Instruction :: StoreUserScalar ( (
359- dest,
360- src,
361- self . symbols . register_user_var ( ident, self . arena ) ,
362- ) ) ) ;
312+ let var = self . symbols . register_user_var ( ident, self . arena ) ;
313+ self . bc . emit ( Instruction :: StoreUserScalar ( ( dest, src, var) ) ) ;
363314 }
364315 Place :: Variable ( var) => {
316+ let index = var_index ( var) ;
365317 self . bc
366- . emit ( Instruction :: StoreBuiltinScalar ( ( dest, src, var_index ( var ) ) ) ) ;
318+ . emit ( Instruction :: StoreBuiltinScalar ( ( dest, src, index ) ) ) ;
367319 }
368320 Place :: Index ( Variable :: User ( ident) , index) => {
369321 let place = self . symbols . register_user_var ( ident, self . arena ) ;
@@ -373,17 +325,39 @@ impl<'a> Code<'a> {
373325 }
374326 Place :: Index ( var, index) => {
375327 let ( start, end, _) = self . gen_call_convention ( index, |_| ( ) ) ;
376- self . bc . emit ( Instruction :: StoreBuiltinArray ( (
377- dest,
378- start,
379- end,
380- var_index ( var) ,
381- ) ) ) ;
328+ let index = var_index ( var) ;
329+ self . bc
330+ . emit ( Instruction :: StoreBuiltinArray ( ( dest, start, end, index) ) ) ;
382331 }
383332 Place :: ChainedIndex ( _, _) => todo ! ( ) ,
384333 }
385334 }
386335
336+ fn emit_branch < T > (
337+ & mut self ,
338+ condition : & Expr < ' _ > ,
339+ cb : impl FnOnce ( & mut Self ) -> T ,
340+ ) -> ( Label , T ) {
341+ let condition = self . lower_expr ( condition) ;
342+ let then_label = self . following_instr ( 1 ) ;
343+ let if_label = self . bc . emit ( Instruction :: br ( condition. to_mi ( ) , then_label) ) ;
344+ condition. free ( self ) ;
345+
346+ let res = cb ( self ) ;
347+ let next = self . following_instr ( 0 ) ;
348+ self . bc . nth ( if_label) . set_label ( next) ;
349+
350+ ( if_label, res)
351+ }
352+
353+ fn emit_jump < T > ( & mut self , cb : impl FnOnce ( & mut Self ) -> T ) -> T {
354+ let label = self . bc . emit ( Instruction :: Jump ( Label ( 0 ) ) ) ;
355+ let res = cb ( self ) ;
356+ let next = self . following_instr ( 0 ) ;
357+ self . bc . nth ( label) . set_label ( next) ;
358+ res
359+ }
360+
387361 fn alloc_reg ( & mut self ) -> LinearReg {
388362 self . free_regs . pop ( ) . map ( LinearReg ) . unwrap_or_else ( || {
389363 let current = self . reg_pointer ;
@@ -466,13 +440,15 @@ impl RegsState {
466440 n_free_regs : code. free_regs . len ( ) ,
467441 }
468442 }
443+
469444 fn scope < T > ( self , code : & mut Code , f : impl FnOnce ( & mut Code ) -> T ) -> ( Self , T ) {
470445 let ret = f ( code) ;
471446 let old = code. reg_pointer ;
472447 code. reg_pointer = self . reg_pointer ;
473448 code. free_regs . truncate ( self . n_free_regs ) ;
474449 ( Self { reg_pointer : old, ..self } , ret)
475450 }
451+
476452 fn scope_hwm < T > ( self , code : & mut Code , f : impl FnOnce ( & mut Code ) -> T ) {
477453 f ( code) ;
478454 code. reg_pointer = code. reg_pointer . max ( self . reg_pointer ) ;
0 commit comments