handling comptime known match
Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
95496116b0
commit
14cf5efaa5
|
@ -428,8 +428,10 @@ foo := @use("foo.hb")
|
||||||
|
|
||||||
main := fn(): uint {
|
main := fn(): uint {
|
||||||
byte := @as(u8, 10)
|
byte := @as(u8, 10)
|
||||||
|
_ = sum(byte, byte)
|
||||||
same_type_as_byte := @as(@TypeOf(byte), 30)
|
same_type_as_byte := @as(@TypeOf(byte), 30)
|
||||||
wide_uint := @as(u32, 40)
|
wide_uint := @as(u32, 40)
|
||||||
|
_ = sum(wide_uint, wide_uint)
|
||||||
truncated_uint := @as(u8, @intcast(wide_uint))
|
truncated_uint := @as(u8, @intcast(wide_uint))
|
||||||
widened_float := @as(f64, @floatcast(1.))
|
widened_float := @as(f64, @floatcast(1.))
|
||||||
int_from_float := @as(int, @fti(1.))
|
int_from_float := @as(int, @fti(1.))
|
||||||
|
@ -445,6 +447,8 @@ main := fn(): uint {
|
||||||
return @inline(foo.foo)
|
return @inline(foo.foo)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$sum := fn(a: @any(), b: @TypeOf(a)): @TypeOf(a) return a + b
|
||||||
|
|
||||||
// in module: foo.hb
|
// in module: foo.hb
|
||||||
|
|
||||||
Type := struct {
|
Type := struct {
|
||||||
|
|
|
@ -707,7 +707,7 @@ impl Nodes {
|
||||||
let free = self.free;
|
let free = self.free;
|
||||||
for &d in node.inputs.as_slice() {
|
for &d in node.inputs.as_slice() {
|
||||||
debug_assert_ne!(d, free);
|
debug_assert_ne!(d, free);
|
||||||
self.values[d as usize].as_mut().unwrap_or_else(|_| panic!("{d}")).outputs.push(free);
|
self.values[d as usize].as_mut().unwrap_or_else(|_| panic!("{d} ")).outputs.push(free);
|
||||||
}
|
}
|
||||||
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err().0;
|
self.free = mem::replace(&mut self.values[free as usize], Ok(node)).unwrap_err().0;
|
||||||
|
|
||||||
|
|
156
lang/src/son.rs
156
lang/src/son.rs
|
@ -2106,62 +2106,112 @@ impl<'a> Codegen<'a> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut covered_values = vec![Pos::MAX; self.tys.enum_field_range(e).len()];
|
let mut covered_values = vec![Pos::MAX; self.tys.enum_field_range(e).len()];
|
||||||
let mut scopes = vec![];
|
|
||||||
let mut else_branch = None::<Expr>;
|
let mut else_branch = None::<Expr>;
|
||||||
for &MatchBranch { pat, pos: bp, body } in branches {
|
|
||||||
if let Expr::Wildcard { .. } = pat {
|
if let Kind::CInt { value: cnst } = self.ci.nodes[value.id].kind {
|
||||||
if let Some(prev) = else_branch {
|
let mut matching_branch = None::<Expr>;
|
||||||
self.error(bp, "duplicate branch");
|
for &MatchBranch { pat, pos: bp, body } in branches {
|
||||||
self.error(prev.pos(), "...first branch declared here");
|
if let Expr::Wildcard { .. } = pat {
|
||||||
|
if let Some(prev) = else_branch {
|
||||||
|
self.error(bp, "duplicate branch");
|
||||||
|
self.error(prev.pos(), "...first branch declared here");
|
||||||
|
}
|
||||||
|
|
||||||
|
else_branch = Some(body);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
else_branch = Some(body);
|
let pat_val = self.eval_const(self.ci.file, self.ci.parent, &pat, value.ty);
|
||||||
continue;
|
if covered_values[pat_val as usize] != Pos::MAX {
|
||||||
|
self.error(bp, "duplicate branch");
|
||||||
|
self.error(
|
||||||
|
covered_values[pat_val as usize],
|
||||||
|
"...first branch declared here",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
covered_values[pat_val as usize] = bp;
|
||||||
|
|
||||||
|
if pat_val == cnst as u64 {
|
||||||
|
matching_branch = Some(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let pat_val = self.eval_const(self.ci.file, self.ci.parent, &pat, value.ty);
|
if let Some(body) = else_branch.or(matching_branch) {
|
||||||
if covered_values[pat_val as usize] != Pos::MAX {
|
self.expr(&body)?;
|
||||||
self.error(bp, "duplicate branch");
|
}
|
||||||
self.error(
|
} else {
|
||||||
covered_values[pat_val as usize],
|
let mut scopes = vec![];
|
||||||
"...first branch declared here",
|
for &MatchBranch { pat, pos: bp, body } in branches {
|
||||||
|
if let Expr::Wildcard { .. } = pat {
|
||||||
|
if let Some(prev) = else_branch {
|
||||||
|
self.error(bp, "duplicate branch");
|
||||||
|
self.error(prev.pos(), "...first branch declared here");
|
||||||
|
}
|
||||||
|
|
||||||
|
else_branch = Some(body);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let pat_val = self.eval_const(self.ci.file, self.ci.parent, &pat, value.ty);
|
||||||
|
if covered_values[pat_val as usize] != Pos::MAX {
|
||||||
|
self.error(bp, "duplicate branch");
|
||||||
|
self.error(
|
||||||
|
covered_values[pat_val as usize],
|
||||||
|
"...first branch declared here",
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
covered_values[pat_val as usize] = bp;
|
||||||
|
|
||||||
|
let pat_val = self.ci.nodes.new_const(value.ty, pat_val as i64);
|
||||||
|
let cnd = self.ci.nodes.new_node(
|
||||||
|
ty::Id::BOOL,
|
||||||
|
Kind::BinOp { op: TokenKind::Eq },
|
||||||
|
[VOID, value.id, pat_val],
|
||||||
|
self.tys,
|
||||||
|
);
|
||||||
|
|
||||||
|
let if_node = self.ci.nodes.new_node(
|
||||||
|
ty::Id::VOID,
|
||||||
|
Kind::If,
|
||||||
|
[self.ci.ctrl.get(), cnd],
|
||||||
|
self.tys,
|
||||||
|
);
|
||||||
|
|
||||||
|
let cached_scope = self.ci.scope.dup(&mut self.ci.nodes);
|
||||||
|
self.ci.ctrl.set(
|
||||||
|
self.ci.nodes.new_node(ty::Id::VOID, Kind::Then, [if_node], self.tys),
|
||||||
|
&mut self.ci.nodes,
|
||||||
|
);
|
||||||
|
let ctrl = self.expr(&body).map_or(Nid::MAX, |_| self.ci.ctrl.get());
|
||||||
|
scopes.push((ctrl, mem::replace(&mut self.ci.scope, cached_scope)));
|
||||||
|
|
||||||
|
self.ci.ctrl.set(
|
||||||
|
self.ci.nodes.new_node(ty::Id::VOID, Kind::Else, [if_node], self.tys),
|
||||||
|
&mut self.ci.nodes,
|
||||||
);
|
);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
covered_values[pat_val as usize] = bp;
|
let mut rcntrl = if let Some(ebr) = else_branch {
|
||||||
|
self.expr(&ebr).map_or(Nid::MAX, |_| self.ci.ctrl.get())
|
||||||
|
} else {
|
||||||
|
self.ci.ctrl.get()
|
||||||
|
};
|
||||||
|
|
||||||
let pat_val = self.ci.nodes.new_const(value.ty, pat_val as i64);
|
for (lcntrl, then_scope) in scopes.into_iter().rev() {
|
||||||
let cnd = self.ci.nodes.new_node(
|
if let Some(v) = self.close_if(lcntrl, rcntrl, then_scope)
|
||||||
ty::Id::BOOL,
|
&& v != VOID
|
||||||
Kind::BinOp { op: TokenKind::Eq },
|
{
|
||||||
[VOID, value.id, pat_val],
|
rcntrl = v;
|
||||||
self.tys,
|
}
|
||||||
);
|
}
|
||||||
|
|
||||||
let if_node = self.ci.nodes.new_node(
|
if rcntrl == Nid::MAX {
|
||||||
ty::Id::VOID,
|
return None;
|
||||||
Kind::If,
|
}
|
||||||
[self.ci.ctrl.get(), cnd],
|
|
||||||
self.tys,
|
|
||||||
);
|
|
||||||
|
|
||||||
let cached_scope = self.ci.scope.dup(&mut self.ci.nodes);
|
|
||||||
self.ci.ctrl.set(
|
|
||||||
self.ci.nodes.new_node(ty::Id::VOID, Kind::Then, [if_node], self.tys),
|
|
||||||
&mut self.ci.nodes,
|
|
||||||
);
|
|
||||||
let ctrl = self.expr(&body).map_or(Nid::MAX, |_| self.ci.ctrl.get());
|
|
||||||
scopes.push((ctrl, mem::replace(&mut self.ci.scope, cached_scope)));
|
|
||||||
|
|
||||||
self.ci.ctrl.set(
|
|
||||||
self.ci.nodes.new_node(ty::Id::VOID, Kind::Else, [if_node], self.tys),
|
|
||||||
&mut self.ci.nodes,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rcntrl = if let Some(ebr) = else_branch {
|
if else_branch.is_none() {
|
||||||
self.expr(&ebr).map_or(Nid::MAX, |_| self.ci.ctrl.get())
|
|
||||||
} else {
|
|
||||||
let missing_branches = covered_values
|
let missing_branches = covered_values
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(self.tys.enum_fields(e))
|
.zip(self.tys.enum_fields(e))
|
||||||
|
@ -2173,19 +2223,6 @@ impl<'a> Codegen<'a> {
|
||||||
if !missing_branches.is_empty() {
|
if !missing_branches.is_empty() {
|
||||||
self.error(pos, fa!("not all cases covered, missing '{missing_branches}'"));
|
self.error(pos, fa!("not all cases covered, missing '{missing_branches}'"));
|
||||||
}
|
}
|
||||||
self.ci.ctrl.get()
|
|
||||||
};
|
|
||||||
|
|
||||||
for (lcntrl, then_scope) in scopes.into_iter().rev() {
|
|
||||||
if let Some(v) = self.close_if(lcntrl, rcntrl, then_scope)
|
|
||||||
&& v != VOID
|
|
||||||
{
|
|
||||||
rcntrl = v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if rcntrl == Nid::MAX {
|
|
||||||
return None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
|
@ -3817,6 +3854,9 @@ impl<'a> Codegen<'a> {
|
||||||
break 'b None;
|
break 'b None;
|
||||||
}
|
}
|
||||||
let ty = self.parse_ty(sc.anon(), &arg.ty);
|
let ty = self.parse_ty(sc.anon(), &arg.ty);
|
||||||
|
if ty == ty::Id::ANY_TYPE {
|
||||||
|
break 'b None;
|
||||||
|
}
|
||||||
self.tys.tmp.args.push(ty);
|
self.tys.tmp.args.push(ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -380,6 +380,7 @@ builtin_type! {
|
||||||
INT;
|
INT;
|
||||||
F32;
|
F32;
|
||||||
F64;
|
F64;
|
||||||
|
ANY_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! type_kind {
|
macro_rules! type_kind {
|
||||||
|
|
Loading…
Reference in a new issue