allowing compatison of types

This commit is contained in:
Jakub Doka 2024-11-23 15:28:02 +01:00
parent aa83ed2ec9
commit fb119bc6eb
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
3 changed files with 93 additions and 29 deletions

View file

@ -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)
}
```

View file

@ -340,6 +340,12 @@ pub mod ty {
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Id(NonZeroU32);
impl From<Id> 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()

View file

@ -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::<Vec<_>>();
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<ty::Id> {
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(