Compare commits

..

6 Commits

Author SHA1 Message Date
David Mak 649874868a artiq: Implement handling for const generic variables 2023-12-08 13:02:35 +08:00
David Mak 638d9f8a30 core: Initial implementation for const generics 2023-12-08 13:02:31 +08:00
David Mak b9b725e78e core: Move some SymbolValue functions to symbol_resolver.rs 2023-12-08 13:01:12 +08:00
David Mak 7c41036c5c core: Codegen for ellipsis expression as NotImplemented
A lot of refactoring was performed, specifically with relaxing
expression codegen to return Option in case where ellipsis are used
within a subexpression.
2023-12-08 13:01:08 +08:00
David Mak aaaeccfc5a ast: Use `{filename}:{row}:{col}` for location output 2023-12-08 12:19:09 +08:00
David Mak 3b8309ae75 core: Infer builtins name list using builtin declaration list 2023-12-08 12:19:06 +08:00
7 changed files with 164 additions and 117 deletions

View File

@ -145,7 +145,8 @@ impl<'a> ArtiqCodeGenerator<'a> {
let end_store = self.gen_store_target( let end_store = self.gen_store_target(
ctx, ctx,
&end, &end,
store_name.map(|name| format!("{name}.addr")).as_deref())?; store_name.map(|name| format!("{name}.addr")).as_deref())?
.unwrap();
ctx.builder.build_store(end_store, max); ctx.builder.build_store(end_store, max);
} }
@ -261,7 +262,9 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: start, ctx: name_ctx.clone() }, node: ExprKind::Name { id: start, ctx: name_ctx.clone() },
custom: Some(ctx.primitives.int64), custom: Some(ctx.primitives.int64),
}; };
let start = self.gen_store_target(ctx, &start_expr, Some("start.addr"))?; let start = self
.gen_store_target(ctx, &start_expr, Some("start.addr"))?
.unwrap();
ctx.builder.build_store(start, now); ctx.builder.build_store(start, now);
Ok(Some(start_expr)) as Result<_, String> Ok(Some(start_expr)) as Result<_, String>
}, },
@ -274,7 +277,9 @@ impl<'b> CodeGenerator for ArtiqCodeGenerator<'b> {
node: ExprKind::Name { id: end, ctx: name_ctx.clone() }, node: ExprKind::Name { id: end, ctx: name_ctx.clone() },
custom: Some(ctx.primitives.int64), custom: Some(ctx.primitives.int64),
}; };
let end = self.gen_store_target(ctx, &end_expr, Some("end.addr"))?; let end = self
.gen_store_target(ctx, &end_expr, Some("end.addr"))?
.unwrap();
ctx.builder.build_store(end, now); ctx.builder.build_store(end, now);
self.end = Some(end_expr); self.end = Some(end_expr);
self.name_counter += 1; self.name_counter += 1;

View File

