From 323d77a455c7340d4622f9cb724e39da497db75e Mon Sep 17 00:00:00 2001 From: pca006132 Date: Mon, 28 Feb 2022 23:09:14 +0800 Subject: [PATCH] nac3artiq: improve error message for out of range error --- nac3artiq/src/codegen.rs | 12 +++---- nac3artiq/src/lib.rs | 8 +++-- nac3artiq/src/symbol_resolver.rs | 36 ++++++++++++-------- nac3core/src/codegen/expr.rs | 56 +++++++++++++++---------------- nac3core/src/codegen/irrt/mod.rs | 4 +-- nac3core/src/codegen/mod.rs | 3 +- nac3core/src/codegen/stmt.rs | 30 ++++++++--------- nac3core/src/symbol_resolver.rs | 6 ++-- nac3core/src/toplevel/builtins.rs | 36 ++++++++++---------- 9 files changed, 101 insertions(+), 90 deletions(-) diff --git a/nac3artiq/src/codegen.rs b/nac3artiq/src/codegen.rs index 9e949568..7b3da805 100644 --- a/nac3artiq/src/codegen.rs +++ b/nac3artiq/src/codegen.rs @@ -67,7 +67,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { ) -> Result>, String> { let result = gen_call(self, ctx, obj, fun, params)?; if let Some(end) = self.end.clone() { - let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self); + let old_end = self.gen_expr(ctx, &end)?.unwrap().to_basic_value_enum(ctx, self)?; let now = self.timeline.emit_now_mu(ctx); let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { let i64 = ctx.ctx.i64_type(); @@ -87,7 +87,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { ctx.builder.build_store(end_store, max); } if let Some(start) = self.start.clone() { - let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self); + let start_val = self.gen_expr(ctx, &start)?.unwrap().to_basic_value_enum(ctx, self)?; self.timeline.emit_at_mu(ctx, start_val); } Ok(result) @@ -119,7 +119,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { let old_start = self.start.take(); let old_end = self.end.take(); let now = if let Some(old_start) = &old_start { - self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self) + self.gen_expr(ctx, old_start)?.unwrap().to_basic_value_enum(ctx, self)? } else { self.timeline.emit_now_mu(ctx) }; @@ -174,7 +174,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { // set duration let end_expr = self.end.take().unwrap(); let end_val = - self.gen_expr(ctx, &end_expr)?.unwrap().to_basic_value_enum(ctx, self); + self.gen_expr(ctx, &end_expr)?.unwrap().to_basic_value_enum(ctx, self)?; // inside a sequential block if old_start.is_none() { @@ -185,7 +185,7 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> { let outer_end_val = self .gen_expr(ctx, old_end)? .unwrap() - .to_basic_value_enum(ctx, self); + .to_basic_value_enum(ctx, self)?; let smax = ctx.module.get_function("llvm.smax.i64").unwrap_or_else(|| { let i64 = ctx.ctx.i64_type(); @@ -370,7 +370,7 @@ fn rpc_codegen_callback_fn<'ctx, 'a>( .args .iter() .map(|arg| mapping.remove(&arg.name).unwrap().to_basic_value_enum(ctx, generator)) - .collect::>(); + .collect::, _>>()?; if let Some(obj) = obj { if let ValueEnum::Static(obj) = obj.1 { real_params.insert(0, obj.get_const_obj(ctx, generator)); diff --git a/nac3artiq/src/lib.rs b/nac3artiq/src/lib.rs index 9ce42969..99d257e5 100644 --- a/nac3artiq/src/lib.rs +++ b/nac3artiq/src/lib.rs @@ -295,7 +295,7 @@ impl Nac3 { vars: HashMap::new(), }, Arc::new(GenCall::new(Box::new(move |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator).unwrap(); time_fns.emit_at_mu(ctx, arg); Ok(None) }))), @@ -312,7 +312,7 @@ impl Nac3 { vars: HashMap::new(), }, Arc::new(GenCall::new(Box::new(move |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator).unwrap(); time_fns.emit_delay_mu(ctx, arg); Ok(None) }))), @@ -434,6 +434,7 @@ impl Nac3 { embedding_map: &PyAny, py: Python, ) -> PyResult<()> { + println!("start compilation"); let (mut composer, _, _) = TopLevelComposer::new( self.builtins.clone(), ComposerConfig { kernel_ann: Some("Kernel"), kernel_invariant_ann: "KernelInvariant" }, @@ -598,7 +599,7 @@ impl Nac3 { &mut composer.unifier, &self.primitive, ); - return Err(CompileError::new_err(msg.unwrap())); + return Err(CompileError::new_err(msg.unwrap_or(e))); } } let top_level = Arc::new(composer.make_top_level_context()); @@ -650,6 +651,7 @@ impl Nac3 { unreachable!() } }; + println!("typecheck complete"); let task = CodeGenTask { subst: Default::default(), diff --git a/nac3artiq/src/symbol_resolver.rs b/nac3artiq/src/symbol_resolver.rs index 0a79314c..5255100e 100644 --- a/nac3artiq/src/symbol_resolver.rs +++ b/nac3artiq/src/symbol_resolver.rs @@ -109,27 +109,26 @@ impl StaticValue for PythonValue { &self, ctx: &mut CodeGenContext<'ctx, 'a>, generator: &mut dyn CodeGenerator, - ) -> BasicValueEnum<'ctx> { + ) -> Result, String> { if let Some(val) = self.resolver.id_to_primitive.read().get(&self.id) { - return match val { + return Ok(match val { PrimitiveValue::I32(val) => ctx.ctx.i32_type().const_int(*val as u64, false).into(), PrimitiveValue::I64(val) => ctx.ctx.i64_type().const_int(*val as u64, false).into(), PrimitiveValue::F64(val) => ctx.ctx.f64_type().const_float(*val).into(), PrimitiveValue::Bool(val) => { ctx.ctx.bool_type().const_int(*val as u64, false).into() } - }; + }); } if let Some(global) = ctx.module.get_global(&self.id.to_string()) { - return global.as_pointer_value().into(); + return Ok(global.as_pointer_value().into()); } Python::with_gil(|py| -> PyResult> { self.resolver .get_obj_value(py, self.value.as_ref(py), ctx, generator) .map(Option::unwrap) - }) - .unwrap() + }).map_err(|e| e.to_string()) } fn get_field<'ctx, 'a>( @@ -594,19 +593,23 @@ impl InnerResolver { self.helper.id_fn.call1(py, (self.helper.type_fn.call1(py, (obj,))?,))?.extract(py)?; let id: u64 = self.helper.id_fn.call1(py, (obj,))?.extract(py)?; if ty_id == self.primitive_ids.int || ty_id == self.primitive_ids.int32 { - let val: i32 = obj.extract()?; + let val: i32 = obj.extract().map_err(|_| super::CompileError::new_err( + format!("{} is not in the range of int32", obj)))?; self.id_to_primitive.write().insert(id, PrimitiveValue::I32(val)); Ok(Some(ctx.ctx.i32_type().const_int(val as u64, false).into())) } else if ty_id == self.primitive_ids.int64 { - let val: i64 = obj.extract()?; + let val: i64 = obj.extract().map_err(|_| super::CompileError::new_err( + format!("{} is not in the range of int64", obj)))?; self.id_to_primitive.write().insert(id, PrimitiveValue::I64(val)); Ok(Some(ctx.ctx.i64_type().const_int(val as u64, false).into())) } else if ty_id == self.primitive_ids.bool { - let val: bool = obj.extract()?; + let val: bool = obj.extract().map_err(|_| super::CompileError::new_err( + format!("{} is not in the range of bool", obj)))?; self.id_to_primitive.write().insert(id, PrimitiveValue::Bool(val)); Ok(Some(ctx.ctx.bool_type().const_int(val as u64, false).into())) } else if ty_id == self.primitive_ids.float { - let val: f64 = obj.extract()?; + let val: f64 = obj.extract().map_err(|_| super::CompileError::new_err( + format!("{} is not in the range of float64", obj)))?; self.id_to_primitive.write().insert(id, PrimitiveValue::F64(val)); Ok(Some(ctx.ctx.f64_type().const_float(val).into())) } else if ty_id == self.primitive_ids.list { @@ -649,7 +652,8 @@ impl InnerResolver { let arr: Result>, _> = (0..len) .map(|i| { - obj.get_item(i).and_then(|elem| self.get_obj_value(py, elem, ctx, generator)) + obj.get_item(i).and_then(|elem| self.get_obj_value(py, elem, ctx, generator).map_err( + |e| super::CompileError::new_err(format!("Error getting element {}: {}", i, e)))) }) .collect(); let arr = arr?.unwrap(); @@ -699,7 +703,8 @@ impl InnerResolver { let elements: &PyTuple = obj.cast_as()?; let types: Result, _>, _> = elements .iter() - .map(|elem| { + .enumerate() + .map(|(i, elem)| { self.get_obj_type( py, elem, @@ -707,6 +712,7 @@ impl InnerResolver { &ctx.top_level.definitions.read(), &ctx.primitives, ) + .map_err(|e| super::CompileError::new_err(format!("Error getting element {}: {}", i, e))) .map(|ty| ty.map(|ty| ctx.get_llvm_type(generator, ty))) }) .collect(); @@ -725,7 +731,8 @@ impl InnerResolver { } let val: Result>, _> = - elements.iter().map(|elem| self.get_obj_value(py, elem, ctx, generator)).collect(); + elements.iter().enumerate().map(|(i, elem)| self.get_obj_value(py, elem, ctx, generator).map_err(|e| + super::CompileError::new_err(format!("Error getting element {}: {}", i, e)))).collect(); let val = val?.unwrap(); let val = ctx.ctx.const_struct(&val, false); let global = ctx.module.add_global(ty, Some(AddressSpace::Generic), &id_str); @@ -764,7 +771,8 @@ impl InnerResolver { let values: Result>, _> = fields .iter() .map(|(name, _, _)| { - self.get_obj_value(py, obj.getattr(&name.to_string())?, ctx, generator) + self.get_obj_value(py, obj.getattr(&name.to_string())?, ctx, generator).map_err(|e| + super::CompileError::new_err(format!("Error getting field {}: {}", name, e))) }) .collect(); let values = values?; diff --git a/nac3core/src/codegen/expr.rs b/nac3core/src/codegen/expr.rs index 975d0052..1b896186 100644 --- a/nac3core/src/codegen/expr.rs +++ b/nac3core/src/codegen/expr.rs @@ -576,7 +576,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>( param_vals = real_params .into_iter() .map(|p| p.to_basic_value_enum(ctx, generator)) - .collect_vec(); + .collect::, String>>()?; instance_to_symbol.get(&key).cloned().ok_or_else(|| "".into()) } TopLevelDef::Class { .. } => { @@ -661,7 +661,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( let cont_bb = ctx.ctx.append_basic_block(current, "cont"); let Comprehension { target, iter, ifs, .. } = &generators[0]; - let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator); + let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator)?; let int32 = ctx.ctx.i32_type(); let size_t = generator.get_size_type(ctx.ctx); let zero_size_t = size_t.const_zero(); @@ -766,7 +766,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( let result = generator .gen_expr(ctx, cond)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); let succ = ctx.ctx.append_basic_block(current, "then"); ctx.builder.build_conditional_branch(result, succ, test_bb); @@ -775,7 +775,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>( let elem = generator.gen_expr(ctx, elt)?.unwrap(); let i = ctx.builder.build_load(index, "i").into_int_value(); let elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") }; - let val = elem.to_basic_value_enum(ctx, generator); + let val = elem.to_basic_value_enum(ctx, generator)?; ctx.builder.build_store(elem_ptr, val); ctx.builder .build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc")); @@ -800,8 +800,8 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>( ) -> Result, String> { let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); - let left = generator.gen_expr(ctx, left)?.unwrap().to_basic_value_enum(ctx, generator); - let right = generator.gen_expr(ctx, right)?.unwrap().to_basic_value_enum(ctx, generator); + let left = generator.gen_expr(ctx, left)?.unwrap().to_basic_value_enum(ctx, generator)?; + let right = generator.gen_expr(ctx, right)?.unwrap().to_basic_value_enum(ctx, generator)?; // we can directly compare the types, because we've got their representatives // which would be unchanged until further unification, which we would never do @@ -856,7 +856,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( resolver .get_symbol_value(*id, ctx) .unwrap() - .to_basic_value_enum(ctx, generator), + .to_basic_value_enum(ctx, generator)?, ) { ctx.builder.build_load(ptr, "tup_val").into() } else { @@ -872,7 +872,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( .map(|x| { generator .gen_expr(ctx, x) - .map(|v| v.unwrap().to_basic_value_enum(ctx, generator)) + .map_or_else(|e| Err(e), |v| v.unwrap().to_basic_value_enum(ctx, generator)) }) .collect::, _>>()?; let ty = if elements.is_empty() { @@ -905,7 +905,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( .map(|x| { generator .gen_expr(ctx, x) - .map(|v| v.unwrap().to_basic_value_enum(ctx, generator)) + .map_or_else(|e| Err(e), |v| v.unwrap().to_basic_value_enum(ctx, generator)) }) .collect::, _>>()?; let element_ty = element_val.iter().map(BasicValueEnum::get_type).collect_vec(); @@ -926,14 +926,14 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( ExprKind::Attribute { value, attr, .. } => { // note that we would handle class methods directly in calls match generator.gen_expr(ctx, value)?.unwrap() { - ValueEnum::Static(v) => v.get_field(*attr, ctx).unwrap_or_else(|| { - let v = v.to_basic_value_enum(ctx, generator); + ValueEnum::Static(v) => v.get_field(*attr, ctx).map_or_else(|| { + let v = v.to_basic_value_enum(ctx, generator)?; let index = ctx.get_attr_index(value.custom.unwrap(), *attr); - ValueEnum::Dynamic(ctx.build_gep_and_load( + Ok(ValueEnum::Dynamic(ctx.build_gep_and_load( v.into_pointer_value(), &[zero, int32.const_int(index as u64, false)], - )) - }), + ))) as Result<_, String> + }, |v| Ok(v))?, ValueEnum::Dynamic(v) => { let index = ctx.get_attr_index(value.custom.unwrap(), *attr); ValueEnum::Dynamic(ctx.build_gep_and_load( @@ -948,7 +948,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let left = generator .gen_expr(ctx, &values[0])? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let a_bb = ctx.ctx.append_basic_block(current, "a"); @@ -964,7 +964,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let b = generator .gen_expr(ctx, &values[1])? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); ctx.builder.build_unconditional_branch(cont_bb); (a, b) @@ -974,7 +974,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let a = generator .gen_expr(ctx, &values[1])? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(b_bb); @@ -992,7 +992,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( ExprKind::UnaryOp { op, operand } => { let ty = ctx.unifier.get_representative(operand.custom.unwrap()); let val = - generator.gen_expr(ctx, operand)?.unwrap().to_basic_value_enum(ctx, generator); + generator.gen_expr(ctx, operand)?.unwrap().to_basic_value_enum(ctx, generator)?; if ty == ctx.primitives.bool { let val = val.into_int_value(); match op { @@ -1052,11 +1052,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( generator .gen_expr(ctx, lhs)? .unwrap() - .to_basic_value_enum(ctx, generator), + .to_basic_value_enum(ctx, generator)?, generator .gen_expr(ctx, rhs)? .unwrap() - .to_basic_value_enum(ctx, generator), + .to_basic_value_enum(ctx, generator)?, ) { (lhs, rhs) } else { @@ -1080,11 +1080,11 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( generator .gen_expr(ctx, lhs)? .unwrap() - .to_basic_value_enum(ctx, generator), + .to_basic_value_enum(ctx, generator)?, generator .gen_expr(ctx, rhs)? .unwrap() - .to_basic_value_enum(ctx, generator), + .to_basic_value_enum(ctx, generator)?, ) { (lhs, rhs) } else { @@ -1112,7 +1112,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let test = generator .gen_expr(ctx, test)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let then_bb = ctx.ctx.append_basic_block(current, "then"); @@ -1120,10 +1120,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let cont_bb = ctx.ctx.append_basic_block(current, "cont"); ctx.builder.build_conditional_branch(test, then_bb, else_bb); ctx.builder.position_at_end(then_bb); - let a = generator.gen_expr(ctx, body)?.unwrap().to_basic_value_enum(ctx, generator); + let a = generator.gen_expr(ctx, body)?.unwrap().to_basic_value_enum(ctx, generator)?; ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(else_bb); - let b = generator.gen_expr(ctx, orelse)?.unwrap().to_basic_value_enum(ctx, generator); + let b = generator.gen_expr(ctx, orelse)?.unwrap().to_basic_value_enum(ctx, generator)?; ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.position_at_end(cont_bb); let phi = ctx.builder.build_phi(a.get_type(), "ifexpr"); @@ -1208,7 +1208,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let v = generator .gen_expr(ctx, value)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_pointer_value(); let ty = ctx.get_llvm_type(generator, *ty); let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero]).into_pointer_value(); @@ -1254,7 +1254,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let raw_index = generator .gen_expr(ctx, slice)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); let raw_index = ctx.builder.build_int_s_extend( raw_index, @@ -1295,7 +1295,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>( let v = generator .gen_expr(ctx, value)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_struct_value(); let index: u32 = if let ExprKind::Constant { value: ast::Constant::Int(v), .. } = &slice.node { diff --git a/nac3core/src/codegen/irrt/mod.rs b/nac3core/src/codegen/irrt/mod.rs index bced56dc..d972878b 100644 --- a/nac3core/src/codegen/irrt/mod.rs +++ b/nac3core/src/codegen/irrt/mod.rs @@ -151,7 +151,7 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>( let step = generator .gen_expr(ctx, step)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); let len_id = ctx.builder.build_int_sub(length, one, "lenmin1"); let neg = ctx.builder.build_int_compare(IntPredicate::SLT, step, zero, "step_is_neg"); @@ -214,7 +214,7 @@ pub fn handle_slice_index_bound<'a, 'ctx, G: CodeGenerator>( ctx.module.add_function(SYMBOL, fn_t, None) }); - let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator); + let i = generator.gen_expr(ctx, i)?.unwrap().to_basic_value_enum(ctx, generator)?; Ok(ctx .builder .build_call(func, &[i.into(), length.into()], "bounded_ind") diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index c8c90f69..a76980fe 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -276,6 +276,7 @@ fn get_llvm_type<'ctx>( &*definition.read() { let struct_type = ctx.opaque_struct_type(&name.to_string()); + type_cache.insert(unifier.get_representative(ty), struct_type.ptr_type(AddressSpace::Generic).into()); let fields = fields_list .iter() .map(|f| { @@ -294,7 +295,7 @@ fn get_llvm_type<'ctx>( } else { unreachable!() }; - ty + return ty; } TTuple { ty } => { // a struct with fields in the order present in the tuple diff --git a/nac3core/src/codegen/stmt.rs b/nac3core/src/codegen/stmt.rs index 55919df0..96b39972 100644 --- a/nac3core/src/codegen/stmt.rs +++ b/nac3core/src/codegen/stmt.rs @@ -54,7 +54,7 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>( } ExprKind::Attribute { value, attr, .. } => { let index = ctx.get_attr_index(value.custom.unwrap(), *attr); - let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum(ctx, generator); + let val = generator.gen_expr(ctx, value)?.unwrap().to_basic_value_enum(ctx, generator)?; let ptr = if let BasicValueEnum::PointerValue(v) = val { v } else { @@ -76,12 +76,12 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>( let v = generator .gen_expr(ctx, value)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_pointer_value(); let index = generator .gen_expr(ctx, slice)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_int_value(); unsafe { let arr_ptr = ctx @@ -102,7 +102,7 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( ) -> Result<(), String> { match &target.node { ExprKind::Tuple { elts, .. } => { - if let BasicValueEnum::StructValue(v) = value.to_basic_value_enum(ctx, generator) { + if let BasicValueEnum::StructValue(v) = value.to_basic_value_enum(ctx, generator)? { for (i, elt) in elts.iter().enumerate() { let v = ctx .builder @@ -121,11 +121,11 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( let ls = generator .gen_expr(ctx, ls)? .unwrap() - .to_basic_value_enum(ctx, generator) + .to_basic_value_enum(ctx, generator)? .into_pointer_value(); let (start, end, step) = handle_slice_indices(lower, upper, step, ctx, generator, ls)?; - let value = value.to_basic_value_enum(ctx, generator).into_pointer_value(); + let value = value.to_basic_value_enum(ctx, generator)?.into_pointer_value(); let ty = if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(target.custom.unwrap()) { ctx.get_llvm_type(generator, *ty) @@ -155,7 +155,7 @@ pub fn gen_assign<'ctx, 'a, G: CodeGenerator>( *static_value = Some(s.clone()); } } - let val = value.to_basic_value_enum(ctx, generator); + let val = value.to_basic_value_enum(ctx, generator)?; ctx.builder.build_store(ptr, val); } }; @@ -185,7 +185,7 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>( // store loop bb information and restore it later let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); - let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator); + let iter_val = generator.gen_expr(ctx, iter)?.unwrap().to_basic_value_enum(ctx, generator)?; if ctx.unifier.unioned(iter.custom.unwrap(), ctx.primitives.range) { // setup let iter_val = iter_val.into_pointer_value(); @@ -296,7 +296,7 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>( let loop_bb = ctx.loop_target.replace((test_bb, cont_bb)); ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(test_bb); - let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator); + let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?; if let BasicValueEnum::IntValue(test) = test { ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); } else { @@ -357,7 +357,7 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>( }; ctx.builder.build_unconditional_branch(test_bb); ctx.builder.position_at_end(test_bb); - let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator); + let test = generator.gen_expr(ctx, test)?.unwrap().to_basic_value_enum(ctx, generator)?; if let BasicValueEnum::IntValue(test) = test { ctx.builder.build_conditional_branch(test, body_bb, orelse_bb); } else { @@ -454,7 +454,7 @@ pub fn exn_constructor<'ctx, 'a>( generator: &mut dyn CodeGenerator, ) -> Result>, String> { let (zelf_ty, zelf) = obj.unwrap(); - let zelf = zelf.to_basic_value_enum(ctx, generator).into_pointer_value(); + let zelf = zelf.to_basic_value_enum(ctx, generator)?.into_pointer_value(); let int32 = ctx.ctx.i32_type(); let zero = int32.const_zero(); let zelf_id = { @@ -477,14 +477,14 @@ pub fn exn_constructor<'ctx, 'a>( let ptr = ctx.builder.build_in_bounds_gep(zelf, &[zero, int32.const_int(5, false)], "exn.msg"); let msg = if !args.is_empty() { - args.remove(0).1.to_basic_value_enum(ctx, generator) + args.remove(0).1.to_basic_value_enum(ctx, generator)? } else { empty_string }; ctx.builder.build_store(ptr, msg); for i in [6, 7, 8].iter() { let value = if !args.is_empty() { - args.remove(0).1.to_basic_value_enum(ctx, generator) + args.remove(0).1.to_basic_value_enum(ctx, generator)? } else { ctx.ctx.i64_type().const_zero().into() }; @@ -900,7 +900,7 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>( ) -> Result<(), String> { let value = value .as_ref() - .map(|v| generator.gen_expr(ctx, v).map(|v| v.unwrap().to_basic_value_enum(ctx, generator))) + .map(|v| generator.gen_expr(ctx, v).and_then(|v| v.unwrap().to_basic_value_enum(ctx, generator))) .transpose()?; if let Some(return_target) = ctx.return_target { if let Some(value) = value { @@ -957,7 +957,7 @@ pub fn gen_stmt<'ctx, 'a, G: CodeGenerator>( StmtKind::Raise { exc, .. } => { if let Some(exc) = exc { let exc = - generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum(ctx, generator); + generator.gen_expr(ctx, exc)?.unwrap().to_basic_value_enum(ctx, generator)?; gen_raise(generator, ctx, Some(&exc), stmt.location); } else { gen_raise(generator, ctx, None, stmt.location); diff --git a/nac3core/src/symbol_resolver.rs b/nac3core/src/symbol_resolver.rs index d88200ab..a70c91bf 100644 --- a/nac3core/src/symbol_resolver.rs +++ b/nac3core/src/symbol_resolver.rs @@ -63,7 +63,7 @@ pub trait StaticValue { &self, ctx: &mut CodeGenContext<'ctx, 'a>, generator: &mut dyn CodeGenerator, - ) -> BasicValueEnum<'ctx>; + ) -> Result, String>; fn get_field<'ctx, 'a>( &self, @@ -107,10 +107,10 @@ impl<'ctx> ValueEnum<'ctx> { self, ctx: &mut CodeGenContext<'ctx, 'a>, generator: &mut dyn CodeGenerator, - ) -> BasicValueEnum<'ctx> { + ) -> Result, String> { match self { ValueEnum::Static(v) => v.to_basic_value_enum(ctx, generator), - ValueEnum::Dynamic(v) => v, + ValueEnum::Dynamic(v) => Ok(v), } } } diff --git a/nac3core/src/toplevel/builtins.rs b/nac3core/src/toplevel/builtins.rs index a48dd17b..f4a99ae3 100644 --- a/nac3core/src/toplevel/builtins.rs +++ b/nac3core/src/toplevel/builtins.rs @@ -194,7 +194,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; Ok(if ctx.unifier.unioned(arg_ty, boolean) { Some( ctx.builder @@ -253,7 +253,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; Ok( if ctx.unifier.unioned(arg_ty, boolean) || ctx.unifier.unioned(arg_ty, int32) @@ -306,7 +306,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let boolean = ctx.primitives.bool; let float = ctx.primitives.float; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; Ok( if ctx.unifier.unioned(arg_ty, boolean) || ctx.unifier.unioned(arg_ty, int32) @@ -342,7 +342,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; let round_intrinsic = ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -382,7 +382,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; let round_intrinsic = ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -442,17 +442,17 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let zero = int32.const_zero(); for (i, arg) in args.iter().enumerate() { if arg.0 == Some("start".into()) { - start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)); + start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); } else if arg.0 == Some("stop".into()) { - stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)); + stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); } else if arg.0 == Some("step".into()) { - step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)); + step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); } else if i == 0 { - start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)); + start = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); } else if i == 1 { - stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)); + stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); } else if i == 2 { - step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)); + step = Some(arg.1.clone().to_basic_value_enum(ctx, generator)?); } } // TODO: error when step == 0 @@ -500,7 +500,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - Ok(Some(args[0].1.clone().to_basic_value_enum(ctx, generator))) + Ok(Some(args[0].1.clone().to_basic_value_enum(ctx, generator)?)) }, )))), loc: None, @@ -524,7 +524,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { let float = ctx.primitives.float; let boolean = ctx.primitives.bool; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; Ok(if ctx.unifier.unioned(arg_ty, boolean) { Some(arg) } else if ctx.unifier.unioned(arg_ty, int32) { @@ -582,7 +582,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; let floor_intrinsic = ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -622,7 +622,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; let floor_intrinsic = ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -662,7 +662,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; let ceil_intrinsic = ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -702,7 +702,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { resolver: None, codegen_callback: Some(Arc::new(GenCall::new(Box::new( |ctx, _, _, args, generator| { - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; let ceil_intrinsic = ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| { let float = ctx.ctx.f64_type(); @@ -754,7 +754,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo { |ctx, _, fun, args, generator| { let range_ty = ctx.primitives.range; let arg_ty = fun.0.args[0].ty; - let arg = args[0].1.clone().to_basic_value_enum(ctx, generator); + let arg = args[0].1.clone().to_basic_value_enum(ctx, generator)?; Ok(if ctx.unifier.unioned(arg_ty, range_ty) { let arg = arg.into_pointer_value(); let (start, end, step) = destructure_range(ctx, arg);