diff --git a/lang/README.md b/lang/README.md index 9c6b2ed7..579a7747 100644 --- a/lang/README.md +++ b/lang/README.md @@ -514,9 +514,16 @@ note: this does not work on scalar values #### generic_functions ```hb -add := fn($T: type, a: T, b: T): T return a + b +add := fn($T: type, a: T, b: T): T { + if T != void { + return a + b + } +} main := fn(): uint { + add(void, { + }, { + }) return add(u32, 2, 2) - add(uint, 1, 3) } ``` diff --git a/lang/src/lib.rs b/lang/src/lib.rs index 19e67161..59995f11 100644 --- a/lang/src/lib.rs +++ b/lang/src/lib.rs @@ -340,6 +340,12 @@ pub mod ty { #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Id(NonZeroU32); + impl From for i64 { + fn from(value: Id) -> Self { + value.0.get() as _ + } + } + impl crate::ctx_map::CtxEntry for Id { type Ctx = crate::TypeIns; type Key<'a> = crate::SymKey<'a>; @@ -638,6 +644,12 @@ pub mod ty { } } + impl From<$variant> for i64 { + fn from(value: $variant) -> Self { + Id::from(value).into() + } + } + impl From<$variant> for Id { fn from(value: $variant) -> Self { $name::$variant(value).compress() diff --git a/lang/src/son.rs b/lang/src/son.rs index 41394a46..aef7ce54 100644 --- a/lang/src/son.rs +++ b/lang/src/son.rs @@ -19,6 +19,7 @@ use { }, alloc::{string::String, vec::Vec}, core::{ + any::Any, assert_matches::debug_assert_matches, cell::{Cell, RefCell}, fmt::{self, Debug, Display, Write}, @@ -768,12 +769,12 @@ impl Nodes { } stack.append(&mut self.queued_peeps); - debug_assert_matches!( - self.iter().find(|(i, n)| n.lock_rc.get() != 0 - && n.kind.is_peeped() - && !stack.contains(i)), - None - ); + //debug_assert_matches!( + // self.iter().find(|(i, n)| n.lock_rc.get() != 0 + // && n.kind.is_peeped() + // && !stack.contains(i)), + // None + //); } debug_assert!(self.queued_peeps.is_empty()); @@ -2748,6 +2749,9 @@ impl<'a> Codegen<'a> { Expr::Float { value, .. } => { self.gen_inferred_const(ctx, ty::Id::F32, value as i64, ty::Id::is_float) } + Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => { + Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, bt)) + } Expr::Ident { id, .. } if let Some(index) = self.ci.scope.vars.iter().rposition(|v| v.id == id) => { @@ -3108,6 +3112,8 @@ impl<'a> Codegen<'a> { _ if lhs.ty.is_pointer() || lhs.ty.is_integer() || lhs.ty == ty::Id::BOOL + || (lhs.ty == ty::Id::TYPE + && matches!(op, TokenKind::Eq | TokenKind::Ne)) || (lhs.ty.is_float() && op.is_supported_float_op()) => { self.strip_ptr(&mut lhs); @@ -3667,7 +3673,7 @@ impl<'a> Codegen<'a> { }); for var in self.ci.scope.vars.iter_mut().skip(self.ci.inline_var_base) { - if !var.ptr && var.value() != NEVER { + if var.ty != ty::Id::TYPE && !var.ptr { var.set_value(VOID, &mut self.ci.nodes); } } @@ -4141,7 +4147,13 @@ impl<'a> Codegen<'a> { while let (Some(aty), Some(arg)) = (tys.next(self.tys), args.next()) { let carg = cargs.next().unwrap(); let var = match aty { - Arg::Type(id) => Variable::new(carg.id, id, false, NEVER, &mut self.ci.nodes), + Arg::Type(id) => Variable::new( + carg.id, + ty::Id::TYPE, + false, + self.ci.nodes.new_const(ty::Id::TYPE, id), + &mut self.ci.nodes, + ), Arg::Value(ty) => { let mut value = self.raw_expr_ctx(arg, Ctx::default().with_ty(ty))?; self.strip_var(&mut value); @@ -4428,7 +4440,7 @@ impl<'a> Codegen<'a> { let sym = parser::find_symbol(&fast.symbols, carg.id); let ty = if sym.flags & idfl::COMPTIME == 0 { // FIXME: could fuck us - ty::Id::UNDECLARED + continue; } else { if ty != ty::Id::TYPE { self.error( @@ -4449,9 +4461,9 @@ impl<'a> Codegen<'a> { self.ci.scope.vars.push(Variable::new( carg.id, - ty, + ty::Id::TYPE, false, - NEVER, + self.ci.nodes.new_const(ty::Id::TYPE, ty), &mut self.ci.nodes, )); } @@ -4632,19 +4644,11 @@ impl<'a> Codegen<'a> { self.ci.pos.push(pos); let mut tys = sig.args.args(); - let mut args = args.iter(); + let mut argsi = args.iter(); while let Some(aty) = tys.next(self.tys) { - let arg = args.next().unwrap(); + let arg = argsi.next().unwrap(); match aty { - Arg::Type(ty) => { - self.ci.scope.vars.push(Variable::new( - arg.id, - ty, - false, - NEVER, - &mut self.ci.nodes, - )); - } + Arg::Type(_) => {} Arg::Value(ty) => { let mut deps = Vc::from([VOID]); if ty.loc(self.tys) == Loc::Stack && self.tys.size_of(ty) <= 16 { @@ -4668,6 +4672,24 @@ impl<'a> Codegen<'a> { } } + let mut tys = sig.args.args(); + let mut args = args.iter(); + while let Some(aty) = tys.next(self.tys) { + let arg = args.next().unwrap(); + match aty { + Arg::Type(ty) => { + self.ci.scope.vars.push(Variable::new( + arg.id, + ty::Id::TYPE, + false, + self.ci.nodes.new_const(ty::Id::TYPE, ty), + &mut self.ci.nodes, + )); + } + Arg::Value(_) => {} + } + } + if self.expr(body).is_some() { if sig.ret == ty::Id::VOID { self.expr(&Expr::Return { pos: body.pos(), val: None }); @@ -5018,21 +5040,39 @@ impl<'a> Codegen<'a> { fn eval_const(&mut self, file: Module, expr: &Expr, ret: ty::Id) -> u64 { self.ct.activate(); - let mut scope = mem::take(&mut self.ci.scope.vars); + let scope = self + .ci + .scope + .vars + .iter() + .filter(|v| v.ty == ty::Id::TYPE) + .map(|v| match self.ci.nodes[v.value.get()].kind { + Kind::CInt { value } => (value, v.id), + _ => unreachable!(), + }) + .collect::>(); self.pool.push_ci(file, Some(ret), self.tys.tasks.len(), &mut self.ci); - self.ci.scope.vars = scope; + self.ci.scope.vars = scope + .into_iter() + .map(|(v, id)| { + Variable::new( + id, + ty::Id::TYPE, + false, + self.ci.nodes.new_const(ty::Id::TYPE, v), + &mut self.ci.nodes, + ) + }) + .collect(); let prev_err_len = self.errors.borrow().len(); self.expr(&Expr::Return { pos: expr.pos(), val: Some(expr) }); - scope = mem::take(&mut self.ci.scope.vars); - let res = if self.finalize(prev_err_len) { self.emit_and_eval(file, ret, &mut []) } else { 1 }; self.pool.pop_ci(&mut self.ci); - self.ci.scope.vars = scope; self.ct.deactivate(); res @@ -5096,7 +5136,12 @@ impl<'a> Codegen<'a> { } fn find_local_ty(&mut self, ident: Ident) -> Option { - self.ci.scope.vars.iter().rfind(|v| (v.id == ident && v.value() == NEVER)).map(|v| v.ty) + self.ci.scope.vars.iter().rfind(|v| (v.id == ident && v.ty == ty::Id::TYPE)).map(|v| { + match self.ci.nodes[v.value.get()].kind { + Kind::CInt { value } => ty::Id::from(value as u64), + k => unreachable!("{k:?}"), + } + }) } fn find_type(