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 #### generic_functions
```hb ```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 { main := fn(): uint {
add(void, {
}, {
})
return add(u32, 2, 2) - add(uint, 1, 3) 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)] #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub struct Id(NonZeroU32); 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 { impl crate::ctx_map::CtxEntry for Id {
type Ctx = crate::TypeIns; type Ctx = crate::TypeIns;
type Key<'a> = crate::SymKey<'a>; 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 { impl From<$variant> for Id {
fn from(value: $variant) -> Self { fn from(value: $variant) -> Self {
$name::$variant(value).compress() $name::$variant(value).compress()

View file

@ -19,6 +19,7 @@ use {
}, },
alloc::{string::String, vec::Vec}, alloc::{string::String, vec::Vec},
core::{ core::{
any::Any,
assert_matches::debug_assert_matches, assert_matches::debug_assert_matches,
cell::{Cell, RefCell}, cell::{Cell, RefCell},
fmt::{self, Debug, Display, Write}, fmt::{self, Debug, Display, Write},
@ -768,12 +769,12 @@ impl Nodes {
} }
stack.append(&mut self.queued_peeps); stack.append(&mut self.queued_peeps);
debug_assert_matches!( //debug_assert_matches!(
self.iter().find(|(i, n)| n.lock_rc.get() != 0 // self.iter().find(|(i, n)| n.lock_rc.get() != 0
&& n.kind.is_peeped() // && n.kind.is_peeped()
&& !stack.contains(i)), // && !stack.contains(i)),
None // None
); //);
} }
debug_assert!(self.queued_peeps.is_empty()); debug_assert!(self.queued_peeps.is_empty());
@ -2748,6 +2749,9 @@ impl<'a> Codegen<'a> {
Expr::Float { value, .. } => { Expr::Float { value, .. } => {
self.gen_inferred_const(ctx, ty::Id::F32, value as i64, ty::Id::is_float) 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, .. } Expr::Ident { id, .. }
if let Some(index) = self.ci.scope.vars.iter().rposition(|v| v.id == 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() _ if lhs.ty.is_pointer()
|| lhs.ty.is_integer() || lhs.ty.is_integer()
|| lhs.ty == ty::Id::BOOL || 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()) => || (lhs.ty.is_float() && op.is_supported_float_op()) =>
{ {
self.strip_ptr(&mut lhs); 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) { 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); 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()) { while let (Some(aty), Some(arg)) = (tys.next(self.tys), args.next()) {
let carg = cargs.next().unwrap(); let carg = cargs.next().unwrap();
let var = match aty { 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) => { Arg::Value(ty) => {
let mut value = self.raw_expr_ctx(arg, Ctx::default().with_ty(ty))?; let mut value = self.raw_expr_ctx(arg, Ctx::default().with_ty(ty))?;
self.strip_var(&mut value); self.strip_var(&mut value);
@ -4428,7 +4440,7 @@ impl<'a> Codegen<'a> {
let sym = parser::find_symbol(&fast.symbols, carg.id); let sym = parser::find_symbol(&fast.symbols, carg.id);
let ty = if sym.flags & idfl::COMPTIME == 0 { let ty = if sym.flags & idfl::COMPTIME == 0 {
// FIXME: could fuck us // FIXME: could fuck us
ty::Id::UNDECLARED continue;
} else { } else {
if ty != ty::Id::TYPE { if ty != ty::Id::TYPE {
self.error( self.error(
@ -4449,9 +4461,9 @@ impl<'a> Codegen<'a> {
self.ci.scope.vars.push(Variable::new( self.ci.scope.vars.push(Variable::new(
carg.id, carg.id,
ty, ty::Id::TYPE,
false, false,
NEVER, self.ci.nodes.new_const(ty::Id::TYPE, ty),
&mut self.ci.nodes, &mut self.ci.nodes,
)); ));
} }
@ -4632,19 +4644,11 @@ impl<'a> Codegen<'a> {
self.ci.pos.push(pos); self.ci.pos.push(pos);
let mut tys = sig.args.args(); let mut tys = sig.args.args();
let mut args = args.iter(); let mut argsi = args.iter();
while let Some(aty) = tys.next(self.tys) { while let Some(aty) = tys.next(self.tys) {
let arg = args.next().unwrap(); let arg = argsi.next().unwrap();
match aty { match aty {
Arg::Type(ty) => { Arg::Type(_) => {}
self.ci.scope.vars.push(Variable::new(
arg.id,
ty,
false,
NEVER,
&mut self.ci.nodes,
));
}
Arg::Value(ty) => { Arg::Value(ty) => {
let mut deps = Vc::from([VOID]); let mut deps = Vc::from([VOID]);
if ty.loc(self.tys) == Loc::Stack && self.tys.size_of(ty) <= 16 { 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 self.expr(body).is_some() {
if sig.ret == ty::Id::VOID { if sig.ret == ty::Id::VOID {
self.expr(&Expr::Return { pos: body.pos(), val: None }); 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 { fn eval_const(&mut self, file: Module, expr: &Expr, ret: ty::Id) -> u64 {
self.ct.activate(); 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.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(); let prev_err_len = self.errors.borrow().len();
self.expr(&Expr::Return { pos: expr.pos(), val: Some(expr) }); self.expr(&Expr::Return { pos: expr.pos(), val: Some(expr) });
scope = mem::take(&mut self.ci.scope.vars);
let res = let res =
if self.finalize(prev_err_len) { self.emit_and_eval(file, ret, &mut []) } else { 1 }; if self.finalize(prev_err_len) { self.emit_and_eval(file, ret, &mut []) } else { 1 };
self.pool.pop_ci(&mut self.ci); self.pool.pop_ci(&mut self.ci);
self.ci.scope.vars = scope;
self.ct.deactivate(); self.ct.deactivate();
res res
@ -5096,7 +5136,12 @@ impl<'a> Codegen<'a> {
} }
fn find_local_ty(&mut self, ident: Ident) -> Option<ty::Id> { 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( fn find_type(