@ -265,7 +265,7 @@ impl<'ctx, 'a> CodeGenContext<'ctx, 'a> {
} }
} }
Constant::Ellipsis => { Constant::Ellipsis => {
let msg = self.gen_string(generator, ""); let msg = self.gen_string(generator, "NotImplementedError");
self.raise_exn( self.raise_exn(
generator, generator,
@ -967,9 +967,15 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(init_bb); ctx.builder.position_at_end(init_bb);
let Comprehension { target, iter, ifs, .. } = &generators[0]; let Comprehension { target, iter, ifs, .. } = &generators[0];
let iter_val = match generator.gen_expr(ctx, iter)? { let iter_val = if let Some(v) = generator.gen_expr(ctx, iter)? {
Some(v) => v.to_basic_value_enum(ctx, generator, iter.custom.unwrap())?, v.to_basic_value_enum(ctx, generator, iter.custom.unwrap())?
None => return Ok(None), } else {
for bb in [test_bb, body_bb, cont_bb] {
ctx.builder.position_at_end(bb);
ctx.builder.build_unreachable();
}
return Ok(None)
}; };
let int32 = ctx.ctx.i32_type(); let int32 = ctx.ctx.i32_type();
let size_t = generator.get_size_type(ctx.ctx); let size_t = generator.get_size_type(ctx.ctx);
@ -1013,9 +1019,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
list_content = ctx.build_gep_and_load(list, &[zero_size_t, zero_32], Some("listcomp.data.addr")) list_content = ctx.build_gep_and_load(list, &[zero_size_t, zero_32], Some("listcomp.data.addr"))
.into_pointer_value(); .into_pointer_value();
let Some(i) = generator.gen_store_target(ctx, target, Some("i.addr"))? else { let i = generator.gen_store_target(ctx, target, Some("i.addr"))?.unwrap();
unreachable!()
};
ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init")); ctx.builder.build_store(i, ctx.builder.build_int_sub(start, step, "start_init"));
ctx.builder.build_conditional_branch( ctx.builder.build_conditional_branch(
@ -1070,12 +1074,24 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
generator.gen_assign(ctx, target, val.into())?; generator.gen_assign(ctx, target, val.into())?;
} }
// Emits the content of `cont_bb`
let emit_cont_bb = |ctx: &CodeGenContext| {
ctx.builder.position_at_end(cont_bb);
let len_ptr = unsafe {
ctx.builder.build_gep(list, &[zero_size_t, int32.const_int(1, false)], "length")
};
ctx.builder.build_store(len_ptr, ctx.builder.build_load(index, "index"));
};
for cond in ifs.iter() { for cond in ifs.iter() {
let result = match generator.gen_expr(ctx, cond)? { let result = if let Some(v) = generator.gen_expr(ctx, cond)? {
Some(v) => v v.to_basic_value_enum(ctx, generator, cond.custom.unwrap())?.into_int_value()
.to_basic_value_enum(ctx, generator, cond.custom.unwrap())? } else {
.into_int_value(), // Bail if the predicate is an ellipsis - Emit cont_bb contents in case the
None => return Ok(None), // no element matches the predicate
emit_cont_bb(ctx);
return Ok(None)
}; };
let result = generator.bool_to_i1(ctx, result); let result = generator.bool_to_i1(ctx, result);
let succ = ctx.ctx.append_basic_block(current, "then"); let succ = ctx.ctx.append_basic_block(current, "then");
@ -1084,9 +1100,11 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(succ); ctx.builder.position_at_end(succ);
} }
let elem = match generator.gen_expr(ctx, elt)? { let Some(elem) = generator.gen_expr(ctx, elt)? else {
Some(v) => v, // Similarly, bail if the generator expression is an ellipsis, but keep cont_bb contents
None => return Ok(None), emit_cont_bb(ctx);
return Ok(None)
}; };
let i = ctx.builder.build_load(index, "i").into_int_value(); 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 elem_ptr = unsafe { ctx.builder.build_gep(list_content, &[i], "elem_ptr") };
@ -1096,11 +1114,7 @@ pub fn gen_comprehension<'ctx, 'a, G: CodeGenerator>(
.build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc")); .build_store(index, ctx.builder.build_int_add(i, size_t.const_int(1, false), "inc"));
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(cont_bb); emit_cont_bb(ctx);
let len_ptr = unsafe {
ctx.builder.build_gep(list, &[zero_size_t, int32.const_int(1, false)], "length")
};
ctx.builder.build_store(len_ptr, ctx.builder.build_load(index, "index"));
Ok(Some(list.into())) Ok(Some(list.into()))
} else { } else {
@ -1126,13 +1140,15 @@ pub fn gen_binop_expr<'ctx, 'a, G: CodeGenerator>(
) -> Result<Option<ValueEnum<'ctx>>, String> { ) -> Result<Option<ValueEnum<'ctx>>, String> {
let ty1 = ctx.unifier.get_representative(left.custom.unwrap()); let ty1 = ctx.unifier.get_representative(left.custom.unwrap());
let ty2 = ctx.unifier.get_representative(right.custom.unwrap()); let ty2 = ctx.unifier.get_representative(right.custom.unwrap());
let left_val = match generator.gen_expr(ctx, left)? { let left_val = if let Some(v) = generator.gen_expr(ctx, left)? {
Some(v) => v.to_basic_value_enum(ctx, generator, left.custom.unwrap())?, v.to_basic_value_enum(ctx, generator, left.custom.unwrap())?
None => return Ok(None), } else {
return Ok(None)
}; };
let right_val = match generator.gen_expr(ctx, right)? { let right_val = if let Some(v) = generator.gen_expr(ctx, right)? {
Some(v) => v.to_basic_value_enum(ctx, generator, right.custom.unwrap())?, v.to_basic_value_enum(ctx, generator, right.custom.unwrap())?
None => return Ok(None), } else {
return Ok(None)
}; };
// we can directly compare the types, because we've got their representatives // we can directly compare the types, because we've got their representatives
@ -1360,11 +1376,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
ExprKind::BoolOp { op, values } => { ExprKind::BoolOp { op, values } => {
// requires conditional branches for short-circuiting... // requires conditional branches for short-circuiting...
let left = match generator.gen_expr(ctx, &values[0])? { let left = if let Some(v) = generator.gen_expr(ctx, &values[0])? {
Some(v) => v v.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())?.into_int_value()
.to_basic_value_enum(ctx, generator, values[0].custom.unwrap())? } else {
.into_int_value(), return Ok(None)
None => return Ok(None),
}; };
let left = generator.bool_to_i1(ctx, left); let left = generator.bool_to_i1(ctx, left);
let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap(); let current = ctx.builder.get_insert_block().unwrap().get_parent().unwrap();
@ -1377,46 +1392,61 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(a_bb); ctx.builder.position_at_end(a_bb);
let a = ctx.ctx.i8_type().const_int(1, false); let a = ctx.ctx.i8_type().const_int(1, false);
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = match generator.gen_expr(ctx, &values[1])? { let b = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
Some(v) => let b = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())? let b = generator.bool_to_i8(ctx, b);
.into_int_value(), ctx.builder.build_unconditional_branch(cont_bb);
None => return Ok(None),
Some(b)
} else {
None
}; };
let b = generator.bool_to_i8(ctx, b);
ctx.builder.build_unconditional_branch(cont_bb); (Some(a), b)
(a, b)
} }
Boolop::And => { Boolop::And => {
ctx.builder.position_at_end(a_bb); ctx.builder.position_at_end(a_bb);
let a = match generator.gen_expr(ctx, &values[1])? { let a = if let Some(v) = generator.gen_expr(ctx, &values[1])? {
Some(v) => v let a = v.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())?.into_int_value();
.to_basic_value_enum(ctx, generator, values[1].custom.unwrap())? let a = generator.bool_to_i8(ctx, a);
.into_int_value(), ctx.builder.build_unconditional_branch(cont_bb);
None => return Ok(None),
Some(a)
} else {
None
}; };
let a = generator.bool_to_i8(ctx, a);
ctx.builder.build_unconditional_branch(cont_bb);
ctx.builder.position_at_end(b_bb); ctx.builder.position_at_end(b_bb);
let b = ctx.ctx.i8_type().const_zero(); let b = ctx.ctx.i8_type().const_zero();
ctx.builder.build_unconditional_branch(cont_bb); ctx.builder.build_unconditional_branch(cont_bb);
(a, b)
(a, Some(b))
} }
}; };
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), ""); match (a, b) {
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]); (Some(a), Some(b)) => {
phi.as_basic_value().into() let phi = ctx.builder.build_phi(ctx.ctx.i8_type(), "");
phi.add_incoming(&[(&a, a_bb), (&b, b_bb)]);
phi.as_basic_value().into()
}
(Some(a), None) => a.into(),
(None, Some(b)) => b.into(),
(None, None) => unreachable!(),
}
} }
ExprKind::BinOp { op, left, right } => { ExprKind::BinOp { op, left, right } => {
return gen_binop_expr(generator, ctx, left, op, right, expr.location, false); return gen_binop_expr(generator, ctx, left, op, right, expr.location, false);
} }
ExprKind::UnaryOp { op, operand } => { ExprKind::UnaryOp { op, operand } => {
let ty = ctx.unifier.get_representative(operand.custom.unwrap()); let ty = ctx.unifier.get_representative(operand.custom.unwrap());
let val = match generator.gen_expr(ctx, operand)? { let val = if let Some(v) = generator.gen_expr(ctx, operand)? {
Some(v) => v.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?, v.to_basic_value_enum(ctx, generator, operand.custom.unwrap())?
None => return Ok(None), } else {
return Ok(None)
}; };
if ty == ctx.primitives.bool { if ty == ctx.primitives.bool {
let val = val.into_int_value(); let val = val.into_int_value();
@ -1454,7 +1484,7 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
} }
ExprKind::Compare { left, ops, comparators } => { ExprKind::Compare { left, ops, comparators } => {
izip!(chain(once(left.as_ref()), comparators.iter()), comparators.iter(), ops.iter(),) let cmp_val = izip!(chain(once(left.as_ref()), comparators.iter()), comparators.iter(), ops.iter(),)
.fold(Ok(None), |prev: Result<Option<_>, String>, (lhs, rhs, op)| { .fold(Ok(None), |prev: Result<Option<_>, String>, (lhs, rhs, op)| {
let ty = ctx.unifier.get_representative(lhs.custom.unwrap()); let ty = ctx.unifier.get_representative(lhs.custom.unwrap());
let current = let current =
@ -1529,9 +1559,12 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
unimplemented!() unimplemented!()
}; };
Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp")).or(Some(current))) Ok(prev?.map(|v| ctx.builder.build_and(v, current, "cmp")).or(Some(current)))
})? })?;
.unwrap()
.into() // as there should be at least 1 element, it should never be none match cmp_val {
Some(v) => v.into(),
None => return Ok(None),
}
} }
ExprKind::IfExp { test, body, orelse } => { ExprKind::IfExp { test, body, orelse } => {
let test = match generator.gen_expr(ctx, test)? { let test = match generator.gen_expr(ctx, test)? {
@ -1580,9 +1613,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
ctx.builder.position_at_end(cont_bb); ctx.builder.position_at_end(cont_bb);
match result { if let Some(v) = result {
None => return Ok(None), ctx.builder.build_load(v, "if_exp_val_load").into()
Some(v) => return Ok(Some(ctx.builder.build_load(v, "if_exp_val_load").into())) } else {
return Ok(None)
} }
} }
ExprKind::Call { func, args, keywords } => { ExprKind::Call { func, args, keywords } => {
@ -1732,11 +1766,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
} }
ExprKind::Subscript { value, slice, .. } => { ExprKind::Subscript { value, slice, .. } => {
if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) { if let TypeEnum::TList { ty } = &*ctx.unifier.get_ty(value.custom.unwrap()) {
let v = match generator.gen_expr(ctx, value)? { let v = if let Some(v) = generator.gen_expr(ctx, value)? {
Some(v) => v v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value()
.to_basic_value_enum(ctx, generator, value.custom.unwrap())? } else {
.into_pointer_value(), return Ok(None)
None => return Ok(None),
}; };
let ty = ctx.get_llvm_type(generator, *ty); let ty = ctx.get_llvm_type(generator, *ty);
let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero], Some("arr.addr")) let arr_ptr = ctx.build_gep_and_load(v, &[zero, zero], Some("arr.addr"))
@ -1785,11 +1818,10 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
let len = ctx let len = ctx
.build_gep_and_load(v, &[zero, int32.const_int(1, false)], Some("len")) .build_gep_and_load(v, &[zero, int32.const_int(1, false)], Some("len"))
.into_int_value(); .into_int_value();
let raw_index = match generator.gen_expr(ctx, slice)? { let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? {
Some(v) => v v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value()
.to_basic_value_enum(ctx, generator, slice.custom.unwrap())? } else {
.into_int_value(), return Ok(None)
None => return Ok(None),
}; };
let raw_index = ctx.builder.build_int_s_extend( let raw_index = ctx.builder.build_int_s_extend(
raw_index, raw_index,
@ -1855,10 +1887,13 @@ pub fn gen_expr<'ctx, 'a, G: CodeGenerator>(
unreachable!("should not be other subscriptable types after type check"); unreachable!("should not be other subscriptable types after type check");
} }
}, },
ExprKind::ListComp { .. } => match gen_comprehension(generator, ctx, expr)? { ExprKind::ListComp { .. } => {
Some(v) => v.into(), if let Some(v) = gen_comprehension(generator, ctx, expr)? {
None => return Ok(None), v.into()
}, } else {
return Ok(None)
}
}
_ => unimplemented!(), _ => unimplemented!(),
})) }))
} }

