| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | from test.support.bytecode_helper import CodegenTestCase | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | # Tests for the code-generation stage of the compiler. | 
					
						
							|  |  |  | # Examine the un-optimized code generated from the AST. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class IsolatedCodeGenTests(CodegenTestCase): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def codegen_test(self, snippet, expected_insts): | 
					
						
							|  |  |  |         import ast | 
					
						
							| 
									
										
										
										
											2024-02-15 14:32:21 +00:00
										 |  |  |         a = ast.parse(snippet, "my_file.py", "exec") | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |         insts = self.generate_code(a) | 
					
						
							|  |  |  |         self.assertInstructionsMatch(insts, expected_insts) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_if_expression(self): | 
					
						
							|  |  |  |         snippet = "42 if True else 24" | 
					
						
							|  |  |  |         false_lbl = self.Label() | 
					
						
							|  |  |  |         expected = [ | 
					
						
							|  |  |  |             ('RESUME', 0, 0), | 
					
						
							|  |  |  |             ('LOAD_CONST', 0, 1), | 
					
						
							| 
									
										
										
										
											2023-06-29 13:49:54 -07:00
										 |  |  |             ('TO_BOOL', 0, 1), | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |             ('POP_JUMP_IF_FALSE', false_lbl := self.Label(), 1), | 
					
						
							|  |  |  |             ('LOAD_CONST', 1, 1), | 
					
						
							| 
									
										
										
										
											2024-01-06 14:20:08 +00:00
										 |  |  |             ('JUMP_NO_INTERRUPT', exit_lbl := self.Label()), | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |             false_lbl, | 
					
						
							|  |  |  |             ('LOAD_CONST', 2, 1), | 
					
						
							|  |  |  |             exit_lbl, | 
					
						
							|  |  |  |             ('POP_TOP', None), | 
					
						
							| 
									
										
										
										
											2023-05-07 18:47:28 +01:00
										 |  |  |             ('LOAD_CONST', 3), | 
					
						
							|  |  |  |             ('RETURN_VALUE', None), | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |         ] | 
					
						
							|  |  |  |         self.codegen_test(snippet, expected) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def test_for_loop(self): | 
					
						
							|  |  |  |         snippet = "for x in l:\n\tprint(x)" | 
					
						
							|  |  |  |         false_lbl = self.Label() | 
					
						
							|  |  |  |         expected = [ | 
					
						
							|  |  |  |             ('RESUME', 0, 0), | 
					
						
							|  |  |  |             ('LOAD_NAME', 0, 1), | 
					
						
							|  |  |  |             ('GET_ITER', None, 1), | 
					
						
							|  |  |  |             loop_lbl := self.Label(), | 
					
						
							|  |  |  |             ('FOR_ITER', exit_lbl := self.Label(), 1), | 
					
						
							| 
									
										
										
										
											2023-02-28 11:29:32 +00:00
										 |  |  |             ('STORE_NAME', 1, 1), | 
					
						
							|  |  |  |             ('LOAD_NAME', 2, 2), | 
					
						
							| 
									
										
										
										
											2023-08-09 11:19:39 -07:00
										 |  |  |             ('PUSH_NULL', None, 2), | 
					
						
							| 
									
										
										
										
											2023-02-28 11:29:32 +00:00
										 |  |  |             ('LOAD_NAME', 1, 2), | 
					
						
							|  |  |  |             ('CALL', 1, 2), | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |             ('POP_TOP', None), | 
					
						
							|  |  |  |             ('JUMP', loop_lbl), | 
					
						
							|  |  |  |             exit_lbl, | 
					
						
							|  |  |  |             ('END_FOR', None), | 
					
						
							| 
									
										
										
										
											2024-01-24 15:10:17 +00:00
										 |  |  |             ('POP_TOP', None), | 
					
						
							| 
									
										
										
										
											2023-05-07 18:47:28 +01:00
										 |  |  |             ('LOAD_CONST', 0), | 
					
						
							|  |  |  |             ('RETURN_VALUE', None), | 
					
						
							| 
									
										
										
										
											2022-11-14 13:56:40 +00:00
										 |  |  |         ] | 
					
						
							|  |  |  |         self.codegen_test(snippet, expected) | 
					
						
							| 
									
										
										
										
											2024-02-15 14:32:21 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     def test_syntax_error__return_not_in_function(self): | 
					
						
							|  |  |  |         snippet = "return 42" | 
					
						
							|  |  |  |         with self.assertRaisesRegex(SyntaxError, "'return' outside function"): | 
					
						
							|  |  |  |             self.codegen_test(snippet, None) |