diff --git a/lib/skc_ast2hir/src/convert_exprs.rs b/lib/skc_ast2hir/src/convert_exprs.rs index da0ec011..e1ae95bb 100644 --- a/lib/skc_ast2hir/src/convert_exprs.rs +++ b/lib/skc_ast2hir/src/convert_exprs.rs @@ -16,13 +16,13 @@ use shiika_core::{names::*, ty, ty::*}; use skc_hir::*; impl<'hir_maker> HirMaker<'hir_maker> { - pub(super) fn convert_exprs(&mut self, exprs: &[AstExpression]) -> Result { + pub(super) fn convert_exprs(&mut self, exprs: &[AstExpression]) -> Result { let hir_exprs = exprs .iter() .map(|expr| self.convert_expr(expr)) .collect::, _>>()?; - Ok(HirExpressions::new(hir_exprs)) + Ok(Hir::expressions(hir_exprs)) } pub(super) fn convert_expr(&mut self, expr: &AstExpression) -> Result { @@ -200,7 +200,7 @@ impl<'hir_maker> HirMaker<'hir_maker> { let mut else_hirs = match else_exprs { Some(exprs) => self.convert_exprs(exprs)?, - None => HirExpressions::void(), + None => Hir::expressions(vec![]), }; let else_ctx = self.ctx_stack.pop_if_ctx(); if_ctxs.push(else_ctx); @@ -210,10 +210,10 @@ impl<'hir_maker> HirMaker<'hir_maker> { } else if else_hirs.ty.is_never_type() { then_hirs.ty.clone() } else if then_hirs.ty.is_void_type() { - else_hirs.voidify(); + else_hirs = else_hirs.voidify(); ty::raw("Void") } else if else_hirs.ty.is_void_type() { - then_hirs.voidify(); + then_hirs = then_hirs.voidify(); ty::raw("Void") } else { let opt_ty = self @@ -221,10 +221,10 @@ impl<'hir_maker> HirMaker<'hir_maker> { .nearest_common_ancestor(&then_hirs.ty, &else_hirs.ty); let ty = type_checking::check_if_body_ty(opt_ty)?; if !then_hirs.ty.equals_to(&ty) { - then_hirs = then_hirs.bitcast_to(ty.clone()); + then_hirs = Hir::bit_cast(ty.clone(), then_hirs); } if !else_hirs.ty.equals_to(&ty) { - else_hirs = else_hirs.bitcast_to(ty.clone()); + else_hirs = Hir::bit_cast(ty.clone(), else_hirs); } ty }; @@ -1063,8 +1063,8 @@ impl<'hir_maker> HirMaker<'hir_maker> { )); } - exprs.push(Hir::lvar_ref(ary_ty, tmp_name, locs.clone())); - Hir::parenthesized_expression(Hir::expressions(exprs), locs) + exprs.push(Hir::lvar_ref(ary_ty.clone(), tmp_name, locs.clone())); + Hir::parenthesized_expression(ary_ty, exprs, locs) } fn convert_self_expr(&self, locs: &LocationSpan) -> HirExpression { diff --git a/lib/skc_ast2hir/src/hir_maker.rs b/lib/skc_ast2hir/src/hir_maker.rs index 752a50a9..8468b220 100644 --- a/lib/skc_ast2hir/src/hir_maker.rs +++ b/lib/skc_ast2hir/src/hir_maker.rs @@ -52,7 +52,7 @@ impl<'hir_maker> HirMaker<'hir_maker> { } /// Destructively convert self to Hir - pub fn extract_hir(&mut self, main_exprs: HirExpressions, main_lvars: HirLVars) -> Hir { + pub fn extract_hir(&mut self, main_exprs: HirExpression, main_lvars: HirLVars) -> Hir { // Extract data from self let sk_types = std::mem::take(&mut self.class_dict.sk_types); let sk_methods = std::mem::take(&mut self.method_dict.0); @@ -141,7 +141,7 @@ impl<'hir_maker> HirMaker<'hir_maker> { pub fn convert_toplevel_items( &mut self, items: Vec, - ) -> Result<(HirExpressions, HirLVars)> { + ) -> Result<(HirExpression, HirLVars)> { let mut defs = vec![]; let mut top_exprs = vec![]; for item in items { @@ -164,7 +164,7 @@ impl<'hir_maker> HirMaker<'hir_maker> { debug_assert!(self.ctx_stack.len() == 1); let mut toplevel_ctx = self.ctx_stack.pop_toplevel_ctx(); Ok(( - HirExpressions::new(main_exprs), + Hir::expressions(main_exprs), extract_lvars(&mut toplevel_ctx.lvars), )) } @@ -471,11 +471,13 @@ impl<'hir_maker> HirMaker<'hir_maker> { } let mut hir_exprs = self.convert_exprs(body_exprs)?; if signature.has_default_expr() { - hir_exprs.prepend(_set_defaults(self, ast_sig)?); + let mut exprs = _set_defaults(self, ast_sig)?; + exprs.push(hir_exprs); + hir_exprs = Hir::expressions(exprs); } // Insert ::Void so that last expr always matches to ret_ty if signature.ret_ty.is_void_type() { - hir_exprs.voidify(); + hir_exprs = hir_exprs.voidify(); } let mut method_ctx = self.ctx_stack.pop_method_ctx(); let lvars = extract_lvars(&mut method_ctx.lvars); @@ -548,7 +550,7 @@ impl<'hir_maker> HirMaker<'hir_maker> { let initialize = SkMethod::simple( signature, SkMethodBody::Normal { - exprs: HirExpressions::new(exprs), + exprs: Hir::expressions(exprs), }, ); self.method_dict @@ -648,14 +650,8 @@ fn _set_default( let arg = Hir::arg_ref(value_expr.ty.clone(), idx, locs.clone()); let cond_expr = Hir::is_omitted_value(arg.clone()); - let mut then_exprs = HirExpressions::void(); - then_exprs.prepend(vec![Hir::lvar_assign( - name.to_string(), - value_expr, - locs.clone(), - )]); - let mut else_exprs = HirExpressions::void(); - else_exprs.prepend(vec![Hir::lvar_assign(name.to_string(), arg, locs)]); + let then_exprs = Hir::lvar_assign(name.to_string(), value_expr, locs.clone()); + let else_exprs = Hir::lvar_assign(name.to_string(), arg, locs); let if_expr = Hir::if_expression( ty::raw("Void"), diff --git a/lib/skc_ast2hir/src/pattern_match.rs b/lib/skc_ast2hir/src/pattern_match.rs index 0f2f5f36..ea6599b4 100644 --- a/lib/skc_ast2hir/src/pattern_match.rs +++ b/lib/skc_ast2hir/src/pattern_match.rs @@ -70,7 +70,7 @@ fn compile_body( mk: &mut HirMaker, components: &[Component], body: &[AstExpression], -) -> Result<(HirExpressions, HirLVars)> { +) -> Result<(HirExpression, HirLVars)> { mk.ctx_stack.push(HirMakerContext::match_clause()); // Declare lvars introduced by matching for component in components { @@ -97,7 +97,9 @@ fn calc_result_ty(mk: &HirMaker, clauses_: &mut [MatchClause]) -> Result } else if clauses.iter().any(|c| c.body_hir.ty.is_void_type()) { for c in clauses.iter_mut() { if !c.body_hir.ty.is_void_type() { - c.body_hir.voidify(); + let mut tmp = Hir::expressions(vec![]); + std::mem::swap(&mut tmp, &mut c.body_hir); + c.body_hir = tmp.voidify(); } } Ok(ty::raw("Void")) @@ -124,7 +126,7 @@ fn calc_result_ty(mk: &HirMaker, clauses_: &mut [MatchClause]) -> Result fn bitcast_match_clause_body(c: &mut MatchClause, ty: TermTy) { let mut tmp = Hir::expressions(Default::default()); std::mem::swap(&mut tmp, &mut c.body_hir); - tmp = tmp.bitcast_to(ty); + tmp = Hir::bit_cast(ty, tmp); std::mem::swap(&mut tmp, &mut c.body_hir); } diff --git a/lib/skc_ast2hir/src/type_system/type_checking.rs b/lib/skc_ast2hir/src/type_system/type_checking.rs index f3ae75c5..28996e0b 100644 --- a/lib/skc_ast2hir/src/type_system/type_checking.rs +++ b/lib/skc_ast2hir/src/type_system/type_checking.rs @@ -17,7 +17,7 @@ macro_rules! type_error { pub fn check_return_value( class_dict: &ClassDict, sig: &MethodSignature, - body_exprs: &HirExpressions, + body_exprs: &HirExpression, ) -> Result<()> { let ty = &body_exprs.ty; if sig.ret_ty.is_void_type() { diff --git a/lib/skc_codegen/src/gen_exprs.rs b/lib/skc_codegen/src/gen_exprs.rs index eca0e557..cfa87992 100644 --- a/lib/skc_codegen/src/gen_exprs.rs +++ b/lib/skc_codegen/src/gen_exprs.rs @@ -19,28 +19,6 @@ use std::rc::Rc; const EXIT_BREAK: u64 = 1; impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { - /// Generate LLVM IR from HirExpressions. - /// May return `None` when, for example, it ends with a `return` - /// expression. - pub fn gen_exprs( - &'run self, - ctx: &mut CodeGenContext<'hir, 'run>, - exprs: &'hir HirExpressions, - ) -> Result>> { - debug_assert!(!exprs.exprs.is_empty()); - let mut last_value = None; - for expr in &exprs.exprs { - let value = self.gen_expr(ctx, expr)?; - if value.is_none() { - //log::warn!("detected unreachable code"); - return Ok(None); - } else { - last_value = Some(value); - } - } - Ok(last_value.unwrap()) - } - pub fn gen_expr( &'run self, ctx: &mut CodeGenContext<'hir, 'run>, @@ -171,7 +149,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { initialize_name, init_cls_name, ))), - HirParenthesizedExpr { exprs } => self.gen_exprs(ctx, exprs), + HirParenthesizedExpr { exprs } => self.gen_parenthesized_expr(ctx, exprs), HirDefaultExpr => Ok(Some(self.gen_default_expr(&expr.ty))), HirIsOmittedValue { expr } => self.gen_is_omitted_value(ctx, expr), } @@ -262,8 +240,8 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { ctx: &mut CodeGenContext<'hir, 'run>, ty: &TermTy, cond_expr: &'hir HirExpression, - then_exprs: &'hir HirExpressions, - else_exprs: &'hir HirExpressions, + then_exprs: &'hir HirExpression, + else_exprs: &'hir HirExpression, ) -> Result>> { let begin_block = self.context.append_basic_block(ctx.function, "IfBegin"); let then_block = self.context.append_basic_block(ctx.function, "IfThen"); @@ -277,14 +255,14 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { self.gen_conditional_branch(cond_value, then_block, else_block); // IfThen: self.builder.position_at_end(then_block); - let then_value = self.gen_exprs(ctx, then_exprs)?; + let then_value = self.gen_expr(ctx, then_exprs)?; if then_value.is_some() { self.builder.build_unconditional_branch(merge_block); } let then_block_end = self.builder.get_insert_block().unwrap(); // IfElse: self.builder.position_at_end(else_block); - let else_value = self.gen_exprs(ctx, else_exprs)?; + let else_value = self.gen_expr(ctx, else_exprs)?; if else_value.is_some() { self.builder.build_unconditional_branch(merge_block); } @@ -400,7 +378,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { } } let result = self - .gen_exprs(ctx, &clause.body_hir)? + .gen_expr(ctx, &clause.body_hir)? .map(|v| self.bitcast(v, result_ty, "as")); ctx.lvars = orig_lvars; Ok(result) @@ -410,7 +388,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { &'run self, ctx: &mut CodeGenContext<'hir, 'run>, cond_expr: &'hir HirExpression, - body_exprs: &'hir HirExpressions, + body_exprs: &'hir HirExpression, ) -> Result>> { let begin_block = self.context.append_basic_block(ctx.function, "WhileBegin"); self.builder.build_unconditional_branch(begin_block); @@ -426,7 +404,7 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { let rc2 = Rc::clone(&rc1); let orig_loop_end = ctx.current_loop_end.as_ref().map(Rc::clone); ctx.current_loop_end = Some(rc1); - self.gen_exprs(ctx, body_exprs)?; + self.gen_expr(ctx, body_exprs)?; ctx.current_loop_end = orig_loop_end; self.builder.build_unconditional_branch(begin_block); @@ -1266,6 +1244,28 @@ impl<'hir, 'run, 'ictx> CodeGen<'hir, 'run, 'ictx> { cls_obj } + /// Compile successive expressions. The last evaluated value is returned. + /// Returns `None` if terminated with a `Never` type (`return`, `panic`, etc.) + fn gen_parenthesized_expr( + &'run self, + ctx: &mut CodeGenContext<'hir, 'run>, + exprs: &'hir [HirExpression], + ) -> Result>> { + debug_assert!(!exprs.is_empty()); + let mut last_value = None; + for expr in exprs { + let value = self.gen_expr(ctx, expr)?; + if value.is_none() { + // Found `return`, `panic` or something. The rest of `exprs` + // will never be executed + return Ok(None); + } else { + last_value = Some(value); + } + } + Ok(last_value.unwrap()) + } + /// Returns a special value (currently a nullptr) that denotes using the default argument value. fn gen_default_expr(&'run self, ty: &TermTy) -> SkObj<'run> { self.null_ptr(ty) diff --git a/lib/skc_codegen/src/lambda.rs b/lib/skc_codegen/src/lambda.rs index 21135e96..97f2ee63 100644 --- a/lib/skc_codegen/src/lambda.rs +++ b/lib/skc_codegen/src/lambda.rs @@ -171,7 +171,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { for methods in hir.sk_methods.values() { for method in methods { if let SkMethodBody::Normal { exprs } = &method.body { - self.gen_lambda_funcs_in_exprs(&exprs.exprs)?; + self.gen_lambda_funcs_in_expr(exprs)?; } } } @@ -180,14 +180,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { self.gen_lambda_funcs_in_expr(expr)?; } - self.gen_lambda_funcs_in_exprs(&hir.main_exprs.exprs)?; - Ok(()) - } - - fn gen_lambda_funcs_in_exprs(&self, exprs: &'hir [HirExpression]) -> Result<()> { - for expr in exprs { - self.gen_lambda_funcs_in_expr(expr)?; - } + self.gen_lambda_funcs_in_expr(&hir.main_exprs)?; Ok(()) } @@ -209,8 +202,8 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .. } => { self.gen_lambda_funcs_in_expr(cond_expr)?; - self.gen_lambda_funcs_in_exprs(&then_exprs.exprs)?; - self.gen_lambda_funcs_in_exprs(&else_exprs.exprs)?; + self.gen_lambda_funcs_in_expr(then_exprs)?; + self.gen_lambda_funcs_in_expr(else_exprs)?; } HirMatchExpression { cond_assign_expr, @@ -218,7 +211,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { } => { self.gen_lambda_funcs_in_expr(cond_assign_expr)?; for clause in clauses { - self.gen_lambda_funcs_in_exprs(&clause.body_hir.exprs)?; + self.gen_lambda_funcs_in_expr(&clause.body_hir)?; } } HirWhileExpression { @@ -227,7 +220,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .. } => { self.gen_lambda_funcs_in_expr(cond_expr)?; - self.gen_lambda_funcs_in_exprs(&body_exprs.exprs)?; + self.gen_lambda_funcs_in_expr(body_exprs)?; } HirBreakExpression { .. } => (), HirReturnExpression { arg, .. } => self.gen_lambda_funcs_in_expr(arg)?, @@ -278,7 +271,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .. } => { self.gen_lambda_func(name, params, exprs, ret_ty, lvars)?; - self.gen_lambda_funcs_in_exprs(&exprs.exprs)?; + self.gen_lambda_funcs_in_expr(exprs)?; } HirSelfExpression => (), HirFloatLiteral { .. } => (), @@ -290,7 +283,11 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { HirLambdaCaptureWrite { rhs, .. } => self.gen_lambda_funcs_in_expr(rhs)?, HirBitCast { expr } => self.gen_lambda_funcs_in_expr(expr)?, HirClassLiteral { .. } => (), - HirParenthesizedExpr { exprs } => self.gen_lambda_funcs_in_exprs(&exprs.exprs)?, + HirParenthesizedExpr { exprs } => { + for expr in exprs { + self.gen_lambda_funcs_in_expr(expr)?; + } + } HirDefaultExpr { .. } => (), HirIsOmittedValue { expr, .. } => self.gen_lambda_funcs_in_expr(expr)?, } @@ -301,7 +298,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { &self, name: &str, params: &'hir [MethodParam], - exprs: &'hir HirExpressions, + exprs: &'hir HirExpression, ret_ty: &TermTy, lvars: &HirLVars, ) -> Result<()> { @@ -322,7 +319,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { for methods in hir.sk_methods.values() { for method in methods { if let SkMethodBody::Normal { exprs } = &method.body { - self.gen_lambda_capture_structs_in_exprs(&exprs.exprs)?; + self.gen_lambda_capture_structs_in_expr(exprs)?; } } } @@ -331,14 +328,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { self.gen_lambda_capture_structs_in_expr(expr)?; } - self.gen_lambda_capture_structs_in_exprs(&hir.main_exprs.exprs)?; - Ok(()) - } - - fn gen_lambda_capture_structs_in_exprs(&self, exprs: &'hir [HirExpression]) -> Result<()> { - for expr in exprs { - self.gen_lambda_capture_structs_in_expr(expr)?; - } + self.gen_lambda_capture_structs_in_expr(&hir.main_exprs)?; Ok(()) } @@ -360,8 +350,8 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .. } => { self.gen_lambda_capture_structs_in_expr(cond_expr)?; - self.gen_lambda_capture_structs_in_exprs(&then_exprs.exprs)?; - self.gen_lambda_capture_structs_in_exprs(&else_exprs.exprs)?; + self.gen_lambda_capture_structs_in_expr(then_exprs)?; + self.gen_lambda_capture_structs_in_expr(else_exprs)?; } HirMatchExpression { cond_assign_expr, @@ -369,7 +359,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { } => { self.gen_lambda_capture_structs_in_expr(cond_assign_expr)?; for clause in clauses { - self.gen_lambda_capture_structs_in_exprs(&clause.body_hir.exprs)?; + self.gen_lambda_capture_structs_in_expr(&clause.body_hir)?; } } HirWhileExpression { @@ -378,7 +368,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .. } => { self.gen_lambda_capture_structs_in_expr(cond_expr)?; - self.gen_lambda_capture_structs_in_exprs(&body_exprs.exprs)?; + self.gen_lambda_capture_structs_in_expr(body_exprs)?; } HirBreakExpression { .. } => (), HirReturnExpression { arg, .. } => self.gen_lambda_capture_structs_in_expr(arg)?, @@ -427,7 +417,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { .. } => { self.gen_lambda_capture_struct(name, captures)?; - self.gen_lambda_capture_structs_in_exprs(&exprs.exprs)?; + self.gen_lambda_capture_structs_in_expr(exprs)?; } HirSelfExpression => (), HirFloatLiteral { .. } => (), @@ -440,7 +430,9 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { HirBitCast { expr } => self.gen_lambda_capture_structs_in_expr(expr)?, HirClassLiteral { .. } => (), HirParenthesizedExpr { exprs } => { - self.gen_lambda_capture_structs_in_exprs(&exprs.exprs)? + for expr in exprs { + self.gen_lambda_capture_structs_in_expr(expr)?; + } } HirDefaultExpr { .. } => (), HirIsOmittedValue { expr, .. } => self.gen_lambda_capture_structs_in_expr(expr)?, diff --git a/lib/skc_codegen/src/lib.rs b/lib/skc_codegen/src/lib.rs index 692d00ed..78edc14c 100644 --- a/lib/skc_codegen/src/lib.rs +++ b/lib/skc_codegen/src/lib.rs @@ -319,7 +319,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { #[allow(clippy::ptr_arg)] fn gen_user_main( &mut self, - main_exprs: &'hir HirExpressions, + main_exprs: &'hir HirExpression, main_lvars: &'hir HirLVars, ) -> Result<()> { // define void @user_main() @@ -330,7 +330,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { // alloca let mut main_lvars = main_lvars.clone(); - Self::collect_lvars_hir_expressions(main_exprs, &mut main_lvars); + Self::collect_lvars_hir_expression(main_exprs, &mut main_lvars); let lvar_ptrs = self.gen_alloca_lvars(function, &main_lvars); @@ -346,7 +346,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { self.builder.position_at_end(user_main_block); let (end_block, mut ctx) = self.new_ctx(FunctionOrigin::Other, function, lvar_ptrs); - self.gen_exprs(&mut ctx, main_exprs)?; + self.gen_expr(&mut ctx, main_exprs)?; self.builder.build_unconditional_branch(*end_block); self.builder.position_at_end(*end_block); self.builder.build_return(None); @@ -582,11 +582,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { // Should lvars of the clauses be collected ? clauses .iter() - .for_each(|clause| Self::collect_lvars_hir_expressions(&clause.body_hir, lvars)) - } - - fn collect_lvars_hir_expressions(exprs: &HirExpressions, lvars: &mut HirLVars) { - Self::collect_lvars_hir_vexpressions(&exprs.exprs, lvars) + .for_each(|clause| Self::collect_lvars_hir_expression(&clause.body_hir, lvars)) } fn collect_lvars_hir_vexpressions(exprs: &[HirExpression], lvars: &mut HirLVars) { @@ -621,8 +617,8 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { let mut if_lvars = if_lvars.clone(); lvars.append(&mut if_lvars); Self::collect_lvars_hir_expression(cond_expr, lvars); - Self::collect_lvars_hir_expressions(then_exprs, lvars); - Self::collect_lvars_hir_expressions(else_exprs, lvars); + Self::collect_lvars_hir_expression(then_exprs, lvars); + Self::collect_lvars_hir_expression(else_exprs, lvars); } HirExpressionBase::HirMatchExpression { cond_assign_expr, @@ -639,7 +635,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { let mut while_lvars = while_lvars.clone(); lvars.append(&mut while_lvars); Self::collect_lvars_hir_expression(cond_expr, lvars); - Self::collect_lvars_hir_expressions(body_exprs, lvars); + Self::collect_lvars_hir_expression(body_exprs, lvars); } HirExpressionBase::HirModuleMethodCall { receiver_expr, @@ -662,7 +658,9 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { Self::collect_lvars_hir_vexpressions(arg_exprs, lvars); } HirExpressionBase::HirParenthesizedExpr { exprs } => { - Self::collect_lvars_hir_expressions(exprs, lvars); + for expr in exprs { + Self::collect_lvars_hir_expression(expr, lvars); + } } HirExpressionBase::HirArgRef { .. } | HirExpressionBase::HirLambdaExpr { .. } @@ -683,11 +681,11 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { } } - fn collect_lvars_of_body(body: Either<&'hir SkMethodBody, &'hir HirExpressions>) -> HirLVars { + fn collect_lvars_of_body(body: Either<&'hir SkMethodBody, &'hir HirExpression>) -> HirLVars { let mut lvars = vec![]; match body { Left(SkMethodBody::Normal { exprs }) | Right(exprs) => { - Self::collect_lvars_hir_expressions(exprs, &mut lvars) + Self::collect_lvars_hir_expression(exprs, &mut lvars) } _ => (), } @@ -702,7 +700,7 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { func_name: &LlvmFuncName, params: &'hir [MethodParam], typarams: &'hir [TyParam], - body: Either<&'hir SkMethodBody, &'hir HirExpressions>, + body: Either<&'hir SkMethodBody, &'hir HirExpression>, lvars: &HirLVars, ret_ty: &TermTy, lambda_name: Option, @@ -825,11 +823,11 @@ impl<'hir: 'ictx, 'run, 'ictx: 'run> CodeGen<'hir, 'run, 'ictx> { function: inkwell::values::FunctionValue<'run>, function_origin: FunctionOrigin<'hir>, ret_ty: &TermTy, - exprs: &'hir HirExpressions, + exprs: &'hir HirExpression, lvars: HashMap>, ) -> Result<()> { let (end_block, mut ctx) = self.new_ctx(function_origin, function, lvars); - let (last_value, last_value_block) = if let Some(v) = self.gen_exprs(&mut ctx, exprs)? { + let (last_value, last_value_block) = if let Some(v) = self.gen_expr(&mut ctx, exprs)? { let b = self.context.append_basic_block(ctx.function, "Ret"); self.builder.build_unconditional_branch(b); self.builder.position_at_end(b); diff --git a/lib/skc_hir/src/lib.rs b/lib/skc_hir/src/lib.rs index 2b94309b..3d806af0 100644 --- a/lib/skc_hir/src/lib.rs +++ b/lib/skc_hir/src/lib.rs @@ -21,7 +21,7 @@ pub struct Hir { pub constants: HashMap, pub str_literals: Vec, pub const_inits: Vec, - pub main_exprs: HirExpressions, + pub main_exprs: HirExpression, /// Local variables in `main_exprs` pub main_lvars: HirLVars, } @@ -75,61 +75,8 @@ pub struct HirLVar { pub captured: bool, } -#[derive(Debug, Clone)] -pub struct HirExpressions { - pub ty: TermTy, - pub exprs: Vec, - pub locs: LocationSpan, -} - -impl HirExpressions { - /// Create a `HirExpressions` just returns Void - pub fn void() -> HirExpressions { - HirExpressions::new(vec![void_const_ref()]) - } - - /// Destructively convert Vec into HirExpressions - pub fn new(mut exprs: Vec) -> HirExpressions { - if exprs.is_empty() { - exprs.push(void_const_ref()); - } - let last_expr = exprs.last().unwrap(); - let ty = last_expr.ty.clone(); - let locs = LocationSpan::merge(&exprs.first().unwrap().locs, &last_expr.locs); - - HirExpressions { ty, exprs, locs } - } - - /// Prepend `exprs` to self - pub fn prepend(&mut self, exprs: Vec) { - if exprs.is_empty() { - return; - } - let mut v = std::mem::replace(&mut self.exprs, exprs); - self.exprs.append(&mut v); - } - - /// Change the type of `self` to `Void` - pub fn voidify(&mut self) { - self.exprs.push(void_const_ref()); - self.ty = ty::raw("Void"); - } - - /// Change the type of `self` to `ty` by bitcasting the result - pub fn bitcast_to(mut self, ty: TermTy) -> Self { - let last_expr = self.exprs.pop().unwrap(); - self.exprs.push(Hir::bit_cast(ty.clone(), last_expr)); - self.ty = ty; - self - } - - pub fn last_expr(&self) -> &HirExpression { - self.exprs.last().unwrap() - } -} - /// Make a HirExpression to refer `::Void` -pub fn void_const_ref() -> HirExpression { +fn void_const_ref() -> HirExpression { Hir::const_ref( ty::raw("Void"), toplevel_const("Void"), @@ -144,6 +91,20 @@ pub struct HirExpression { pub locs: LocationSpan, } +impl HirExpression { + pub fn voidify(self) -> HirExpression { + let exprs = vec![self, void_const_ref()]; + Hir::expressions(exprs) + } + + pub fn last_expr(&self) -> &HirExpression { + match &self.node { + HirExpressionBase::HirParenthesizedExpr { exprs } => exprs.last().unwrap(), + _ => panic!("unexpected"), + } + } +} + #[derive(Debug, Clone)] #[allow(clippy::large_enum_variant)] pub enum HirExpressionBase { @@ -161,8 +122,8 @@ pub enum HirExpressionBase { HirIfExpression { lvars: HirLVars, cond_expr: Box, - then_exprs: Box, - else_exprs: Box, // may be a dummy expression + then_exprs: Box, + else_exprs: Box, }, HirMatchExpression { cond_assign_expr: Box, @@ -171,7 +132,7 @@ pub enum HirExpressionBase { HirWhileExpression { lvars: HirLVars, cond_expr: Box, - body_exprs: Box, + body_exprs: Box, }, HirBreakExpression { from: HirBreakFrom, @@ -240,7 +201,7 @@ pub enum HirExpressionBase { HirLambdaExpr { name: String, params: Vec, - exprs: HirExpressions, + exprs: Box, captures: Vec, lvars: HirLVars, ret_ty: TermTy, @@ -291,7 +252,7 @@ pub enum HirExpressionBase { }, /// Wrap several expressions in to an expression HirParenthesizedExpr { - exprs: HirExpressions, + exprs: Vec, }, /// Only appears as an method call argument. Denotes using the default value. HirDefaultExpr, @@ -340,8 +301,14 @@ pub enum HirReturnFrom { } impl Hir { - pub fn expressions(exprs: Vec) -> HirExpressions { - HirExpressions::new(exprs) + pub fn expressions(mut exprs: Vec) -> HirExpression { + if exprs.is_empty() { + exprs.push(void_const_ref()); + } + let last_expr = exprs.last().unwrap(); + let ty = last_expr.ty.clone(); + let locs = LocationSpan::merge(&exprs.first().unwrap().locs, &last_expr.locs); + Hir::parenthesized_expression(ty, exprs, locs) } pub fn logical_not(expr_hir: HirExpression, locs: LocationSpan) -> HirExpression { @@ -387,8 +354,8 @@ impl Hir { pub fn if_expression( ty: TermTy, cond_hir: HirExpression, - then_hir: HirExpressions, - else_hir: HirExpressions, + then_hir: HirExpression, + else_hir: HirExpression, lvars: HirLVars, locs: LocationSpan, ) -> HirExpression { @@ -422,7 +389,7 @@ impl Hir { pub fn while_expression( cond_hir: HirExpression, - body_hirs: HirExpressions, + body_hirs: HirExpression, lvars: HirLVars, locs: LocationSpan, ) -> HirExpression { @@ -659,7 +626,7 @@ impl Hir { ty: TermTy, name: String, params: Vec, - exprs: HirExpressions, + exprs: HirExpression, captures: Vec, lvars: HirLVars, has_break: bool, @@ -671,7 +638,7 @@ impl Hir { node: HirExpressionBase::HirLambdaExpr { name, params, - exprs, + exprs: Box::new(exprs), captures, lvars, ret_ty, @@ -754,9 +721,13 @@ impl Hir { } } - pub fn parenthesized_expression(exprs: HirExpressions, locs: LocationSpan) -> HirExpression { + pub fn parenthesized_expression( + ty: TermTy, + exprs: Vec, + locs: LocationSpan, + ) -> HirExpression { HirExpression { - ty: exprs.ty.clone(), + ty, node: HirExpressionBase::HirParenthesizedExpr { exprs }, locs, } diff --git a/lib/skc_hir/src/pattern_match.rs b/lib/skc_hir/src/pattern_match.rs index ff4722c5..cdaa693e 100644 --- a/lib/skc_hir/src/pattern_match.rs +++ b/lib/skc_hir/src/pattern_match.rs @@ -1,4 +1,4 @@ -use crate::{HirExpression, HirExpressions, HirLVars}; +use crate::{HirExpression, HirLVars}; #[derive(Debug, Clone)] pub enum Component { @@ -11,7 +11,7 @@ pub enum Component { #[derive(Debug, Clone)] pub struct MatchClause { pub components: Vec, - pub body_hir: HirExpressions, + pub body_hir: HirExpression, /// Local variables declared in this clause pub lvars: HirLVars, } diff --git a/lib/skc_hir/src/sk_method.rs b/lib/skc_hir/src/sk_method.rs index 4a224d47..85428beb 100644 --- a/lib/skc_hir/src/sk_method.rs +++ b/lib/skc_hir/src/sk_method.rs @@ -1,5 +1,5 @@ use crate::signature::MethodSignature; -use crate::{HirExpressions, HirLVars}; +use crate::{HirExpression, HirLVars}; use shiika_core::names::*; use shiika_core::ty::TermTy; use std::collections::HashMap; @@ -16,7 +16,7 @@ pub type SkMethods = HashMap>; #[derive(Debug)] pub enum SkMethodBody { /// A method defined with Shiika expressions - Normal { exprs: HirExpressions }, + Normal { exprs: HirExpression }, /// A method defined in skc_rustlib RustLib, /// The method .new