View File

@ -166,22 +166,22 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32"); let length = ctx.builder.build_int_truncate_or_bit_cast(length, int32, "leni32");
Ok(Some(match (start, end, step) { Ok(Some(match (start, end, step) {
(s, e, None) => ( (s, e, None) => (
match s.as_ref() { if let Some(s) = s.as_ref() {
Some(s) => { match handle_slice_index_bound(s, ctx, generator, length)? {
if let Some(v) = handle_slice_index_bound(s, ctx, generator, length)? { Some(v) => v,
v None => return Ok(None),
} else { return Ok(None) }
} }
None => int32.const_zero(), } else {
int32.const_zero()
}, },
{ {
let e = match e.as_ref() { let e = if let Some(s) = e.as_ref() {
Some(s) => { match handle_slice_index_bound(s, ctx, generator, length)? {
if let Some(v) = handle_slice_index_bound(s, ctx, generator, length)? { Some(v) => v,
v None => return Ok(None),
} else { return Ok(None) }
} }
None => length, } else {
length
}; };
ctx.builder.build_int_sub(e, one, "final_end") ctx.builder.build_int_sub(e, one, "final_end")
}, },
@ -190,7 +190,9 @@ pub fn handle_slice_indices<'a, 'ctx, G: CodeGenerator>(
(s, e, Some(step)) => { (s, e, Some(step)) => {
let step = if let Some(v) = generator.gen_expr(ctx, step)? { let step = if let Some(v) = generator.gen_expr(ctx, step)? {
v.to_basic_value_enum(ctx, generator, ctx.primitives.int32)?.into_int_value() v.to_basic_value_enum(ctx, generator, ctx.primitives.int32)?.into_int_value()
} else { return Ok(None) }; } else {
return Ok(None)
};
// assert step != 0, throw exception if not // assert step != 0, throw exception if not
let not_zero = ctx.builder.build_int_compare( let not_zero = ctx.builder.build_int_compare(
IntPredicate::NE, IntPredicate::NE,
@ -273,7 +275,9 @@ pub fn handle_slice_index_bound<'a, 'ctx, G: CodeGenerator>(
let i = if let Some(v) = generator.gen_expr(ctx, i)? { let i = if let Some(v) = generator.gen_expr(ctx, i)? {
v.to_basic_value_enum(ctx, generator, i.custom.unwrap())? v.to_basic_value_enum(ctx, generator, i.custom.unwrap())?
} else { return Ok(None) }; } else {
return Ok(None)
};
Ok(Some(ctx Ok(Some(ctx
.builder .builder
.build_call(func, &[i.into(), length.into()], "bounded_ind") .build_call(func, &[i.into(), length.into()], "bounded_ind")

View File

@ -109,13 +109,17 @@ pub fn gen_store_target<'ctx, 'a, G: CodeGenerator>(
let zero = i32_type.const_zero(); let zero = i32_type.const_zero();
let v = if let Some(v) = generator.gen_expr(ctx, value)? { let v = if let Some(v) = generator.gen_expr(ctx, value)? {
v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value() v.to_basic_value_enum(ctx, generator, value.custom.unwrap())?.into_pointer_value()
} else { return Ok(None) }; } else {
return Ok(None)
};
let len = ctx let len = ctx
.build_gep_and_load(v, &[zero, i32_type.const_int(1, false)], Some("len")) .build_gep_and_load(v, &[zero, i32_type.const_int(1, false)], Some("len"))
.into_int_value(); .into_int_value();
let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? { let raw_index = if let Some(v) = generator.gen_expr(ctx, slice)? {
v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value() v.to_basic_value_enum(ctx, generator, slice.custom.unwrap())?.into_int_value()
} else { return Ok(None) }; } else {
return Ok(None)
};
let raw_index = ctx.builder.build_int_s_extend( let raw_index = ctx.builder.build_int_s_extend(
raw_index, raw_index,
generator.get_size_type(ctx.ctx), generator.get_size_type(ctx.ctx),
@ -272,13 +276,14 @@ pub fn gen_for<'ctx, 'a, G: CodeGenerator>(
// store loop bb information and restore it later // store loop bb information and restore it later
let loop_bb = ctx.loop_target.replace((incr_bb, cont_bb)); let loop_bb = ctx.loop_target.replace((incr_bb, cont_bb));
let iter_val = match generator.gen_expr(ctx, iter)? { let iter_val = if let Some(v) = generator.gen_expr(ctx, iter)? {
Some(v) => v.to_basic_value_enum( v.to_basic_value_enum(
ctx, ctx,
generator, generator,
iter.custom.unwrap(), iter.custom.unwrap(),
)?, )?
None => return Ok(()), } else {
return Ok(())
}; };
if is_iterable_range_expr { if is_iterable_range_expr {
let iter_val = iter_val.into_pointer_value(); let iter_val = iter_val.into_pointer_value();
@ -421,7 +426,14 @@ pub fn gen_while<'ctx, 'a, G: CodeGenerator>(
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = if let Some(v) = generator.gen_expr(ctx, test)? { let test = if let Some(v) = generator.gen_expr(ctx, test)? {
v.to_basic_value_enum(ctx, generator, test.custom.unwrap())? v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?
} else { return Ok(()) }; } else {
for bb in [body_bb, cont_bb] {
ctx.builder.position_at_end(bb);
ctx.builder.build_unreachable();
}
return Ok(())
};
if let BasicValueEnum::IntValue(test) = test { if let BasicValueEnum::IntValue(test) = test {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb); ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
} else { } else {
@ -483,14 +495,11 @@ pub fn gen_if<'ctx, 'a, G: CodeGenerator>(
}; };
ctx.builder.build_unconditional_branch(test_bb); ctx.builder.build_unconditional_branch(test_bb);
ctx.builder.position_at_end(test_bb); ctx.builder.position_at_end(test_bb);
let test = match generator.gen_expr(ctx, test)? { let test = generator
Some(v) => v.to_basic_value_enum(ctx, generator, test.custom.unwrap())?, .gen_expr(ctx, test)
None => return Ok(()), .and_then(|v| v.map(|v| v.to_basic_value_enum(ctx, generator, test.custom.unwrap())).transpose())?;
}; if let Some(BasicValueEnum::IntValue(test)) = test {
if let BasicValueEnum::IntValue(test) = test {
ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb); ctx.builder.build_conditional_branch(generator.bool_to_i1(ctx, test), body_bb, orelse_bb);
} else {
unreachable!()
}; };
ctx.builder.position_at_end(body_bb); ctx.builder.position_at_end(body_bb);
generator.gen_block(ctx, body.iter())?; generator.gen_block(ctx, body.iter())?;
@ -1043,11 +1052,12 @@ pub fn gen_return<'ctx, 'a, G: CodeGenerator>(
) -> Result<(), String> { ) -> Result<(), String> {
let func = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap(); let func = ctx.builder.get_insert_block().and_then(|bb| bb.get_parent()).unwrap();
let value = if let Some(v_expr) = value.as_ref() { let value = if let Some(v_expr) = value.as_ref() {
match generator.gen_expr(ctx, v_expr).transpose() { if let Some(v) = generator.gen_expr(ctx, v_expr).transpose() {
Some(v) => Some( Some(
v.and_then(|v| v.to_basic_value_enum(ctx, generator, v_expr.custom.unwrap()))? v.and_then(|v| v.to_basic_value_enum(ctx, generator, v_expr.custom.unwrap()))?
), )
None => return Ok(()) } else {
return Ok(())
} }
} else { } else {
None None

View File

@ -1,7 +0,0 @@
@extern
def output_str(x: str):
...
def run() -> int32:
[i for i in range(10) if ...]
return 0

View File

@ -76,7 +76,7 @@ fn handle_typevar_definition(
) -> Result<Type, String> { ) -> Result<Type, String> {
let ExprKind::Call { func, args, .. } = &var.node else { let ExprKind::Call { func, args, .. } = &var.node else {
return Err(format!( return Err(format!(
"expression {:?} cannot be handled as a TypeVar or ConstGeneric in global scope", "expression {:?} cannot be handled as a generic parameter in global scope",
var var
)) ))
}; };