forked from AbleOS/holey-bytes
Dividing function into template and instance, rmoving cumbersome options
Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
c5d5301b7b
commit
71ba2c2486
|
@ -273,7 +273,7 @@ impl Backend for HbvmBackend {
|
||||||
tys: &Types,
|
tys: &Types,
|
||||||
files: &EntSlice<Module, parser::Ast>,
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
) {
|
) {
|
||||||
let sig = tys.ins.funcs[id].sig.unwrap();
|
let sig = tys.ins.funcs[id].sig;
|
||||||
|
|
||||||
debug_assert!(self.code.is_empty());
|
debug_assert!(self.code.is_empty());
|
||||||
|
|
||||||
|
|
|
@ -272,6 +272,10 @@ impl Ident {
|
||||||
self.0 & ((1 << Self::LEN_BITS) - 1)
|
self.0 & ((1 << Self::LEN_BITS) - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_type(self) -> bool {
|
||||||
|
ty::Builtin::try_from(self) == Ok(ty::Builtin::TYPE)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_empty(self) -> bool {
|
pub fn is_empty(self) -> bool {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|
269
lang/src/son.rs
269
lang/src/son.rs
|
@ -16,7 +16,7 @@ use {
|
||||||
ty::{
|
ty::{
|
||||||
self, Arg, ArrayLen, CompState, ConstData, EnumData, EnumField, FTask, FuncData,
|
self, Arg, ArrayLen, CompState, ConstData, EnumData, EnumField, FTask, FuncData,
|
||||||
GlobalData, Loc, Module, Offset, OffsetIter, OptLayout, Sig, StringRef, StructData,
|
GlobalData, Loc, Module, Offset, OffsetIter, OptLayout, Sig, StringRef, StructData,
|
||||||
StructField, SymKey, Tuple, TypeBase, TypeIns, Types, UnionData,
|
StructField, SymKey, TemplateData, Tuple, TypeBase, TypeIns, Types, UnionData,
|
||||||
},
|
},
|
||||||
utils::{BitSet, EntSlice, Vc},
|
utils::{BitSet, EntSlice, Vc},
|
||||||
Ident,
|
Ident,
|
||||||
|
@ -2782,7 +2782,7 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
let fuc = self.tys.ins.funcs.push(FuncData {
|
let fuc = self.tys.ins.funcs.push(FuncData {
|
||||||
file,
|
file,
|
||||||
sig: Some(Sig { args: Tuple::empty(), ret }),
|
sig: Sig { args: Tuple::empty(), ret },
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2894,8 +2894,8 @@ impl<'a> Codegen<'a> {
|
||||||
fn make_func_reachable(&mut self, func: ty::Func) {
|
fn make_func_reachable(&mut self, func: ty::Func) {
|
||||||
let state_slot = self.ct.active() as usize;
|
let state_slot = self.ct.active() as usize;
|
||||||
let fuc = &mut self.tys.ins.funcs[func];
|
let fuc = &mut self.tys.ins.funcs[func];
|
||||||
if fuc.comp_state[state_slot] == CompState::Dead {
|
if CompState::from(fuc.comp_state[state_slot]) == CompState::Dead {
|
||||||
fuc.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len() as _);
|
fuc.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len() as _).into();
|
||||||
self.tys.tasks.push(Some(FTask { file: fuc.file, id: func, ct: self.ct.active() }));
|
self.tys.tasks.push(Some(FTask { file: fuc.file, id: func, ct: self.ct.active() }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4231,12 +4231,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
ref e => {
|
ref e => {
|
||||||
let ty = self.parse_ty(
|
let ty = self.parse_ty(
|
||||||
TyScope {
|
TyScope { file: self.ci.file, parent: self.ci.parent, ..Default::default() },
|
||||||
file: self.ci.file,
|
|
||||||
parent: self.ci.parent,
|
|
||||||
name: None,
|
|
||||||
alloc_const: false,
|
|
||||||
},
|
|
||||||
e,
|
e,
|
||||||
);
|
);
|
||||||
Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, ty))
|
Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, ty))
|
||||||
|
@ -4327,6 +4322,7 @@ impl<'a> Codegen<'a> {
|
||||||
| ty::Kind::Slice(_)
|
| ty::Kind::Slice(_)
|
||||||
| ty::Kind::Opt(_)
|
| ty::Kind::Opt(_)
|
||||||
| ty::Kind::Func(_)
|
| ty::Kind::Func(_)
|
||||||
|
| ty::Kind::Template(_)
|
||||||
| ty::Kind::Global(_)
|
| ty::Kind::Global(_)
|
||||||
| ty::Kind::Const(_)) => self.error(
|
| ty::Kind::Const(_)) => self.error(
|
||||||
pos,
|
pos,
|
||||||
|
@ -4432,21 +4428,16 @@ impl<'a> Codegen<'a> {
|
||||||
ref e => (self.ty(e), None),
|
ref e => (self.ty(e), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
let ty::Kind::Func(mut fu) = ty.expand() else {
|
let Some(fu) = self.compute_signature(ty, func.pos(), args) else {
|
||||||
self.error(func.pos(), fa!("compiler cant (yet) call '{}'", self.ty_display(ty)));
|
|
||||||
return Value::NEVER;
|
return Value::NEVER;
|
||||||
};
|
};
|
||||||
|
|
||||||
let Some(sig) = self.compute_signature(&mut fu, func.pos(), args) else {
|
let FuncData { expr, file, is_inline, parent, sig, .. } = self.tys.ins.funcs[fu];
|
||||||
return Value::NEVER;
|
|
||||||
};
|
|
||||||
|
|
||||||
inline |= sig.ret == ty::Id::TYPE;
|
|
||||||
|
|
||||||
let FuncData { expr, file, is_inline, parent, .. } = self.tys.ins.funcs[fu];
|
|
||||||
let ast = &self.files[file];
|
let ast = &self.files[file];
|
||||||
let &Expr::Closure { args: cargs, body, .. } = expr.get(ast) else { unreachable!() };
|
let &Expr::Closure { args: cargs, body, .. } = expr.get(ast) else { unreachable!() };
|
||||||
|
|
||||||
|
inline |= sig.ret == ty::Id::TYPE;
|
||||||
|
|
||||||
let arg_count = args.len() + caller.is_some() as usize;
|
let arg_count = args.len() + caller.is_some() as usize;
|
||||||
if arg_count != cargs.len() {
|
if arg_count != cargs.len() {
|
||||||
self.error(
|
self.error(
|
||||||
|
@ -4803,79 +4794,90 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_signature(&mut self, func: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option<Sig> {
|
fn compute_signature(&mut self, func: ty::Id, pos: Pos, args: &[Expr]) -> Option<ty::Func> {
|
||||||
let FuncData { file, expr, sig, parent, .. } = self.tys.ins.funcs[*func];
|
let template = match func.expand() {
|
||||||
|
ty::Kind::Func(f) => return Some(f),
|
||||||
|
ty::Kind::Template(t) => t,
|
||||||
|
_ => {
|
||||||
|
self.error(pos, fa!("compiler cant (yet) call '{}'", self.ty_display(func)));
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let TemplateData { file, expr, parent, name, is_inline, .. } =
|
||||||
|
self.tys.ins.templates[template];
|
||||||
let fast = &self.files[file];
|
let fast = &self.files[file];
|
||||||
let &Expr::Closure { args: cargs, ret, .. } = expr.get(fast) else {
|
let &Expr::Closure { pos, args: cargs, ret, .. } = expr.get(fast) else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(if let Some(sig) = sig {
|
let arg_base = self.tys.tmp.args.len();
|
||||||
sig
|
|
||||||
} else {
|
|
||||||
let arg_base = self.tys.tmp.args.len();
|
|
||||||
|
|
||||||
let base = self.ci.scope.vars.len();
|
let base = self.ci.scope.vars.len();
|
||||||
for (arg, carg) in args.iter().zip(cargs) {
|
for (arg, carg) in args.iter().zip(cargs) {
|
||||||
let ty = self.ty_in(file, parent, &carg.ty);
|
let ty = self.ty_in(file, parent, &carg.ty);
|
||||||
|
|
||||||
self.tys.tmp.args.push(ty);
|
self.tys.tmp.args.push(ty);
|
||||||
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
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
if ty != ty::Id::TYPE {
|
if ty != ty::Id::TYPE {
|
||||||
self.error(
|
self.error(
|
||||||
arg.pos(),
|
arg.pos(),
|
||||||
fa!(
|
fa!(
|
||||||
"arbitrary comptime types are not supported yet \
|
"arbitrary comptime types are not supported yet \
|
||||||
(expected '{}' got '{}')",
|
(expected '{}' got '{}')",
|
||||||
self.ty_display(ty::Id::TYPE),
|
self.ty_display(ty::Id::TYPE),
|
||||||
self.ty_display(ty)
|
self.ty_display(ty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ty = self.ty(arg);
|
let ty = self.ty(arg);
|
||||||
self.tys.tmp.args.push(ty);
|
self.tys.tmp.args.push(ty);
|
||||||
ty
|
ty
|
||||||
};
|
|
||||||
|
|
||||||
self.ci.scope.vars.push(Variable::new(
|
|
||||||
carg.id,
|
|
||||||
ty::Id::TYPE,
|
|
||||||
false,
|
|
||||||
self.ci.nodes.new_const(ty::Id::TYPE, ty),
|
|
||||||
&mut self.ci.nodes,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let Some(args) = self.tys.pack_args(arg_base) else {
|
|
||||||
self.error(pos, "function instance has too many arguments");
|
|
||||||
return None;
|
|
||||||
};
|
};
|
||||||
let ret = self.ty_in(file, parent, ret);
|
|
||||||
|
|
||||||
self.ci.scope.vars.drain(base..).for_each(|v| v.remove(&mut self.ci.nodes));
|
self.ci.scope.vars.push(Variable::new(
|
||||||
|
carg.id,
|
||||||
|
ty::Id::TYPE,
|
||||||
|
false,
|
||||||
|
self.ci.nodes.new_const(ty::Id::TYPE, ty),
|
||||||
|
&mut self.ci.nodes,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let sym = SymKey::FuncInst(*func, args);
|
let Some(args) = self.tys.pack_args(arg_base) else {
|
||||||
let ct = |ins: &mut TypeIns| {
|
self.error(pos, "function instance has too many arguments");
|
||||||
let fuc = ins.funcs[*func];
|
return None;
|
||||||
debug_assert!(fuc.comp_state.iter().all(|&s| s == CompState::default()));
|
};
|
||||||
ins.funcs
|
let ret = self.ty_in(file, parent, ret);
|
||||||
.push(FuncData { base: Some(*func), sig: Some(Sig { args, ret }), ..fuc })
|
|
||||||
.into()
|
|
||||||
};
|
|
||||||
let ty::Kind::Func(f) =
|
|
||||||
self.tys.syms.get_or_insert(sym, &mut self.tys.ins, ct).expand()
|
|
||||||
else {
|
|
||||||
unreachable!()
|
|
||||||
};
|
|
||||||
*func = f;
|
|
||||||
|
|
||||||
Sig { args, ret }
|
self.ci.scope.vars.drain(base..).for_each(|v| v.remove(&mut self.ci.nodes));
|
||||||
})
|
|
||||||
|
let sym = SymKey::Type(parent, pos, args);
|
||||||
|
let ct = |ins: &mut TypeIns| {
|
||||||
|
ins.funcs
|
||||||
|
.push(FuncData {
|
||||||
|
file,
|
||||||
|
parent,
|
||||||
|
name,
|
||||||
|
pos,
|
||||||
|
expr,
|
||||||
|
sig: Sig { args, ret },
|
||||||
|
is_inline,
|
||||||
|
is_generic: true,
|
||||||
|
comp_state: Default::default(),
|
||||||
|
})
|
||||||
|
.into()
|
||||||
|
};
|
||||||
|
let ty::Kind::Func(f) = self.tys.syms.get_or_insert(sym, &mut self.tys.ins, ct).expand()
|
||||||
|
else {
|
||||||
|
unreachable!()
|
||||||
|
};
|
||||||
|
Some(f)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_pattern(&mut self, pat: &Expr, mut right: Value) {
|
fn assign_pattern(&mut self, pat: &Expr, mut right: Value) {
|
||||||
|
@ -5032,8 +5034,8 @@ impl<'a> Codegen<'a> {
|
||||||
debug_assert_eq!(func.file, file);
|
debug_assert_eq!(func.file, file);
|
||||||
let cct = self.ct.active();
|
let cct = self.ct.active();
|
||||||
debug_assert_eq!(cct, ct);
|
debug_assert_eq!(cct, ct);
|
||||||
func.comp_state[cct as usize] = CompState::Compiled;
|
func.comp_state[cct as usize] = CompState::Compiled.into();
|
||||||
let sig = func.sig.expect("to emmit only concrete functions");
|
let sig = func.sig;
|
||||||
let ast = &self.files[file];
|
let ast = &self.files[file];
|
||||||
let expr = func.expr.get(ast);
|
let expr = func.expr.get(ast);
|
||||||
|
|
||||||
|
@ -5198,7 +5200,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_in(&mut self, file: Module, parent: ty::Id, expr: &Expr) -> ty::Id {
|
fn ty_in(&mut self, file: Module, parent: ty::Id, expr: &Expr) -> ty::Id {
|
||||||
self.parse_ty(TyScope { file, parent, name: None, alloc_const: true }, expr)
|
self.parse_ty(TyScope { file, parent, alloc_const: true, ..Default::default() }, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ty_display(&self, ty: ty::Id) -> ty::Display {
|
fn ty_display(&self, ty: ty::Id) -> ty::Display {
|
||||||
|
@ -5495,10 +5497,10 @@ impl<'a> Codegen<'a> {
|
||||||
let state_slot = self.ct.active() as usize;
|
let state_slot = self.ct.active() as usize;
|
||||||
if let ty::Kind::Func(id) = existing.expand()
|
if let ty::Kind::Func(id) = existing.expand()
|
||||||
&& let func = &mut self.tys.ins.funcs[id]
|
&& let func = &mut self.tys.ins.funcs[id]
|
||||||
&& let CompState::Queued(idx) = func.comp_state[state_slot]
|
&& let CompState::Queued(idx) = func.comp_state[state_slot].into()
|
||||||
&& idx < self.tys.tasks.len()
|
&& idx < self.tys.tasks.len()
|
||||||
{
|
{
|
||||||
func.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len());
|
func.comp_state[state_slot] = CompState::Queued(self.tys.tasks.len()).into();
|
||||||
let task = self.tys.tasks[idx].take();
|
let task = self.tys.tasks[idx].take();
|
||||||
self.tys.tasks.push(task);
|
self.tys.tasks.push(task);
|
||||||
}
|
}
|
||||||
|
@ -5643,9 +5645,9 @@ impl<'a> Codegen<'a> {
|
||||||
{
|
{
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
let (is_ct, ty) = left
|
let ty = left
|
||||||
.find_pattern_path(name, right, |right, is_ct| {
|
.find_pattern_path(name, right, |right, is_ct| {
|
||||||
let ty = if is_ct && !matches!(right, Expr::Closure { .. }) {
|
if is_ct && !matches!(right, Expr::Closure { .. }) {
|
||||||
self.tys
|
self.tys
|
||||||
.ins
|
.ins
|
||||||
.consts
|
.consts
|
||||||
|
@ -5653,23 +5655,23 @@ impl<'a> Codegen<'a> {
|
||||||
.into()
|
.into()
|
||||||
} else {
|
} else {
|
||||||
self.parse_ty(
|
self.parse_ty(
|
||||||
TyScope { file, parent, name: Some(name), alloc_const: true },
|
TyScope {
|
||||||
|
file,
|
||||||
|
parent,
|
||||||
|
name: Some(name),
|
||||||
|
alloc_const: true,
|
||||||
|
is_ct,
|
||||||
|
},
|
||||||
right,
|
right,
|
||||||
)
|
)
|
||||||
};
|
}
|
||||||
(is_ct, ty)
|
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|_| unreachable!());
|
.unwrap_or_else(|_| unreachable!());
|
||||||
if let ty::Kind::Func(f) = ty.expand()
|
|
||||||
&& is_ct
|
|
||||||
{
|
|
||||||
self.tys.ins.funcs[f].is_inline = true;
|
|
||||||
}
|
|
||||||
self.tys.syms.insert(SymKey::Decl(parent, name), ty, &self.tys.ins);
|
self.tys.syms.insert(SymKey::Decl(parent, name), ty, &self.tys.ins);
|
||||||
ty
|
ty
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Err(proper_case) = self.tys.case(ty)(f.ident_str(name)) {
|
if let Err(proper_case) = self.tys.case(ty, self.files)(f.ident_str(name)) {
|
||||||
self.warn_low(
|
self.warn_low(
|
||||||
from_file,
|
from_file,
|
||||||
pos,
|
pos,
|
||||||
|
@ -5775,35 +5777,53 @@ impl<'a> Codegen<'a> {
|
||||||
|s, base| s.ins.unions.push(UnionData { base, ..Default::default() }),
|
|s, base| s.ins.unions.push(UnionData { base, ..Default::default() }),
|
||||||
),
|
),
|
||||||
Expr::Closure { pos, args, ret, .. } if let Some(name) = sc.name => {
|
Expr::Closure { pos, args, ret, .. } if let Some(name) = sc.name => {
|
||||||
let func = FuncData {
|
let sig = 'b: {
|
||||||
file: sc.file,
|
let arg_base = self.tys.tmp.args.len();
|
||||||
parent: sc.parent,
|
for arg in args {
|
||||||
name,
|
let sym = parser::find_symbol(&self.files[sc.file].symbols, arg.id);
|
||||||
sig: 'b: {
|
if sym.flags & idfl::COMPTIME != 0 {
|
||||||
let arg_base = self.tys.tmp.args.len();
|
self.tys.tmp.args.truncate(arg_base);
|
||||||
for arg in args {
|
break 'b None;
|
||||||
let sym = parser::find_symbol(&self.files[sc.file].symbols, arg.id);
|
|
||||||
if sym.flags & idfl::COMPTIME != 0 {
|
|
||||||
self.tys.tmp.args.truncate(arg_base);
|
|
||||||
break 'b None;
|
|
||||||
}
|
|
||||||
let ty = self.parse_ty(sc.anon(), &arg.ty);
|
|
||||||
self.tys.tmp.args.push(ty);
|
|
||||||
}
|
}
|
||||||
|
let ty = self.parse_ty(sc.anon(), &arg.ty);
|
||||||
|
self.tys.tmp.args.push(ty);
|
||||||
|
}
|
||||||
|
|
||||||
let Some(args) = self.tys.pack_args(arg_base) else {
|
let Some(args) = self.tys.pack_args(arg_base) else {
|
||||||
return self.error_low(sc.file, pos, "function has too many argumnets");
|
return self.error_low(sc.file, pos, "function has too many argumnets");
|
||||||
};
|
};
|
||||||
let ret = self.parse_ty(sc.anon(), ret);
|
let ret = self.parse_ty(sc.anon(), ret);
|
||||||
|
|
||||||
Some(Sig { args, ret })
|
Some(Sig { args, ret })
|
||||||
},
|
|
||||||
expr: ExprRef::new(expr),
|
|
||||||
returns_type: matches!(ret, &Expr::Ident { id, .. } if ty::Builtin::try_from(id) == Ok(ty::Builtin::TYPE)),
|
|
||||||
..Default::default()
|
|
||||||
};
|
};
|
||||||
|
//let returns_type = matches!(ret, &Expr::Ident { id, .. } if );
|
||||||
|
|
||||||
self.tys.ins.funcs.push(func).into()
|
match sig {
|
||||||
|
Some(sig) => {
|
||||||
|
let func = FuncData {
|
||||||
|
file: sc.file,
|
||||||
|
parent: sc.parent,
|
||||||
|
name,
|
||||||
|
pos,
|
||||||
|
sig,
|
||||||
|
expr: ExprRef::new(expr),
|
||||||
|
is_inline: sc.is_ct,
|
||||||
|
is_generic: false,
|
||||||
|
comp_state: Default::default(),
|
||||||
|
};
|
||||||
|
self.tys.ins.funcs.push(func).into()
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let template = TemplateData {
|
||||||
|
file: sc.file,
|
||||||
|
parent: sc.parent,
|
||||||
|
name,
|
||||||
|
expr: ExprRef::new(expr),
|
||||||
|
is_inline: sc.is_ct,
|
||||||
|
};
|
||||||
|
self.tys.ins.templates.push(template).into()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_ if sc.alloc_const
|
_ if sc.alloc_const
|
||||||
&& let Some(name) = sc.name =>
|
&& let Some(name) = sc.name =>
|
||||||
|
@ -5839,7 +5859,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
let captured = self.tys.pack_args(captures_start).expect("TODO");
|
let captured = self.tys.pack_args(captures_start).expect("TODO");
|
||||||
|
|
||||||
let sym = SymKey::Type(sc.file, pos, captured);
|
let sym = SymKey::Type(sc.parent, pos, captured);
|
||||||
if let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins) {
|
if let Some(&ty) = self.tys.syms.get(sym, &self.tys.ins) {
|
||||||
return ty;
|
return ty;
|
||||||
}
|
}
|
||||||
|
@ -5871,17 +5891,18 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
struct TyScope {
|
struct TyScope {
|
||||||
file: Module,
|
file: Module,
|
||||||
parent: ty::Id,
|
parent: ty::Id,
|
||||||
name: Option<Ident>,
|
name: Option<Ident>,
|
||||||
alloc_const: bool,
|
alloc_const: bool,
|
||||||
|
is_ct: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TyScope {
|
impl TyScope {
|
||||||
fn anon(self) -> Self {
|
fn anon(self) -> Self {
|
||||||
Self { name: None, ..self }
|
Self { name: None, is_ct: false, ..self }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
108
lang/src/ty.rs
108
lang/src/ty.rs
|
@ -119,29 +119,32 @@ impl crate::ctx_map::CtxEntry for Id {
|
||||||
Kind::Struct(s) => {
|
Kind::Struct(s) => {
|
||||||
let st = &ctx.structs[s];
|
let st = &ctx.structs[s];
|
||||||
debug_assert_ne!(st.pos, Pos::MAX);
|
debug_assert_ne!(st.pos, Pos::MAX);
|
||||||
SymKey::Type(st.file, st.pos, st.captured)
|
SymKey::Type(st.parent, st.pos, st.captured)
|
||||||
}
|
}
|
||||||
Kind::Enum(e) => {
|
Kind::Enum(e) => {
|
||||||
let en = &ctx.enums[e];
|
let en = &ctx.enums[e];
|
||||||
debug_assert_ne!(en.pos, Pos::MAX);
|
debug_assert_ne!(en.pos, Pos::MAX);
|
||||||
SymKey::Type(en.file, en.pos, en.captured)
|
SymKey::Type(en.parent, en.pos, en.captured)
|
||||||
}
|
}
|
||||||
Kind::Union(e) => {
|
Kind::Union(e) => {
|
||||||
let en = &ctx.unions[e];
|
let en = &ctx.unions[e];
|
||||||
debug_assert_ne!(en.pos, Pos::MAX);
|
debug_assert_ne!(en.pos, Pos::MAX);
|
||||||
SymKey::Type(en.file, en.pos, en.captured)
|
SymKey::Type(en.parent, en.pos, en.captured)
|
||||||
}
|
}
|
||||||
Kind::Ptr(p) => SymKey::Pointer(&ctx.ptrs[p]),
|
Kind::Ptr(p) => SymKey::Pointer(&ctx.ptrs[p]),
|
||||||
Kind::Opt(p) => SymKey::Optional(&ctx.opts[p]),
|
Kind::Opt(p) => SymKey::Optional(&ctx.opts[p]),
|
||||||
Kind::Func(f) => {
|
Kind::Func(f) => {
|
||||||
let fc = &ctx.funcs[f];
|
let fc = &ctx.funcs[f];
|
||||||
if let Some(base) = fc.base {
|
if fc.is_generic {
|
||||||
// TODO: merge base and sig
|
SymKey::Type(fc.parent, fc.pos, fc.sig.args)
|
||||||
SymKey::FuncInst(base, fc.sig.unwrap().args)
|
|
||||||
} else {
|
} else {
|
||||||
SymKey::Decl(fc.parent, fc.name)
|
SymKey::Decl(fc.parent, fc.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Kind::Template(t) => {
|
||||||
|
let tc = &ctx.templates[t];
|
||||||
|
SymKey::Decl(tc.parent, tc.name)
|
||||||
|
}
|
||||||
Kind::Global(g) => {
|
Kind::Global(g) => {
|
||||||
let gb = &ctx.globals[g];
|
let gb = &ctx.globals[g];
|
||||||
SymKey::Decl(gb.file.into(), gb.name)
|
SymKey::Decl(gb.file.into(), gb.name)
|
||||||
|
@ -271,7 +274,11 @@ impl Id {
|
||||||
Kind::Ptr(_) | Kind::Enum(_) | Kind::Builtin(_) => Loc::Reg,
|
Kind::Ptr(_) | Kind::Enum(_) | Kind::Builtin(_) => Loc::Reg,
|
||||||
Kind::Struct(_) | Kind::Union(_) if tys.size_of(*self) == 0 => Loc::Reg,
|
Kind::Struct(_) | Kind::Union(_) if tys.size_of(*self) == 0 => Loc::Reg,
|
||||||
Kind::Struct(_) | Kind::Union(_) | Kind::Slice(_) | Kind::Opt(_) => Loc::Stack,
|
Kind::Struct(_) | Kind::Union(_) | Kind::Slice(_) | Kind::Opt(_) => Loc::Stack,
|
||||||
c @ (Kind::Func(_) | Kind::Global(_) | Kind::Module(_) | Kind::Const(_)) => {
|
c @ (Kind::Func(_)
|
||||||
|
| Kind::Global(_)
|
||||||
|
| Kind::Module(_)
|
||||||
|
| Kind::Const(_)
|
||||||
|
| Kind::Template(_)) => {
|
||||||
unreachable!("{c:?}")
|
unreachable!("{c:?}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -439,6 +446,7 @@ type_kind! {
|
||||||
Slice,
|
Slice,
|
||||||
Opt,
|
Opt,
|
||||||
Func,
|
Func,
|
||||||
|
Template,
|
||||||
Global,
|
Global,
|
||||||
Module,
|
Module,
|
||||||
Const,
|
Const,
|
||||||
|
@ -568,6 +576,10 @@ impl core::fmt::Display for Display<'_> {
|
||||||
f.write_str("fn")?;
|
f.write_str("fn")?;
|
||||||
idx.fmt(f)
|
idx.fmt(f)
|
||||||
}
|
}
|
||||||
|
TK::Template(idx) => {
|
||||||
|
f.write_str("fn")?;
|
||||||
|
idx.fmt(f)
|
||||||
|
}
|
||||||
TK::Global(idx) => {
|
TK::Global(idx) => {
|
||||||
let global = &self.tys.ins.globals[idx];
|
let global = &self.tys.ins.globals[idx];
|
||||||
let file = &self.files[global.file];
|
let file = &self.files[global.file];
|
||||||
|
@ -598,30 +610,71 @@ impl core::fmt::Display for Display<'_> {
|
||||||
pub enum SymKey<'a> {
|
pub enum SymKey<'a> {
|
||||||
Pointer(&'a PtrData),
|
Pointer(&'a PtrData),
|
||||||
Optional(&'a OptData),
|
Optional(&'a OptData),
|
||||||
Type(Module, Pos, Tuple),
|
Type(Id, Pos, Tuple),
|
||||||
FuncInst(Func, Tuple),
|
|
||||||
Decl(Id, Ident),
|
Decl(Id, Ident),
|
||||||
Array(&'a ArrayData),
|
Array(&'a ArrayData),
|
||||||
Constant(&'a ConstData),
|
Constant(&'a ConstData),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct Sig {
|
pub struct Sig {
|
||||||
pub args: Tuple,
|
pub args: Tuple,
|
||||||
pub ret: Id,
|
pub ret: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct TemplateData {
|
||||||
|
pub file: Module,
|
||||||
|
pub parent: Id,
|
||||||
|
pub name: Ident,
|
||||||
|
pub expr: ExprRef,
|
||||||
|
pub is_inline: bool,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy)]
|
||||||
pub struct FuncData {
|
pub struct FuncData {
|
||||||
pub file: Module,
|
pub file: Module,
|
||||||
pub parent: Id,
|
pub parent: Id,
|
||||||
pub name: Ident,
|
pub name: Ident,
|
||||||
pub base: Option<Func>,
|
pub pos: Pos,
|
||||||
pub expr: ExprRef,
|
pub expr: ExprRef,
|
||||||
pub sig: Option<Sig>,
|
pub sig: Sig,
|
||||||
pub is_inline: bool,
|
pub is_inline: bool,
|
||||||
pub returns_type: bool,
|
pub is_generic: bool,
|
||||||
pub comp_state: [CompState; 2],
|
pub comp_state: [PackedCompState; 2],
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||||
|
pub struct PackedCompState(u16);
|
||||||
|
|
||||||
|
impl Default for PackedCompState {
|
||||||
|
fn default() -> Self {
|
||||||
|
CompState::default().into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PackedCompState {
|
||||||
|
const COMPILED: u16 = u16::MAX - 1;
|
||||||
|
const DEAD: u16 = u16::MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<PackedCompState> for CompState {
|
||||||
|
fn from(value: PackedCompState) -> Self {
|
||||||
|
match value.0 {
|
||||||
|
PackedCompState::DEAD => CompState::Dead,
|
||||||
|
PackedCompState::COMPILED => CompState::Compiled,
|
||||||
|
v => CompState::Queued(v as _),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<CompState> for PackedCompState {
|
||||||
|
fn from(value: CompState) -> Self {
|
||||||
|
Self(match value {
|
||||||
|
CompState::Dead => Self::DEAD,
|
||||||
|
CompState::Queued(v) => v.try_into().unwrap(),
|
||||||
|
CompState::Compiled => Self::COMPILED,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Eq, Clone, Copy)]
|
#[derive(Default, PartialEq, Eq, Clone, Copy)]
|
||||||
|
@ -774,6 +827,7 @@ pub struct TypeIns {
|
||||||
pub struct_fields: Vec<StructField>,
|
pub struct_fields: Vec<StructField>,
|
||||||
pub enum_fields: Vec<EnumField>,
|
pub enum_fields: Vec<EnumField>,
|
||||||
pub funcs: EntVec<Func, FuncData>,
|
pub funcs: EntVec<Func, FuncData>,
|
||||||
|
pub templates: EntVec<Template, TemplateData>,
|
||||||
pub globals: EntVec<Global, GlobalData>,
|
pub globals: EntVec<Global, GlobalData>,
|
||||||
pub consts: EntVec<Const, ConstData>,
|
pub consts: EntVec<Const, ConstData>,
|
||||||
pub structs: EntVec<Struct, StructData>,
|
pub structs: EntVec<Struct, StructData>,
|
||||||
|
@ -812,7 +866,11 @@ pub struct Types {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Types {
|
impl Types {
|
||||||
pub fn case(&self, ty: Id) -> fn(&str) -> Result<(), &'static str> {
|
pub fn case(
|
||||||
|
&self,
|
||||||
|
ty: Id,
|
||||||
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
|
) -> fn(&str) -> Result<(), &'static str> {
|
||||||
match ty.expand() {
|
match ty.expand() {
|
||||||
Kind::NEVER => |_| Ok(()),
|
Kind::NEVER => |_| Ok(()),
|
||||||
Kind::Enum(_)
|
Kind::Enum(_)
|
||||||
|
@ -822,8 +880,23 @@ impl Types {
|
||||||
| Kind::Ptr(_)
|
| Kind::Ptr(_)
|
||||||
| Kind::Slice(_)
|
| Kind::Slice(_)
|
||||||
| Kind::Opt(_) => utils::is_pascal_case,
|
| Kind::Opt(_) => utils::is_pascal_case,
|
||||||
Kind::Func(f) if self.ins.funcs[f].returns_type => utils::is_pascal_case,
|
Kind::Func(f)
|
||||||
Kind::Func(_) | Kind::Global(_) | Kind::Module(_) => utils::is_snake_case,
|
if let &Expr::Closure { ret: &Expr::Ident { id, .. }, .. } =
|
||||||
|
self.ins.funcs[f].expr.get(&files[self.ins.funcs[f].file])
|
||||||
|
&& id.is_type() =>
|
||||||
|
{
|
||||||
|
utils::is_pascal_case
|
||||||
|
}
|
||||||
|
Kind::Template(f)
|
||||||
|
if let &Expr::Closure { ret: &Expr::Ident { id, .. }, .. } =
|
||||||
|
self.ins.templates[f].expr.get(&files[self.ins.templates[f].file])
|
||||||
|
&& id.is_type() =>
|
||||||
|
{
|
||||||
|
utils::is_pascal_case
|
||||||
|
}
|
||||||
|
Kind::Func(_) | Kind::Template(_) | Kind::Global(_) | Kind::Module(_) => {
|
||||||
|
utils::is_snake_case
|
||||||
|
}
|
||||||
Kind::Const(_) => utils::is_screaming_case,
|
Kind::Const(_) => utils::is_screaming_case,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1063,6 +1136,7 @@ impl Types {
|
||||||
| Kind::Slice(_)
|
| Kind::Slice(_)
|
||||||
| Kind::Opt(_)
|
| Kind::Opt(_)
|
||||||
| Kind::Func(_)
|
| Kind::Func(_)
|
||||||
|
| Kind::Template(_)
|
||||||
| Kind::Global(_)
|
| Kind::Global(_)
|
||||||
| Kind::Module(_)
|
| Kind::Module(_)
|
||||||
| Kind::Const(_) => return None,
|
| Kind::Const(_) => return None,
|
||||||
|
|
Loading…
Reference in a new issue