Fix inner block generation
This commit is contained in:
		
							parent
							
								
									f944387847
								
							
						
					
					
						commit
						0a90ac4497
					
				
							
								
								
									
										2
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								Makefile
									
									
									
									
									
								
							| @ -3,7 +3,7 @@ BIN=$(SRC:.reid=.out) | |||||||
| 
 | 
 | ||||||
| REID=cargo run --example cli | REID=cargo run --example cli | ||||||
| LD=ld | LD=ld | ||||||
| LDFLAGS= | LDFLAGS=-lSDL3 | ||||||
| 
 | 
 | ||||||
| all: $(BIN) | all: $(BIN) | ||||||
| clean: | clean: | ||||||
|  | |||||||
							
								
								
									
										153
									
								
								graphics.reid
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								graphics.reid
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | |||||||
|  | struct StringBuffer { | ||||||
|  |     buffer: [char; 64], | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | struct SDL_Thing {} // TODO: replace with proper dummy structs now that we can cast | ||||||
|  | struct SDL_FRect { x: f32, y: f32, w: f32, h: f32 } | ||||||
|  | struct SDL_Rect { x: i32, y: i32, w: i32, h: i32 } | ||||||
|  | extern fn SDL_malloc(size: u64) -> *SDL_Thing; | ||||||
|  | extern fn SDL_Init(flags: u32) -> bool; | ||||||
|  | extern fn SDL_Quit(); | ||||||
|  | extern fn SDL_CreateWindowAndRenderer(title: *char, width: i32, height: i32, flags: i32, | ||||||
|  |     window_out: &mut *SDL_Thing, renderer_out: &mut *SDL_Thing) -> bool; | ||||||
|  | extern fn SDL_Delay(ms: u32); | ||||||
|  | extern fn SDL_SetRenderDrawColor(renderer: *SDL_Thing, r: u8, g: u8, b: u8, a: u8); | ||||||
|  | extern fn SDL_RenderClear(renderer: *SDL_Thing); | ||||||
|  | extern fn SDL_RenderPresent(renderer: *SDL_Thing); | ||||||
|  | extern fn SDL_HasEvent(event_type: u32) -> bool; | ||||||
|  | extern fn SDL_PumpEvents(); | ||||||
|  | extern fn SDL_FlushEvents(min_type: u32, max_type: u32); | ||||||
|  | extern fn SDL_GetTicks() -> u64; | ||||||
|  | extern fn SDL_snprintf(text: &mut StringBuffer, maxlen: u64, fmt: *char, var: u64) -> i32; | ||||||
|  | extern fn SDL_SetWindowTitle(window: *SDL_Thing, title: &StringBuffer) -> bool; | ||||||
|  | extern fn SDL_CreateTexture(renderer: *SDL_Thing,  | ||||||
|  |     pixel_format: u32, texture_access: u32, width: u32, height: u32) -> *SDL_Thing; | ||||||
|  | extern fn SDL_RenderTexture(renderer: *SDL_Thing, | ||||||
|  |     texture: *SDL_Thing, srcfrect: &SDL_FRect, dstfrect: &SDL_FRect) -> bool; | ||||||
|  | extern fn SDL_UpdateTexture(texture: *SDL_Thing, rect: &SDL_Rect, pixels: *u8, pitch: u32) -> bool; | ||||||
|  | extern fn SDL_Log(fmt: *char, string_var: *char); | ||||||
|  | extern fn SDL_GetError() -> *char; | ||||||
|  | extern fn SDL_GetWindowSize(window: *SDL_Thing, w: &mut i32, h: &mut i32) -> bool; | ||||||
|  | 
 | ||||||
|  | struct GameState { | ||||||
|  |     renderer: *SDL_Thing, | ||||||
|  |     window: *SDL_Thing, | ||||||
|  |     render_texture: *SDL_Thing, | ||||||
|  |     frame_counter: u64, | ||||||
|  |     pixels: *u8, | ||||||
|  |     pixels_w: u32, | ||||||
|  |     pixels_h: u32, | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn main() -> i32 { | ||||||
|  |     let SDL_INIT_VIDEO = 32; | ||||||
|  |     let SDL_WINDOW_RESIZABLE = 32; | ||||||
|  |     let SDL_PIXELFORMAT_RGBA8888 = 373694468; | ||||||
|  |     let SDL_PIXELFORMAT_ABGR8888 = 376840196; | ||||||
|  |     let SDL_TEXTUREACCESS_STREAMING = 1; | ||||||
|  | 
 | ||||||
|  |     let init_success = SDL_Init(SDL_INIT_VIDEO); | ||||||
|  |     if init_success == false { | ||||||
|  |         SDL_Log("SDL init failed: %s", SDL_GetError()); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let mut window = placeholder_ptr(); | ||||||
|  |     let mut renderer = placeholder_ptr(); | ||||||
|  |     let gfx_init_success = SDL_CreateWindowAndRenderer( | ||||||
|  |         "graphical reid program", 640, 480, SDL_WINDOW_RESIZABLE, | ||||||
|  |         &mut window, &mut renderer | ||||||
|  |     ); | ||||||
|  |     if gfx_init_success == false { | ||||||
|  |         SDL_Log("SDL renderer and window creation failed: %s", SDL_GetError()); | ||||||
|  |         return 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     let width = 256; | ||||||
|  |     let height = 256; | ||||||
|  |     let render_texture = SDL_CreateTexture(renderer,  | ||||||
|  |         SDL_PIXELFORMAT_ABGR8888, SDL_TEXTUREACCESS_STREAMING, width, height); | ||||||
|  | 
 | ||||||
|  |     let pixels_len = (width * height * 4) as u64; | ||||||
|  |     let pixels = SDL_malloc(pixels_len) as *u8; | ||||||
|  |     let mut game_state = GameState { | ||||||
|  |         renderer: renderer, | ||||||
|  |         window: window, | ||||||
|  |         render_texture: render_texture, | ||||||
|  |         frame_counter: 0, | ||||||
|  |         pixels: pixels, | ||||||
|  |         pixels_w: width, | ||||||
|  |         pixels_h: height, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     frame_loop(game_state); | ||||||
|  | 
 | ||||||
|  |     // TODO: maybe clean up resources here but also it's a bit of a waste of energy | ||||||
|  |     SDL_Quit(); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn frame_loop(game_state: GameState) -> GameState { | ||||||
|  |     SDL_PumpEvents(); | ||||||
|  |     if SDL_HasEvent(256) { // SDL_EVENT_QUIT | ||||||
|  |         return game_state; | ||||||
|  |     } | ||||||
|  |     SDL_FlushEvents(0, 4294967296); | ||||||
|  | 
 | ||||||
|  |     let mut screen_width = 0; | ||||||
|  |     let mut screen_height = 0; | ||||||
|  |     SDL_GetWindowSize(game_state.window, &mut screen_width, &mut screen_height); | ||||||
|  | 
 | ||||||
|  |     let renderer = game_state.renderer; | ||||||
|  |     SDL_SetRenderDrawColor(renderer, 0, 50, 90, 255); | ||||||
|  |     SDL_RenderClear(renderer); | ||||||
|  | 
 | ||||||
|  |     let w = game_state.pixels_w; | ||||||
|  |     let h = game_state.pixels_h; | ||||||
|  |     draw_pixels(game_state.pixels, 0, 0, w, h, game_state.frame_counter); | ||||||
|  |     let texture_area = SDL_Rect { x: 0, y: 0, w: w as i32, h: h as i32 }; | ||||||
|  |     if SDL_UpdateTexture(game_state.render_texture, &texture_area, game_state.pixels, 4 * w) == false { | ||||||
|  |         SDL_Log("UpdateTexture error: %s", SDL_GetError()); | ||||||
|  |     } | ||||||
|  |     let src = SDL_FRect { x: 0.0, y: 0.0, w: w as f32, h: h as f32 }; | ||||||
|  |     let dst = SDL_FRect { x: 0.0, y: 0.0, w: screen_width as f32, h: screen_height as f32 }; | ||||||
|  |     if SDL_RenderTexture(renderer, game_state.render_texture, &src, &dst) == false { | ||||||
|  |         SDL_Log("RenderTexture error: %s", SDL_GetError()); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     SDL_RenderPresent(renderer); | ||||||
|  |     SDL_Delay(16); | ||||||
|  | 
 | ||||||
|  |     game_state.frame_counter = game_state.frame_counter + 1; | ||||||
|  |     let mut s = StringBuffer {}; | ||||||
|  |     SDL_snprintf(&mut s, 64, "graphical reid program frame %u", game_state.frame_counter); | ||||||
|  |     SDL_SetWindowTitle(game_state.window, &s); | ||||||
|  | 
 | ||||||
|  |     return frame_loop(game_state); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn placeholder_ptr() -> *SDL_Thing { | ||||||
|  |     return SDL_malloc(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | fn draw_pixels(pixels: *u8, x: u32, y: u32, w: u32, h: u32, frame_counter: u64) -> i32 { | ||||||
|  |     if y >= h { | ||||||
|  |         return 0; | ||||||
|  |     } | ||||||
|  |     let index = (x + y * w) * 4; | ||||||
|  | 
 | ||||||
|  |     pixels[index + 0] = x as u8; | ||||||
|  |     pixels[index + 1] = y as u8; | ||||||
|  |     pixels[index + 2] = frame_counter as u8; | ||||||
|  |     pixels[index + 3] = 255; | ||||||
|  | 
 | ||||||
|  |     let mut new_x = x + 1; | ||||||
|  |     let mut new_y = y; | ||||||
|  |     if new_x >= w { | ||||||
|  |         new_x = 0; | ||||||
|  |         new_y = y + 1; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     draw_pixels(pixels, new_x, new_y, w, h, frame_counter); | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
| @ -199,6 +199,7 @@ pub struct BlockData { | |||||||
|     deleted: bool, |     deleted: bool, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #[derive(Clone)] | ||||||
| pub struct Block<'builder> { | pub struct Block<'builder> { | ||||||
|     phantom: PhantomData<&'builder ()>, |     phantom: PhantomData<&'builder ()>, | ||||||
|     builder: Builder, |     builder: Builder, | ||||||
|  | |||||||
| @ -14,6 +14,6 @@ color = ["colored"] | |||||||
| [dependencies] | [dependencies] | ||||||
| ## Make it easier to generate errors | ## Make it easier to generate errors | ||||||
| thiserror = "1.0.44" | thiserror = "1.0.44" | ||||||
| reid-lib = { path = "../reid-llvm-lib", version = "0.1.0"} | reid-lib = { path = "../reid-llvm-lib", version = "0.1.0" } | ||||||
| 
 | 
 | ||||||
| colored = {version = "3.0.0", optional = true} | colored = {version = "3.0.0", optional = true} | ||||||
| @ -94,13 +94,13 @@ fn str_length(string: *char, position: u32) -> u32 { | |||||||
| 
 | 
 | ||||||
| pub fn add_num_to_str(string: &mut String, num: u64) { | pub fn add_num_to_str(string: &mut String, num: u64) { | ||||||
|     if num == 0 { add_char(string, '0'); }  |     if num == 0 { add_char(string, '0'); }  | ||||||
|     else { if num == 1 { add_char(string, '1'); }  |     else if num == 1 { add_char(string, '1'); } | ||||||
|     else { if num == 2 { add_char(string, '2'); }  |     else if num == 2 { add_char(string, '2'); } | ||||||
|     else { if num == 3 { add_char(string, '3'); }  |     else if num == 3 { add_char(string, '3'); } | ||||||
|     else { if num == 4 { add_char(string, '4'); }  |     else if num == 4 { add_char(string, '4'); } | ||||||
|     else { if num == 5 { add_char(string, '5'); }  |     else if num == 5 { add_char(string, '5'); } | ||||||
|     else { if num == 6 { add_char(string, '6'); }  |     else if num == 6 { add_char(string, '6'); } | ||||||
|     else { if num == 7 { add_char(string, '7'); }  |     else if num == 7 { add_char(string, '7'); } | ||||||
|     else { if num == 8 { add_char(string, '8'); }  |     else if num == 8 { add_char(string, '8'); } | ||||||
|     else { if num == 9 { add_char(string, '9'); } } } } } } } } } } |     else if num == 9 { add_char(string, '9'); } | ||||||
| } | } | ||||||
| @ -746,16 +746,19 @@ impl mir::Expression { | |||||||
|             } |             } | ||||||
|             mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state), |             mir::ExprKind::If(if_expression) => if_expression.codegen(scope, state), | ||||||
|             mir::ExprKind::Block(block) => { |             mir::ExprKind::Block(block) => { | ||||||
|                 let mut inner_scope = scope.with_block(scope.function.ir.block("inner")); |                 let inner = scope.function.ir.block("inner"); | ||||||
|                 if let Some(ret) = block.codegen(&mut inner_scope, state) { |                 scope.block.terminate(Term::Br(inner.value())).unwrap(); | ||||||
|                     inner_scope | 
 | ||||||
|                         .block |                 let mut inner_scope = scope.with_block(inner); | ||||||
|                         .terminate(Term::Br(scope.block.value())) |                 let ret = if let Some(ret) = block.codegen(&mut inner_scope, state) { | ||||||
|                         .unwrap(); |  | ||||||
|                     Some(ret) |                     Some(ret) | ||||||
|                 } else { |                 } else { | ||||||
|                     None |                     None | ||||||
|                 } |                 }; | ||||||
|  |                 let outer = scope.function.ir.block("outer"); | ||||||
|  |                 inner_scope.block.terminate(Term::Br(outer.value())).ok(); | ||||||
|  |                 scope.swap_block(outer); | ||||||
|  |                 ret | ||||||
|             } |             } | ||||||
|             mir::ExprKind::Indexed(expression, val_t, idx_expr) => { |             mir::ExprKind::Indexed(expression, val_t, idx_expr) => { | ||||||
|                 let StackValue(kind, ty) = expression |                 let StackValue(kind, ty) = expression | ||||||
| @ -1138,19 +1141,12 @@ impl mir::IfExpression { | |||||||
|             let before_v = debug.info.location(&debug.scope, before_location); |             let before_v = debug.info.location(&debug.scope, before_location); | ||||||
|             scope.block.set_terminator_location(before_v).ok(); |             scope.block.set_terminator_location(before_v).ok(); | ||||||
| 
 | 
 | ||||||
|             let then_location = self |             let then_location = self.1 .1.into_debug(scope.tokens, debug.scope).unwrap(); | ||||||
|                 .1 |  | ||||||
|                 .return_meta() |  | ||||||
|                 .into_debug(scope.tokens, debug.scope) |  | ||||||
|                 .unwrap(); |  | ||||||
|             let then_v = debug.info.location(&debug.scope, then_location); |             let then_v = debug.info.location(&debug.scope, then_location); | ||||||
|             then_b.set_terminator_location(then_v).unwrap(); |             then_b.set_terminator_location(then_v).unwrap(); | ||||||
| 
 | 
 | ||||||
|             let else_location = if let Some(else_block) = &self.2 { |             let else_location = if let Some(else_expr) = self.2.as_ref() { | ||||||
|                 else_block |                 else_expr.1.into_debug(scope.tokens, debug.scope).unwrap() | ||||||
|                     .return_meta() |  | ||||||
|                     .into_debug(scope.tokens, debug.scope) |  | ||||||
|                     .unwrap() |  | ||||||
|             } else { |             } else { | ||||||
|                 then_location |                 then_location | ||||||
|             }; |             }; | ||||||
| @ -1168,7 +1164,7 @@ impl mir::IfExpression { | |||||||
|         let then_res = self.1.codegen(&mut then_scope, state); |         let then_res = self.1.codegen(&mut then_scope, state); | ||||||
|         then_scope.block.terminate(Term::Br(after_bb)).ok(); |         then_scope.block.terminate(Term::Br(after_bb)).ok(); | ||||||
| 
 | 
 | ||||||
|         let else_res = if let Some(else_block) = &self.2 { |         let else_res = if let Some(else_expr) = self.2.as_ref() { | ||||||
|             let mut else_scope = scope.with_block(else_b); |             let mut else_scope = scope.with_block(else_b); | ||||||
| 
 | 
 | ||||||
|             scope |             scope | ||||||
| @ -1176,7 +1172,7 @@ impl mir::IfExpression { | |||||||
|                 .terminate(Term::CondBr(condition.instr(), then_bb, else_bb)) |                 .terminate(Term::CondBr(condition.instr(), then_bb, else_bb)) | ||||||
|                 .unwrap(); |                 .unwrap(); | ||||||
| 
 | 
 | ||||||
|             let opt = else_block.codegen(&mut else_scope, state); |             let opt = else_expr.codegen(&mut else_scope, state); | ||||||
| 
 | 
 | ||||||
|             else_scope.block.terminate(Term::Br(after_bb)).ok(); |             else_scope.block.terminate(Term::Br(after_bb)).ok(); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -275,7 +275,7 @@ pub fn tokenize<T: Into<String>>(to_tokenize: T) -> Result<Vec<FullToken>, Error | |||||||
|                 match character { |                 match character { | ||||||
|                     '\'' => Token::CharLit(value), |                     '\'' => Token::CharLit(value), | ||||||
|                     '\"' => Token::StringLit(value), |                     '\"' => Token::StringLit(value), | ||||||
|                     _ => unsafe { unreachable_unchecked() }, |                     _ => unreachable!(), | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             // "words"
 |             // "words"
 | ||||||
|  | |||||||
| @ -240,7 +240,7 @@ impl Display for IfExpression { | |||||||
|     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||||
|         write!(f, "if {} ", self.0)?; |         write!(f, "if {} ", self.0)?; | ||||||
|         Display::fmt(&self.1, f)?; |         Display::fmt(&self.1, f)?; | ||||||
|         if let Some(e) = *self.2 { |         if let Some(e) = self.2.as_ref() { | ||||||
|             Display::fmt(&e, f)?; |             Display::fmt(&e, f)?; | ||||||
|         } |         } | ||||||
|         Ok(()) |         Ok(()) | ||||||
|  | |||||||
| @ -491,8 +491,8 @@ impl IfExpression { | |||||||
|         mod_id: SourceModuleId, |         mod_id: SourceModuleId, | ||||||
|     ) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { |     ) -> Result<(ReturnKind, TypeKind), ReturnTypeOther> { | ||||||
|         let then_r = self.1.return_type(refs, mod_id)?; |         let then_r = self.1.return_type(refs, mod_id)?; | ||||||
|         if let Some(else_b) = &self.2 { |         if let Some(else_e) = self.2.as_ref() { | ||||||
|             let else_r = else_b.return_type(refs, mod_id)?; |             let else_r = else_e.return_type(refs, mod_id)?; | ||||||
| 
 | 
 | ||||||
|             let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard { |             let kind = if then_r.0 == ReturnKind::Hard && else_r.0 == ReturnKind::Hard { | ||||||
|                 ReturnKind::Hard |                 ReturnKind::Hard | ||||||
|  | |||||||
| @ -491,46 +491,31 @@ impl Expression { | |||||||
|                 // Typecheck then/else return types and make sure they are the
 |                 // Typecheck then/else return types and make sure they are the
 | ||||||
|                 // same, if else exists.
 |                 // same, if else exists.
 | ||||||
|                 let then_res = lhs.typecheck(state, &typerefs, hint_t); |                 let then_res = lhs.typecheck(state, &typerefs, hint_t); | ||||||
|                 let (then_ret_kind, then_ret_t) = state.or_else( |                 let then_ret_t = state.or_else(then_res, TypeKind::Vague(Vague::Unknown), lhs.1); | ||||||
|                     then_res, |                 let else_ret_t = if let Some(else_expr) = rhs.as_mut() { | ||||||
|                     (ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)), |                     let res = else_expr.typecheck(state, &typerefs, hint_t); | ||||||
|                     lhs.meta, |                     let else_ret_t = | ||||||
|                 ); |                         state.or_else(res, TypeKind::Vague(Vague::Unknown), else_expr.1); | ||||||
|                 let else_ret_t = if let Some(else_block) = rhs { |  | ||||||
|                     let res = else_block.typecheck(state, &typerefs, hint_t); |  | ||||||
|                     let (else_ret_kind, else_ret_t) = state.or_else( |  | ||||||
|                         res, |  | ||||||
|                         (ReturnKind::Soft, TypeKind::Vague(Vague::Unknown)), |  | ||||||
|                         else_block.meta, |  | ||||||
|                     ); |  | ||||||
| 
 | 
 | ||||||
|                     if else_ret_kind == ReturnKind::Hard { |                     else_ret_t | ||||||
|                         TypeKind::Void |  | ||||||
|                     } else { |  | ||||||
|                         else_ret_t |  | ||||||
|                     } |  | ||||||
|                 } else { |                 } else { | ||||||
|                     // Else return type is Void if it does not exist
 |                     // Else return type is Void if it does not exist
 | ||||||
|                     TypeKind::Void |                     TypeKind::Void | ||||||
|                 }; |                 }; | ||||||
|                 let then_ret_t = if then_ret_kind == ReturnKind::Hard { |                 let then_ret_t = then_ret_t; | ||||||
|                     TypeKind::Void |  | ||||||
|                 } else { |  | ||||||
|                     then_ret_t |  | ||||||
|                 }; |  | ||||||
| 
 | 
 | ||||||
|                 // Make sure then and else -blocks have the same return type
 |                 // Make sure then and else -blocks have the same return type
 | ||||||
|                 let collapsed = then_ret_t |                 let collapsed = then_ret_t | ||||||
|                     .collapse_into(&else_ret_t) |                     .collapse_into(&else_ret_t) | ||||||
|                     .or(Err(ErrorKind::BranchTypesDiffer(then_ret_t, else_ret_t)))?; |                     .or(Err(ErrorKind::BranchTypesDiffer(then_ret_t, else_ret_t)))?; | ||||||
| 
 | 
 | ||||||
|                 if let Some(rhs) = rhs { |                 if let Some(rhs) = rhs.as_mut() { | ||||||
|                     // If rhs existed, typecheck both sides to perform type
 |                     // If rhs existed, typecheck both sides to perform type
 | ||||||
|                     // coercion.
 |                     // coercion.
 | ||||||
|                     let lhs_res = lhs.typecheck(state, &typerefs, Some(&collapsed)); |                     let lhs_res = lhs.typecheck(state, &typerefs, Some(&collapsed)); | ||||||
|                     let rhs_res = rhs.typecheck(state, &typerefs, Some(&collapsed)); |                     let rhs_res = rhs.typecheck(state, &typerefs, Some(&collapsed)); | ||||||
|                     state.ok(lhs_res, lhs.meta); |                     state.ok(lhs_res, lhs.1); | ||||||
|                     state.ok(rhs_res, rhs.meta); |                     state.ok(rhs_res, rhs.1); | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 Ok(collapsed) |                 Ok(collapsed) | ||||||
|  | |||||||
| @ -227,22 +227,26 @@ impl Expression { | |||||||
|                 let lhs_res = lhs.infer_types(state, type_refs); |                 let lhs_res = lhs.infer_types(state, type_refs); | ||||||
|                 let lhs_hints = state.ok(lhs_res, cond.1); |                 let lhs_hints = state.ok(lhs_res, cond.1); | ||||||
| 
 | 
 | ||||||
|                 if let Some(rhs) = rhs { |                 if let Some(rhs) = rhs.as_mut() { | ||||||
|                     // Infer RHS return type
 |                     // Infer RHS return type
 | ||||||
|                     let rhs_res = rhs.infer_types(state, type_refs); |                     let rhs_res = rhs.infer_types(state, type_refs); | ||||||
|                     let rhs_hints = state.ok(rhs_res, cond.1); |                     let rhs_hints = state.ok(rhs_res, cond.1); | ||||||
| 
 | 
 | ||||||
|                     // Narrow LHS to the same type as RHS and return it's return type
 |                     // Narrow LHS to the same type as RHS and return it's return type
 | ||||||
|                     if let (Some(mut lhs_hints), Some(mut rhs_hints)) = (lhs_hints, rhs_hints) { |                     if let (Some(mut lhs_hints), Some(mut rhs_hints)) = (lhs_hints, rhs_hints) { | ||||||
|                         lhs_hints.1.narrow(&mut rhs_hints.1); |                         lhs_hints | ||||||
|                         Ok(pick_return(lhs_hints, rhs_hints).1) |                             .narrow(&mut rhs_hints) | ||||||
|  |                             .ok_or(ErrorKind::TypesIncompatible( | ||||||
|  |                                 lhs_hints.resolve_deep().unwrap(), | ||||||
|  |                                 rhs_hints.resolve_deep().unwrap(), | ||||||
|  |                             )) | ||||||
|                     } else { |                     } else { | ||||||
|                         // Failed to retrieve types from either
 |                         // Failed to retrieve types from either
 | ||||||
|                         Ok(type_refs.from_type(&Vague(Unknown)).unwrap()) |                         Ok(type_refs.from_type(&Vague(Unknown)).unwrap()) | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     // Return LHS return type
 |                     // Return LHS return type
 | ||||||
|                     if let Some((_, type_ref)) = lhs_hints { |                     if let Some(type_ref) = lhs_hints { | ||||||
|                         Ok(type_ref) |                         Ok(type_ref) | ||||||
|                     } else { |                     } else { | ||||||
|                         Ok(type_refs.from_type(&Vague(Unknown)).unwrap()) |                         Ok(type_refs.from_type(&Vague(Unknown)).unwrap()) | ||||||
|  | |||||||
| @ -166,8 +166,6 @@ impl<'a, 'b> TokenStream<'a, 'b> { | |||||||
| 
 | 
 | ||||||
|         match T::parse(clone) { |         match T::parse(clone) { | ||||||
|             Ok(res) => { |             Ok(res) => { | ||||||
|                 #[cfg(debug_assertions)] |  | ||||||
|                 // dbg!(&res);
 |  | ||||||
|                 let new_pos = ref_pos.max(self.position); |                 let new_pos = ref_pos.max(self.position); | ||||||
|                 Ok((res, new_pos)) |                 Ok((res, new_pos)) | ||||||
|             } |             } | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user