Dividing function into template and instance, rmoving cumbersome options

Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
Jakub Doka 2024-12-02 15:51:12 +01:00
parent c5d5301b7b
commit 71ba2c2486
No known key found for this signature in database
GPG key ID: C6E9A89936B8C143
4 changed files with 241 additions and 142 deletions

View file

@ -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());

View file

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

View file

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

View file

@ -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,