@@ -11,7 +11,7 @@ use iter_extended::{try_vecmap, vecmap};
11
11
use noirc_errors:: Location ;
12
12
use noirc_frontend:: ast:: { UnaryOp , Visibility } ;
13
13
use noirc_frontend:: hir_def:: types:: Type as HirType ;
14
- use noirc_frontend:: monomorphization:: ast:: { self , Expression , Program } ;
14
+ use noirc_frontend:: monomorphization:: ast:: { self , Expression , Program , While } ;
15
15
16
16
use crate :: {
17
17
errors:: RuntimeError ,
@@ -153,6 +153,7 @@ impl<'a> FunctionContext<'a> {
153
153
Expression :: Cast ( cast) => self . codegen_cast ( cast) ,
154
154
Expression :: For ( for_expr) => self . codegen_for ( for_expr) ,
155
155
Expression :: Loop ( block) => self . codegen_loop ( block) ,
156
+ Expression :: While ( while_) => self . codegen_while ( while_) ,
156
157
Expression :: If ( if_expr) => self . codegen_if ( if_expr) ,
157
158
Expression :: Tuple ( tuple) => self . codegen_tuple ( tuple) ,
158
159
Expression :: ExtractTupleField ( tuple, index) => {
@@ -588,7 +589,7 @@ impl<'a> FunctionContext<'a> {
588
589
Ok ( Self :: unit_value ( ) )
589
590
}
590
591
591
- /// Codegens a loop, creating three new blocks in the process.
592
+ /// Codegens a loop, creating two new blocks in the process.
592
593
/// The return value of a loop is always a unit literal.
593
594
///
594
595
/// For example, the loop `loop { body }` is codegen'd as:
@@ -620,6 +621,47 @@ impl<'a> FunctionContext<'a> {
620
621
Ok ( Self :: unit_value ( ) )
621
622
}
622
623
624
+ /// Codegens a while loop, creating three new blocks in the process.
625
+ /// The return value of a while is always a unit literal.
626
+ ///
627
+ /// For example, the loop `while cond { body }` is codegen'd as:
628
+ ///
629
+ /// ```text
630
+ /// jmp while_entry()
631
+ /// while_entry:
632
+ /// v0 = ... codegen cond ...
633
+ /// jmpif v0, then: while_body, else: while_end
634
+ /// while_body():
635
+ /// v3 = ... codegen body ...
636
+ /// jmp while_entry()
637
+ /// while_end():
638
+ /// ... This is the current insert point after codegen_while finishes ...
639
+ /// ```
640
+ fn codegen_while ( & mut self , while_ : & While ) -> Result < Values , RuntimeError > {
641
+ let while_entry = self . builder . insert_block ( ) ;
642
+ let while_body = self . builder . insert_block ( ) ;
643
+ let while_end = self . builder . insert_block ( ) ;
644
+
645
+ self . builder . terminate_with_jmp ( while_entry, vec ! [ ] ) ;
646
+
647
+ // Codegen the entry (where the condition is)
648
+ self . builder . switch_to_block ( while_entry) ;
649
+ let condition = self . codegen_non_tuple_expression ( & while_. condition ) ?;
650
+ self . builder . terminate_with_jmpif ( condition, while_body, while_end) ;
651
+
652
+ self . enter_loop ( Loop { loop_entry : while_entry, loop_index : None , loop_end : while_end } ) ;
653
+
654
+ // Codegen the body
655
+ self . builder . switch_to_block ( while_body) ;
656
+ self . codegen_expression ( & while_. body ) ?;
657
+ self . builder . terminate_with_jmp ( while_entry, vec ! [ ] ) ;
658
+
659
+ // Finish by switching to the end of the while
660
+ self . builder . switch_to_block ( while_end) ;
661
+ self . exit_loop ( ) ;
662
+ Ok ( Self :: unit_value ( ) )
663
+ }
664
+
623
665
/// Codegens an if expression, handling the case of what to do if there is no 'else'.
624
666
///
625
667
/// For example, the expression `if cond { a } else { b }` is codegen'd as:
0 commit comments