Compare commits
6 Commits
e7add9ea0d
...
649874868a
Author | SHA1 | Date |
---|---|---|
David Mak | 649874868a | |
David Mak | 638d9f8a30 | |
David Mak | b9b725e78e | |
David Mak | 7c41036c5c | |
David Mak | aaaeccfc5a | |
David Mak | 3b8309ae75 |
|
@ -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;
|
||||||
|
|
|
@ -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!(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
@extern
|
|
||||||
def output_str(x: str):
|
|
||||||
...
|
|
||||||
|
|
||||||
def run() -> int32:
|
|
||||||
[i for i in range(10) if ...]
|
|
||||||
return 0
|
|
|
@ -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
|
||||||
))
|
))
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue