forked from AbleOS/holey-bytes
Removing repetative code, adding ent slice to properly index modules
Signed-off-by: Jakub Doka <jakub.doka2@gmail.com>
This commit is contained in:
parent
9ce446b507
commit
c553c3d9e9
15
foo.hb
Normal file
15
foo.hb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
Res := fn($O: type, $E: type): type return union(enum) {
|
||||||
|
ok: O,
|
||||||
|
err: E,
|
||||||
|
}
|
||||||
|
|
||||||
|
main := fn(): uint {
|
||||||
|
r := do_something()
|
||||||
|
if r == .err return v.err
|
||||||
|
return v.ok
|
||||||
|
}
|
||||||
|
|
||||||
|
do_something := fn(): Res(uint, uint) {
|
||||||
|
return .{ok: 0}
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ use {
|
||||||
parser,
|
parser,
|
||||||
son::{Kind, Nid, Node, Nodes, MEM, VOID},
|
son::{Kind, Nid, Node, Nodes, MEM, VOID},
|
||||||
ty::{self, Arg, Loc, Module, Offset, Sig, Size, Types},
|
ty::{self, Arg, Loc, Module, Offset, Sig, Size, Types},
|
||||||
utils::{Ent, EntVec},
|
utils::{EntSlice, EntVec},
|
||||||
},
|
},
|
||||||
alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec},
|
alloc::{boxed::Box, collections::BTreeMap, string::String, vec::Vec},
|
||||||
core::{assert_matches::debug_assert_matches, mem, ops::Range},
|
core::{assert_matches::debug_assert_matches, mem, ops::Range},
|
||||||
|
@ -213,7 +213,7 @@ impl Backend for HbvmBackend {
|
||||||
mut sluce: &[u8],
|
mut sluce: &[u8],
|
||||||
eca_handler: &mut dyn FnMut(&mut &[u8]),
|
eca_handler: &mut dyn FnMut(&mut &[u8]),
|
||||||
types: &'a Types,
|
types: &'a Types,
|
||||||
files: &'a [parser::Ast],
|
files: &'a EntSlice<Module, parser::Ast>,
|
||||||
output: &mut String,
|
output: &mut String,
|
||||||
) -> Result<(), hbbytecode::DisasmError<'a>> {
|
) -> Result<(), hbbytecode::DisasmError<'a>> {
|
||||||
use hbbytecode::DisasmItem;
|
use hbbytecode::DisasmItem;
|
||||||
|
@ -225,7 +225,7 @@ impl Backend for HbvmBackend {
|
||||||
.filter(|(_, f)| f.offset != u32::MAX)
|
.filter(|(_, f)| f.offset != u32::MAX)
|
||||||
.map(|(f, fd)| {
|
.map(|(f, fd)| {
|
||||||
let name = if f.file != Module::default() {
|
let name = if f.file != Module::default() {
|
||||||
let file = &files[f.file.index()];
|
let file = &files[f.file];
|
||||||
file.ident_str(f.name)
|
file.ident_str(f.name)
|
||||||
} else {
|
} else {
|
||||||
"target_fn"
|
"target_fn"
|
||||||
|
@ -243,7 +243,7 @@ impl Backend for HbvmBackend {
|
||||||
let name = if g.file == Module::default() {
|
let name = if g.file == Module::default() {
|
||||||
core::str::from_utf8(&g.data).unwrap_or("invalid utf-8")
|
core::str::from_utf8(&g.data).unwrap_or("invalid utf-8")
|
||||||
} else {
|
} else {
|
||||||
let file = &files[g.file.index()];
|
let file = &files[g.file];
|
||||||
file.ident_str(g.name)
|
file.ident_str(g.name)
|
||||||
};
|
};
|
||||||
(gd.offset, (name, g.data.len() as Size, DisasmItem::Global))
|
(gd.offset, (name, g.data.len() as Size, DisasmItem::Global))
|
||||||
|
@ -253,14 +253,26 @@ impl Backend for HbvmBackend {
|
||||||
hbbytecode::disasm(&mut sluce, &functions, output, eca_handler)
|
hbbytecode::disasm(&mut sluce, &functions, output, eca_handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_ct_body(&mut self, id: ty::Func, nodes: &Nodes, tys: &Types, files: &[parser::Ast]) {
|
fn emit_ct_body(
|
||||||
|
&mut self,
|
||||||
|
id: ty::Func,
|
||||||
|
nodes: &Nodes,
|
||||||
|
tys: &Types,
|
||||||
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
|
) {
|
||||||
self.emit_body(id, nodes, tys, files);
|
self.emit_body(id, nodes, tys, files);
|
||||||
let fd = &mut self.funcs[id];
|
let fd = &mut self.funcs[id];
|
||||||
fd.code.truncate(fd.code.len() - instrs::jala(0, 0, 0).0);
|
fd.code.truncate(fd.code.len() - instrs::jala(0, 0, 0).0);
|
||||||
emit(&mut fd.code, instrs::tx());
|
emit(&mut fd.code, instrs::tx());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn emit_body(&mut self, id: ty::Func, nodes: &Nodes, tys: &Types, files: &[parser::Ast]) {
|
fn emit_body(
|
||||||
|
&mut self,
|
||||||
|
id: ty::Func,
|
||||||
|
nodes: &Nodes,
|
||||||
|
tys: &Types,
|
||||||
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
|
) {
|
||||||
let sig = tys.ins.funcs[id].sig.unwrap();
|
let sig = tys.ins.funcs[id].sig.unwrap();
|
||||||
|
|
||||||
debug_assert!(self.code.is_empty());
|
debug_assert!(self.code.is_empty());
|
||||||
|
@ -432,11 +444,18 @@ struct InstrCtx<'a> {
|
||||||
allocs: &'a [u8],
|
allocs: &'a [u8],
|
||||||
nodes: &'a Nodes,
|
nodes: &'a Nodes,
|
||||||
tys: &'a Types,
|
tys: &'a Types,
|
||||||
files: &'a [parser::Ast],
|
files: &'a EntSlice<Module, parser::Ast>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HbvmBackend {
|
impl HbvmBackend {
|
||||||
fn extend(&mut self, base: ty::Id, dest: ty::Id, reg: Reg, tys: &Types, files: &[parser::Ast]) {
|
fn extend(
|
||||||
|
&mut self,
|
||||||
|
base: ty::Id,
|
||||||
|
dest: ty::Id,
|
||||||
|
reg: Reg,
|
||||||
|
tys: &Types,
|
||||||
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
|
) {
|
||||||
if reg == 0 {
|
if reg == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ use {
|
||||||
},
|
},
|
||||||
parser, quad_sort,
|
parser, quad_sort,
|
||||||
son::{Kind, ARG_START, MEM, VOID},
|
son::{Kind, ARG_START, MEM, VOID},
|
||||||
ty::{self, Arg, Loc, Sig, Types},
|
ty::{self, Arg, Loc, Module, Sig, Types},
|
||||||
utils::BitSet,
|
utils::{BitSet, EntSlice},
|
||||||
},
|
},
|
||||||
alloc::{borrow::ToOwned, vec::Vec},
|
alloc::{borrow::ToOwned, vec::Vec},
|
||||||
core::{assert_matches::debug_assert_matches, mem, ops::Range},
|
core::{assert_matches::debug_assert_matches, mem, ops::Range},
|
||||||
|
@ -20,7 +20,7 @@ impl HbvmBackend {
|
||||||
nodes: &Nodes,
|
nodes: &Nodes,
|
||||||
sig: Sig,
|
sig: Sig,
|
||||||
tys: &Types,
|
tys: &Types,
|
||||||
files: &[parser::Ast],
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
) -> (usize, bool) {
|
) -> (usize, bool) {
|
||||||
let tail = Function::build(nodes, tys, &mut self.ralloc, sig);
|
let tail = Function::build(nodes, tys, &mut self.ralloc, sig);
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,8 @@ pub mod backend {
|
||||||
crate::{
|
crate::{
|
||||||
parser,
|
parser,
|
||||||
son::Nodes,
|
son::Nodes,
|
||||||
ty::{self, Types},
|
ty::{self, Module, Types},
|
||||||
|
utils::EntSlice,
|
||||||
},
|
},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
};
|
};
|
||||||
|
@ -94,12 +95,24 @@ pub mod backend {
|
||||||
sluce: &[u8],
|
sluce: &[u8],
|
||||||
eca_handler: &mut dyn FnMut(&mut &[u8]),
|
eca_handler: &mut dyn FnMut(&mut &[u8]),
|
||||||
types: &'a Types,
|
types: &'a Types,
|
||||||
files: &'a [parser::Ast],
|
files: &'a EntSlice<Module, parser::Ast>,
|
||||||
output: &mut String,
|
output: &mut String,
|
||||||
) -> Result<(), hbbytecode::DisasmError<'a>>;
|
) -> Result<(), hbbytecode::DisasmError<'a>>;
|
||||||
fn emit_body(&mut self, id: ty::Func, ci: &Nodes, tys: &Types, files: &[parser::Ast]);
|
fn emit_body(
|
||||||
|
&mut self,
|
||||||
|
id: ty::Func,
|
||||||
|
ci: &Nodes,
|
||||||
|
tys: &Types,
|
||||||
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
|
);
|
||||||
|
|
||||||
fn emit_ct_body(&mut self, id: ty::Func, ci: &Nodes, tys: &Types, files: &[parser::Ast]) {
|
fn emit_ct_body(
|
||||||
|
&mut self,
|
||||||
|
id: ty::Func,
|
||||||
|
ci: &Nodes,
|
||||||
|
tys: &Types,
|
||||||
|
files: &EntSlice<Module, parser::Ast>,
|
||||||
|
) {
|
||||||
self.emit_body(id, ci, tys, files);
|
self.emit_body(id, ci, tys, files);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1079,9 +1079,11 @@ generate_expr! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr<'_> {
|
impl Expr<'_> {
|
||||||
pub fn declares(&self, iden: Result<Ident, &str>, source: &str) -> Option<Ident> {
|
pub fn declares(&self, iden: DeclId, source: &str) -> Option<Ident> {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Ident { id, .. } if iden == Ok(id) || iden == Err(&source[id.range()]) => {
|
Self::Ident { id, .. }
|
||||||
|
if iden == DeclId::Ident(id) || iden == DeclId::Name(&source[id.range()]) =>
|
||||||
|
{
|
||||||
Some(id)
|
Some(id)
|
||||||
}
|
}
|
||||||
Self::Ctor { fields, .. } => fields.iter().find_map(|f| f.value.declares(iden, source)),
|
Self::Ctor { fields, .. } => fields.iter().find_map(|f| f.value.declares(iden, source)),
|
||||||
|
@ -1389,7 +1391,7 @@ impl Ast {
|
||||||
unsafe { self.0.as_ref() }
|
unsafe { self.0.as_ref() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_decl(&self, id: Result<Ident, &str>) -> Option<(&Expr, Ident)> {
|
pub fn find_decl(&self, id: DeclId) -> Option<(&Expr, Ident)> {
|
||||||
find_decl(self.exprs(), &self.file, id)
|
find_decl(self.exprs(), &self.file, id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1401,7 +1403,7 @@ impl Ast {
|
||||||
pub fn find_decl<'a>(
|
pub fn find_decl<'a>(
|
||||||
exprs: &'a [Expr<'a>],
|
exprs: &'a [Expr<'a>],
|
||||||
file: &str,
|
file: &str,
|
||||||
id: Result<Ident, &str>,
|
id: DeclId,
|
||||||
) -> Option<(&'a Expr<'a>, Ident)> {
|
) -> Option<(&'a Expr<'a>, Ident)> {
|
||||||
exprs.iter().find_map(|expr| match expr {
|
exprs.iter().find_map(|expr| match expr {
|
||||||
Expr::BinOp { left, op: TokenKind::Decl, .. } => {
|
Expr::BinOp { left, op: TokenKind::Decl, .. } => {
|
||||||
|
@ -1411,6 +1413,24 @@ pub fn find_decl<'a>(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Clone, Copy)]
|
||||||
|
pub enum DeclId<'a> {
|
||||||
|
Ident(Ident),
|
||||||
|
Name(&'a str),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Ident> for DeclId<'_> {
|
||||||
|
fn from(value: Ident) -> Self {
|
||||||
|
Self::Ident(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a str> for DeclId<'a> {
|
||||||
|
fn from(value: &'a str) -> Self {
|
||||||
|
Self::Name(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Ast {
|
impl Default for Ast {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self(AstInner::new("".into(), "".into(), &mut Ctx::default(), &mut no_loader))
|
Self(AstInner::new("".into(), "".into(), &mut Ctx::default(), &mut no_loader))
|
||||||
|
|
379
lang/src/son.rs
379
lang/src/son.rs
|
@ -11,14 +11,14 @@ use {
|
||||||
parser::{
|
parser::{
|
||||||
self,
|
self,
|
||||||
idfl::{self},
|
idfl::{self},
|
||||||
CommentOr, CtorField, Expr, ExprRef, FieldList, MatchBranch, Pos,
|
CommentOr, CtorField, DeclId, Expr, ExprRef, FieldList, MatchBranch, Pos,
|
||||||
},
|
},
|
||||||
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, Tuple, TypeBase, TypeIns, Types, UnionData,
|
||||||
},
|
},
|
||||||
utils::{BitSet, Ent, Vc},
|
utils::{BitSet, EntSlice, Vc},
|
||||||
Ident,
|
Ident,
|
||||||
},
|
},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
|
@ -2506,7 +2506,12 @@ impl ItemCtx {
|
||||||
self.scope.aclasses.push(AClass::new(&mut self.nodes)); // GLOBAL
|
self.scope.aclasses.push(AClass::new(&mut self.nodes)); // GLOBAL
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(&mut self, stack: &mut Vec<Nid>, tys: &Types, _files: &[parser::Ast]) {
|
fn finalize(
|
||||||
|
&mut self,
|
||||||
|
stack: &mut Vec<Nid>,
|
||||||
|
tys: &Types,
|
||||||
|
_files: &EntSlice<Module, parser::Ast>,
|
||||||
|
) {
|
||||||
self.scope.clear(&mut self.nodes);
|
self.scope.clear(&mut self.nodes);
|
||||||
mem::take(&mut self.ctrl).soft_remove(&mut self.nodes);
|
mem::take(&mut self.ctrl).soft_remove(&mut self.nodes);
|
||||||
|
|
||||||
|
@ -2535,6 +2540,7 @@ pub struct Pool {
|
||||||
used_cis: usize,
|
used_cis: usize,
|
||||||
scratch1: Vec<Nid>,
|
scratch1: Vec<Nid>,
|
||||||
scratch2: Vec<Nid>,
|
scratch2: Vec<Nid>,
|
||||||
|
lit_buf: Vec<u8>,
|
||||||
nid_set: BitSet,
|
nid_set: BitSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2546,7 +2552,7 @@ impl Pool {
|
||||||
ret: Option<ty::Id>,
|
ret: Option<ty::Id>,
|
||||||
task_base: usize,
|
task_base: usize,
|
||||||
target: &mut ItemCtx,
|
target: &mut ItemCtx,
|
||||||
) {
|
) -> &mut ItemCtx {
|
||||||
if let Some(slot) = self.cis.get_mut(self.used_cis) {
|
if let Some(slot) = self.cis.get_mut(self.used_cis) {
|
||||||
mem::swap(slot, target);
|
mem::swap(slot, target);
|
||||||
} else {
|
} else {
|
||||||
|
@ -2555,6 +2561,7 @@ impl Pool {
|
||||||
}
|
}
|
||||||
target.init(file, parent, ret, task_base);
|
target.init(file, parent, ret, task_base);
|
||||||
self.used_cis += 1;
|
self.used_cis += 1;
|
||||||
|
&mut self.cis[self.used_cis - 1]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn pop_ci(&mut self, target: &mut ItemCtx) {
|
fn pop_ci(&mut self, target: &mut ItemCtx) {
|
||||||
|
@ -2633,7 +2640,7 @@ impl CodegenCtx {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Codegen<'a> {
|
pub struct Codegen<'a> {
|
||||||
pub files: &'a [parser::Ast],
|
pub files: &'a EntSlice<Module, parser::Ast>,
|
||||||
pub errors: &'a RefCell<String>,
|
pub errors: &'a RefCell<String>,
|
||||||
pub warnings: &'a RefCell<String>,
|
pub warnings: &'a RefCell<String>,
|
||||||
tys: &'a mut Types,
|
tys: &'a mut Types,
|
||||||
|
@ -2665,7 +2672,7 @@ impl<'a> Codegen<'a> {
|
||||||
ctx: &'a mut CodegenCtx,
|
ctx: &'a mut CodegenCtx,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
files,
|
files: files.into(),
|
||||||
errors: &ctx.parser.errors,
|
errors: &ctx.parser.errors,
|
||||||
warnings: &ctx.parser.warnings,
|
warnings: &ctx.parser.warnings,
|
||||||
tys: &mut ctx.tys,
|
tys: &mut ctx.tys,
|
||||||
|
@ -2678,7 +2685,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate(&mut self, entry: Module) {
|
pub fn generate(&mut self, entry: Module) {
|
||||||
self.find_type_in_file(0, entry, Err("main"));
|
self.find_type(0, entry, entry, "main");
|
||||||
if self.tys.ins.funcs.is_empty() {
|
if self.tys.ins.funcs.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2925,46 +2932,37 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
Some(Value::var(index).ty(var.ty))
|
Some(Value::var(index).ty(var.ty))
|
||||||
}
|
}
|
||||||
Expr::Ident { id, pos, .. } => {
|
Expr::Ident { id, pos, .. } => self.find_type_as_value(pos, self.ci.parent, id, ctx),
|
||||||
let decl = self.find_type_in_scope(pos, Ok(id));
|
|
||||||
match decl.expand() {
|
|
||||||
ty::Kind::NEVER => Value::NEVER,
|
|
||||||
ty::Kind::Global(global) => self.gen_global(global),
|
|
||||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
|
||||||
_ => Some(self.ci.nodes.new_const_lit(ty::Id::TYPE, decl)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Expr::Comment { .. } => Some(Value::VOID),
|
Expr::Comment { .. } => Some(Value::VOID),
|
||||||
Expr::String { pos, literal } => {
|
Expr::String { pos, literal } => {
|
||||||
let literal = &literal[1..literal.len() - 1];
|
let literal = &literal[1..literal.len() - 1];
|
||||||
|
let mut data = std::mem::take(&mut self.pool.lit_buf);
|
||||||
|
debug_assert!(data.is_empty());
|
||||||
|
|
||||||
let report = |bytes: &core::str::Bytes, message: &str| {
|
let report = |bytes: &core::str::Bytes, message: &str| {
|
||||||
self.error(pos + (literal.len() - bytes.len()) as u32 - 1, message);
|
self.error(pos + (literal.len() - bytes.len()) as u32 - 1, message);
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut data = Vec::<u8>::with_capacity(literal.len());
|
|
||||||
crate::endoce_string(literal, &mut data, report).unwrap();
|
crate::endoce_string(literal, &mut data, report).unwrap();
|
||||||
|
|
||||||
let ty = self.tys.make_ptr(ty::Id::U8);
|
let ty = self.tys.make_ptr(ty::Id::U8);
|
||||||
let global = match self.tys.strings.entry(&data, &self.tys.ins.globals) {
|
let global = self
|
||||||
(hash_map::RawEntryMut::Occupied(occupied_entry), _) => {
|
.tys
|
||||||
occupied_entry.get_key_value().0.value.0
|
.strings
|
||||||
}
|
.get_or_insert(&data, &mut self.tys.ins.globals, |globals| {
|
||||||
(hash_map::RawEntryMut::Vacant(vacant_entry), hash) => {
|
StringRef(globals.push(GlobalData {
|
||||||
let global = self.tys.ins.globals.push(GlobalData {
|
data: data.clone(),
|
||||||
data,
|
|
||||||
ty,
|
ty,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
}))
|
||||||
vacant_entry
|
})
|
||||||
.insert(crate::ctx_map::Key { value: StringRef(global), hash }, ())
|
.0;
|
||||||
.0
|
|
||||||
.value
|
|
||||||
.0
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let global = self.ci.nodes.new_node_nop(ty, Kind::Global { global }, [VOID]);
|
let global = self.ci.nodes.new_node_nop(ty, Kind::Global { global }, [VOID]);
|
||||||
self.ci.nodes[global].aclass = GLOBAL_ACLASS as _;
|
self.ci.nodes[global].aclass = GLOBAL_ACLASS as _;
|
||||||
|
|
||||||
|
data.clear();
|
||||||
|
self.pool.lit_buf = data;
|
||||||
|
|
||||||
Some(Value::new(global).ty(ty))
|
Some(Value::new(global).ty(ty))
|
||||||
}
|
}
|
||||||
Expr::Defer { pos, value } => {
|
Expr::Defer { pos, value } => {
|
||||||
|
@ -3080,9 +3078,7 @@ impl<'a> Codegen<'a> {
|
||||||
self.ci.nodes.new_node_nop(ty::Id::VOID, Kind::Die, [self.ci.ctrl.get()]),
|
self.ci.nodes.new_node_nop(ty::Id::VOID, Kind::Die, [self.ci.ctrl.get()]),
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
);
|
);
|
||||||
|
self.ci.nodes.bind(self.ci.ctrl.get(), NEVER);
|
||||||
self.ci.nodes[NEVER].inputs.push(self.ci.ctrl.get());
|
|
||||||
self.ci.nodes[self.ci.ctrl.get()].outputs.push(NEVER);
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
Expr::Field { target, name, pos } => {
|
Expr::Field { target, name, pos } => {
|
||||||
|
@ -3115,11 +3111,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.implicit_unwrap(val.pos(), &mut vl);
|
self.implicit_unwrap(val.pos(), &mut vl);
|
||||||
|
|
||||||
let Some(base) = self.tys.base_of(vl.ty) else {
|
let Some(base) = self.tys.base_of(vl.ty) else {
|
||||||
self.error(
|
return self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!("the '{}' can not be dereferneced", self.ty_display(vl.ty)),
|
fa!("the '{}' can not be dereferneced", self.ty_display(vl.ty)),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
vl.ptr = true;
|
vl.ptr = true;
|
||||||
vl.ty = base;
|
vl.ty = base;
|
||||||
|
@ -3129,11 +3124,10 @@ impl<'a> Codegen<'a> {
|
||||||
inference!(ty, ctx, self, pos, "enum type", "<EnumTy>.Variant");
|
inference!(ty, ctx, self, pos, "enum type", "<EnumTy>.Variant");
|
||||||
|
|
||||||
let ty::Kind::Enum(e) = ty.expand() else {
|
let ty::Kind::Enum(e) = ty.expand() else {
|
||||||
self.error(
|
return self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!("expected inferred type to be enum but got '{}'", self.ty_display(ty)),
|
fa!("expected inferred type to be enum but got '{}'", self.ty_display(ty)),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let intrnd = self.tys.names.project(self.file().ident_str(id));
|
let intrnd = self.tys.names.project(self.file().ident_str(id));
|
||||||
|
@ -3158,8 +3152,7 @@ impl<'a> Codegen<'a> {
|
||||||
self.tys,
|
self.tys,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
self.error(pos, fa!("cant negate '{}'", self.ty_display(val.ty)));
|
self.error(pos, fa!("cant negate '{}'", self.ty_display(val.ty)))
|
||||||
Value::NEVER
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::UnOp { pos, op: op @ TokenKind::Not, val } => {
|
Expr::UnOp { pos, op: op @ TokenKind::Not, val } => {
|
||||||
|
@ -3173,8 +3166,7 @@ impl<'a> Codegen<'a> {
|
||||||
self.tys,
|
self.tys,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
self.error(pos, fa!("cant logically negate '{}'", self.ty_display(val.ty)));
|
self.error(pos, fa!("cant logically negate '{}'", self.ty_display(val.ty)))
|
||||||
Value::NEVER
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::BinOp { left, op: TokenKind::Decl, right, pos } => {
|
Expr::BinOp { left, op: TokenKind::Decl, right, pos } => {
|
||||||
|
@ -3218,8 +3210,7 @@ impl<'a> Codegen<'a> {
|
||||||
Some(Value::VOID)
|
Some(Value::VOID)
|
||||||
}
|
}
|
||||||
Expr::BinOp { left: &Expr::Null { pos }, .. } => {
|
Expr::BinOp { left: &Expr::Null { pos }, .. } => {
|
||||||
self.error(pos, "'null' must always be no the right side of an expression");
|
self.error(pos, "'null' must always be no the right side of an expression")
|
||||||
Value::NEVER
|
|
||||||
}
|
}
|
||||||
Expr::BinOp {
|
Expr::BinOp {
|
||||||
left,
|
left,
|
||||||
|
@ -3231,11 +3222,10 @@ impl<'a> Codegen<'a> {
|
||||||
self.strip_var(&mut cmped);
|
self.strip_var(&mut cmped);
|
||||||
|
|
||||||
let Some(ty) = self.tys.inner_of(cmped.ty) else {
|
let Some(ty) = self.tys.inner_of(cmped.ty) else {
|
||||||
self.error(
|
return self.error(
|
||||||
left.pos(),
|
left.pos(),
|
||||||
fa!("'{}' is never null, remove this check", self.ty_display(cmped.ty)),
|
fa!("'{}' is never null, remove this check", self.ty_display(cmped.ty)),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(Value::new(self.gen_null_check(cmped, ty, op)).ty(ty::Id::BOOL))
|
Some(Value::new(self.gen_null_check(cmped, ty, op)).ty(ty::Id::BOOL))
|
||||||
|
@ -3316,13 +3306,8 @@ impl<'a> Codegen<'a> {
|
||||||
self.struct_fold_op(left.pos(), op, binding_op, s, lhs.id, rhs.id)
|
self.struct_fold_op(left.pos(), op, binding_op, s, lhs.id, rhs.id)
|
||||||
.or(Value::NEVER)
|
.or(Value::NEVER)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => self
|
||||||
self.error(
|
.error(pos, fa!("'{} {op} _' is not supported", self.ty_display(lhs.ty))),
|
||||||
pos,
|
|
||||||
fa!("'{} {op} _' is not supported", self.ty_display(lhs.ty)),
|
|
||||||
);
|
|
||||||
Value::NEVER
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Index { base, index } => {
|
Expr::Index { base, index } => {
|
||||||
|
@ -3335,14 +3320,13 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let ty::Kind::Slice(s) = bs.ty.expand() else {
|
let ty::Kind::Slice(s) = bs.ty.expand() else {
|
||||||
self.error(
|
return self.error(
|
||||||
base.pos(),
|
base.pos(),
|
||||||
fa!(
|
fa!(
|
||||||
"cant index into '{}' which is not array nor slice",
|
"cant index into '{}' which is not array nor slice",
|
||||||
self.ty_display(bs.ty)
|
self.ty_display(bs.ty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let elem = self.tys.ins.slices[s].elem;
|
let elem = self.tys.ins.slices[s].elem;
|
||||||
|
@ -3421,14 +3405,13 @@ impl<'a> Codegen<'a> {
|
||||||
self.strip_var(&mut val);
|
self.strip_var(&mut val);
|
||||||
|
|
||||||
if !val.ty.is_optional() {
|
if !val.ty.is_optional() {
|
||||||
self.error(
|
return self.error(
|
||||||
expr.pos(),
|
expr.pos(),
|
||||||
fa!(
|
fa!(
|
||||||
"only optional types can be unwrapped ('{}' is not optional)",
|
"only optional types can be unwrapped ('{}' is not optional)",
|
||||||
self.ty_display(val.ty)
|
self.ty_display(val.ty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.explicit_unwrap(expr.pos(), &mut val);
|
self.explicit_unwrap(expr.pos(), &mut val);
|
||||||
|
@ -3438,14 +3421,13 @@ impl<'a> Codegen<'a> {
|
||||||
let mut val = self.expr(expr)?;
|
let mut val = self.expr(expr)?;
|
||||||
|
|
||||||
if !val.ty.is_integer() {
|
if !val.ty.is_integer() {
|
||||||
self.error(
|
return self.error(
|
||||||
expr.pos(),
|
expr.pos(),
|
||||||
fa!(
|
fa!(
|
||||||
"only integers can be truncated ('{}' is not an integer)",
|
"only integers can be truncated ('{}' is not an integer)",
|
||||||
self.ty_display(val.ty)
|
self.ty_display(val.ty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inference!(ty, ctx, self, pos, "integer", "@as(<ty>, @intcast(<expr>))");
|
inference!(ty, ctx, self, pos, "integer", "@as(<ty>, @intcast(<expr>))");
|
||||||
|
@ -3471,14 +3453,13 @@ impl<'a> Codegen<'a> {
|
||||||
let val = self.expr(expr)?;
|
let val = self.expr(expr)?;
|
||||||
|
|
||||||
if !val.ty.is_float() {
|
if !val.ty.is_float() {
|
||||||
self.error(
|
return self.error(
|
||||||
expr.pos(),
|
expr.pos(),
|
||||||
fa!(
|
fa!(
|
||||||
"only floats can be truncated ('{}' is not a float)",
|
"only floats can be truncated ('{}' is not a float)",
|
||||||
self.ty_display(val.ty)
|
self.ty_display(val.ty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inference!(ty, ctx, self, pos, "float", "@as(<floaty>, @floatcast(<expr>))");
|
inference!(ty, ctx, self, pos, "float", "@as(<floaty>, @floatcast(<expr>))");
|
||||||
|
@ -3510,11 +3491,10 @@ impl<'a> Codegen<'a> {
|
||||||
let ret_ty = match val.ty {
|
let ret_ty = match val.ty {
|
||||||
ty::Id::F32 | ty::Id::F64 => ty::Id::INT,
|
ty::Id::F32 | ty::Id::F64 => ty::Id::INT,
|
||||||
_ => {
|
_ => {
|
||||||
self.error(
|
return self.error(
|
||||||
expr.pos(),
|
expr.pos(),
|
||||||
fa!("expected float ('{}' is not a float)", self.ty_display(val.ty)),
|
fa!("expected float ('{}' is not a float)", self.ty_display(val.ty)),
|
||||||
);
|
)
|
||||||
return Value::NEVER;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3653,7 +3633,7 @@ impl<'a> Codegen<'a> {
|
||||||
.map_or_else(|| self.tys.make_array(elem, len as ArrayLen), |_| sty);
|
.map_or_else(|| self.tys.make_array(elem, len as ArrayLen), |_| sty);
|
||||||
|
|
||||||
if len != fields.len() {
|
if len != fields.len() {
|
||||||
self.error(
|
return self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"expected '{}' but constructor has {} elements",
|
"expected '{}' but constructor has {} elements",
|
||||||
|
@ -3661,7 +3641,6 @@ impl<'a> Codegen<'a> {
|
||||||
fields.len()
|
fields.len()
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mem = self.new_stack(pos, aty);
|
let mem = self.new_stack(pos, aty);
|
||||||
|
@ -3677,18 +3656,15 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
Some(Value::ptr(mem).ty(aty))
|
Some(Value::ptr(mem).ty(aty))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => self.error(
|
||||||
let inferred = if ty.is_some() { "" } else { "inferred " };
|
pos,
|
||||||
self.error(
|
fa!(
|
||||||
pos,
|
"the {}type of the constructor is `{}`, \
|
||||||
fa!(
|
|
||||||
"the {inferred}type of the constructor is `{}`, \
|
|
||||||
but thats not a struct nor slice or array",
|
but thats not a struct nor slice or array",
|
||||||
self.ty_display(sty)
|
if ty.is_some() { "" } else { "inferred " },
|
||||||
),
|
self.ty_display(sty),
|
||||||
);
|
),
|
||||||
Value::NEVER
|
),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Struct { .. } => {
|
Expr::Struct { .. } => {
|
||||||
|
@ -3712,15 +3688,14 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
let mem = self.new_stack(pos, sty);
|
let mem = self.new_stack(pos, sty);
|
||||||
|
|
||||||
let Some(index) = self.tys.find_union_field(u, name) else {
|
let Some((_, field)) = self.tys.find_union_field(u, name) else {
|
||||||
self.error(
|
return self.error(
|
||||||
fpos,
|
fpos,
|
||||||
fa!("union '{}' does not have this field", self.ty_display(sty)),
|
fa!("union '{}' does not have this field", self.ty_display(sty)),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let (ty, offset) = (self.tys.union_fields(u)[index].ty, 0);
|
let (ty, offset) = (field.ty, 0);
|
||||||
|
|
||||||
let mut value = self.expr_ctx(&value, Ctx::default().with_ty(ty))?;
|
let mut value = self.expr_ctx(&value, Ctx::default().with_ty(ty))?;
|
||||||
self.assert_ty(fpos, &mut value, ty, fa!("field {}", name));
|
self.assert_ty(fpos, &mut value, ty, fa!("field {}", name));
|
||||||
|
@ -4118,14 +4093,13 @@ impl<'a> Codegen<'a> {
|
||||||
let value = self.expr(value)?;
|
let value = self.expr(value)?;
|
||||||
|
|
||||||
let ty::Kind::Enum(e) = value.ty.expand() else {
|
let ty::Kind::Enum(e) = value.ty.expand() else {
|
||||||
self.error(
|
return self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"match operates on enums (for now), '{}' is not an enum",
|
"match operates on enums (for now), '{}' is not an enum",
|
||||||
self.ty_display(value.ty)
|
self.ty_display(value.ty)
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut covered_values = vec![Pos::MAX; self.tys.enum_field_range(e).len()];
|
let mut covered_values = vec![Pos::MAX; self.tys.enum_field_range(e).len()];
|
||||||
|
@ -4142,7 +4116,7 @@ impl<'a> Codegen<'a> {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
let pat_val = self.eval_const(self.ci.file, &pat, value.ty);
|
let pat_val = self.eval_const(self.ci.file, self.ci.parent, &pat, value.ty);
|
||||||
if covered_values[pat_val as usize] != Pos::MAX {
|
if covered_values[pat_val as usize] != Pos::MAX {
|
||||||
self.error(bp, "duplicate branch");
|
self.error(bp, "duplicate branch");
|
||||||
self.error(
|
self.error(
|
||||||
|
@ -4241,93 +4215,78 @@ impl<'a> Codegen<'a> {
|
||||||
let tty = vtarget.ty;
|
let tty = vtarget.ty;
|
||||||
|
|
||||||
match self.tys.base_of(tty).unwrap_or(tty).expand() {
|
match self.tys.base_of(tty).unwrap_or(tty).expand() {
|
||||||
ty::Kind::Module(m) => self.find_type_as_value(pos, m, m, Err(name), ctx),
|
ty::Kind::Module(m) => self.find_type_as_value(pos, m, name, ctx),
|
||||||
ty::Kind::Enum(e) => {
|
ty::Kind::Enum(e) => {
|
||||||
let intrnd = self.tys.names.project(name);
|
let intrnd = self.tys.names.project(name);
|
||||||
self.gen_enum_variant(pos, e, intrnd)
|
self.gen_enum_variant(pos, e, intrnd)
|
||||||
}
|
}
|
||||||
ty::Kind::Union(u) => {
|
ty::Kind::Union(u) => {
|
||||||
let TypeBase { ast, file, .. } = *self.tys.ins.unions[u];
|
if let Some((_, f)) = self.tys.find_union_field(u, name) {
|
||||||
if let Some(f) =
|
|
||||||
self.tys.find_union_field(u, name).map(|i| &self.tys.union_fields(u)[i])
|
|
||||||
{
|
|
||||||
Some(Value::ptr(vtarget.id).ty(f.ty))
|
Some(Value::ptr(vtarget.id).ty(f.ty))
|
||||||
} else if let Expr::Struct { fields: [.., CommentOr::Or(Err(_))], .. } =
|
} else if let ty = self.find_type(pos, self.ci.file, u, name)
|
||||||
ast.get(&self.files[file.index()])
|
|
||||||
&& let ty = self.find_type(pos, self.ci.file, file, u.into(), Err(name))
|
|
||||||
&& let ty::Kind::Func(_) = ty.expand()
|
&& let ty::Kind::Func(_) = ty.expand()
|
||||||
{
|
{
|
||||||
return Some(Err((ty, vtarget)));
|
return Some(Err((ty, vtarget)));
|
||||||
} else {
|
} else {
|
||||||
let field_list = self
|
|
||||||
.tys
|
|
||||||
.union_fields(u)
|
|
||||||
.iter()
|
|
||||||
.map(|f| self.tys.names.ident_str(f.name))
|
|
||||||
.intersperse("', '")
|
|
||||||
.collect::<String>();
|
|
||||||
self.error(
|
self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"the '{}' does not have this field, \
|
"the '{}' does not have this field, \
|
||||||
but it does have '{field_list}'",
|
but it does have '{}'",
|
||||||
self.ty_display(tty)
|
self.ty_display(tty),
|
||||||
|
self.tys
|
||||||
|
.union_fields(u)
|
||||||
|
.iter()
|
||||||
|
.map(|f| self.tys.names.ident_str(f.name))
|
||||||
|
.intersperse("', '")
|
||||||
|
.collect::<String>()
|
||||||
),
|
),
|
||||||
);
|
)
|
||||||
Value::NEVER
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Kind::Struct(s) => {
|
ty::Kind::Struct(s) => {
|
||||||
let TypeBase { ast, file, .. } = *self.tys.ins.structs[s];
|
|
||||||
if let Some((offset, ty)) = OffsetIter::offset_of(self.tys, s, name) {
|
if let Some((offset, ty)) = OffsetIter::offset_of(self.tys, s, name) {
|
||||||
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
Some(Value::ptr(self.offset(vtarget.id, offset)).ty(ty))
|
||||||
} else if let Expr::Struct { fields: [.., CommentOr::Or(Err(_))], .. } =
|
} else if let ty = self.find_type(pos, self.ci.file, s, name)
|
||||||
ast.get(&self.files[file.index()])
|
|
||||||
&& let ty = self.find_type(pos, self.ci.file, file, s.into(), Err(name))
|
|
||||||
&& let ty::Kind::Func(_) = ty.expand()
|
&& let ty::Kind::Func(_) = ty.expand()
|
||||||
{
|
{
|
||||||
return Some(Err((ty, vtarget)));
|
return Some(Err((ty, vtarget)));
|
||||||
} else {
|
} else {
|
||||||
let field_list = self
|
|
||||||
.tys
|
|
||||||
.struct_fields(s)
|
|
||||||
.iter()
|
|
||||||
.map(|f| self.tys.names.ident_str(f.name))
|
|
||||||
.intersperse("', '")
|
|
||||||
.collect::<String>();
|
|
||||||
self.error(
|
self.error(
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"the '{}' does not have this field, \
|
"the '{}' does not have this field, \
|
||||||
but it does have '{field_list}'",
|
but it does have '{}'",
|
||||||
self.ty_display(tty)
|
self.ty_display(tty),
|
||||||
|
self.tys
|
||||||
|
.struct_fields(s)
|
||||||
|
.iter()
|
||||||
|
.map(|f| self.tys.names.ident_str(f.name))
|
||||||
|
.intersperse("', '")
|
||||||
|
.collect::<String>()
|
||||||
),
|
),
|
||||||
);
|
)
|
||||||
Value::NEVER
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Kind::TYPE => match self.ci.nodes.as_ty(vtarget.id).expand() {
|
ty::Kind::TYPE => match self.ci.nodes.as_ty(vtarget.id).expand() {
|
||||||
ty::Kind::Struct(s) => {
|
ty::Kind::Module(m) => self.find_type_as_value(pos, m, name, ctx),
|
||||||
let TypeBase { file, .. } = *self.tys.ins.structs[s];
|
ty::Kind::Enum(e)
|
||||||
self.find_type_as_value(pos, file, s, Err(name), ctx)
|
if let intrnd = self.tys.names.project(name)
|
||||||
|
&& let Some(index) =
|
||||||
|
self.tys.enum_fields(e).iter().position(|f| Some(f.name) == intrnd) =>
|
||||||
|
{
|
||||||
|
Some(self.ci.nodes.new_const_lit(e.into(), index as i64))
|
||||||
}
|
}
|
||||||
ty::Kind::Union(u) => {
|
ty @ (ty::Kind::Struct(_) | ty::Kind::Enum(_) | ty::Kind::Union(_)) => {
|
||||||
let TypeBase { file, .. } = *self.tys.ins.unions[u];
|
self.find_type_as_value(pos, ty.compress(), name, ctx)
|
||||||
self.find_type_as_value(pos, file, u, Err(name), ctx)
|
|
||||||
}
|
}
|
||||||
ty::Kind::Module(m) => self.find_type_as_value(pos, m, m, Err(name), ctx),
|
ty @ (ty::Kind::Builtin(_)
|
||||||
ty::Kind::Enum(e) => {
|
| ty::Kind::Ptr(_)
|
||||||
let intrnd = self.tys.names.project(name);
|
| ty::Kind::Slice(_)
|
||||||
if let Some(index) =
|
| ty::Kind::Opt(_)
|
||||||
self.tys.enum_fields(e).iter().position(|f| Some(f.name) == intrnd)
|
| ty::Kind::Func(_)
|
||||||
{
|
| ty::Kind::Global(_)
|
||||||
Some(self.ci.nodes.new_const_lit(e.into(), index as i64))
|
| ty::Kind::Const(_)) => self.error(
|
||||||
} else {
|
|
||||||
let TypeBase { file, .. } = *self.tys.ins.enums[e];
|
|
||||||
self.find_type_as_value(pos, file, e, Err(name), ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ty => self.error(
|
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"accesing scope on '{}' is not supported yet",
|
"accesing scope on '{}' is not supported yet",
|
||||||
|
@ -4380,22 +4339,20 @@ impl<'a> Codegen<'a> {
|
||||||
fn gen_enum_variant(&mut self, pos: Pos, e: ty::Enum, intrnd: Option<Ident>) -> Option<Value> {
|
fn gen_enum_variant(&mut self, pos: Pos, e: ty::Enum, intrnd: Option<Ident>) -> Option<Value> {
|
||||||
let Some(index) = self.tys.enum_fields(e).iter().position(|f| Some(f.name) == intrnd)
|
let Some(index) = self.tys.enum_fields(e).iter().position(|f| Some(f.name) == intrnd)
|
||||||
else {
|
else {
|
||||||
let field_list = self
|
return self.error(
|
||||||
.tys
|
|
||||||
.enum_fields(e)
|
|
||||||
.iter()
|
|
||||||
.map(|f| self.tys.names.ident_str(f.name))
|
|
||||||
.intersperse("', '")
|
|
||||||
.collect::<String>();
|
|
||||||
self.error(
|
|
||||||
pos,
|
pos,
|
||||||
fa!(
|
fa!(
|
||||||
"the '{}' does not have this variant, \
|
"the '{}' does not have this variant, \
|
||||||
but it does have '{field_list}'",
|
but it does have '{}'",
|
||||||
self.ty_display(e.into())
|
self.ty_display(e.into()),
|
||||||
|
self.tys
|
||||||
|
.enum_fields(e)
|
||||||
|
.iter()
|
||||||
|
.map(|f| self.tys.names.ident_str(f.name))
|
||||||
|
.intersperse("', '")
|
||||||
|
.collect::<String>()
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return Value::NEVER;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Some(self.ci.nodes.new_const_lit(e.into(), index as i64))
|
Some(self.ci.nodes.new_const_lit(e.into(), index as i64))
|
||||||
|
@ -4445,7 +4402,7 @@ impl<'a> Codegen<'a> {
|
||||||
inline |= sig.ret == ty::Id::TYPE;
|
inline |= sig.ret == ty::Id::TYPE;
|
||||||
|
|
||||||
let FuncData { expr, file, is_inline, parent, .. } = self.tys.ins.funcs[fu];
|
let FuncData { expr, file, is_inline, parent, .. } = self.tys.ins.funcs[fu];
|
||||||
let ast = &self.files[file.index()];
|
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!() };
|
||||||
|
|
||||||
let arg_count = args.len() + caller.is_some() as usize;
|
let arg_count = args.len() + caller.is_some() as usize;
|
||||||
|
@ -4661,7 +4618,7 @@ impl<'a> Codegen<'a> {
|
||||||
let c = &self.tys.ins.consts[cnst];
|
let c = &self.tys.ins.consts[cnst];
|
||||||
let prev_file = mem::replace(&mut self.ci.file, c.file);
|
let prev_file = mem::replace(&mut self.ci.file, c.file);
|
||||||
let prev_parent = mem::replace(&mut self.ci.parent, c.parent);
|
let prev_parent = mem::replace(&mut self.ci.parent, c.parent);
|
||||||
let f = &self.files[c.file.index()];
|
let f = &self.files[c.file];
|
||||||
let Expr::BinOp { left, right, .. } = c.ast.get(f) else { unreachable!() };
|
let Expr::BinOp { left, right, .. } = c.ast.get(f) else { unreachable!() };
|
||||||
|
|
||||||
let mut value = left
|
let mut value = left
|
||||||
|
@ -4806,7 +4763,7 @@ 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: &mut ty::Func, pos: Pos, args: &[Expr]) -> Option<Sig> {
|
||||||
let FuncData { file, expr, sig, parent, .. } = self.tys.ins.funcs[*func];
|
let FuncData { file, expr, sig, parent, .. } = self.tys.ins.funcs[*func];
|
||||||
let fast = &self.files[file.index()];
|
let fast = &self.files[file];
|
||||||
let &Expr::Closure { args: cargs, ret, .. } = expr.get(fast) else {
|
let &Expr::Closure { args: cargs, ret, .. } = expr.get(fast) else {
|
||||||
unreachable!();
|
unreachable!();
|
||||||
};
|
};
|
||||||
|
@ -5035,7 +4992,7 @@ impl<'a> Codegen<'a> {
|
||||||
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;
|
||||||
let sig = func.sig.expect("to emmit only concrete functions");
|
let sig = func.sig.expect("to emmit only concrete functions");
|
||||||
let ast = &self.files[file.index()];
|
let ast = &self.files[file];
|
||||||
let expr = func.expr.get(ast);
|
let expr = func.expr.get(ast);
|
||||||
|
|
||||||
self.pool.push_ci(file, func.parent, Some(sig.ret), 0, &mut self.ci);
|
self.pool.push_ci(file, func.parent, Some(sig.ret), 0, &mut self.ci);
|
||||||
|
@ -5445,22 +5402,18 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn file(&self) -> &'a parser::Ast {
|
fn file(&self) -> &'a parser::Ast {
|
||||||
&self.files[self.ci.file.index()]
|
&self.files[self.ci.file]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn eval_const(&mut self, file: Module, expr: &Expr, ret: ty::Id) -> u64 {
|
fn eval_const(&mut self, file: Module, parent: ty::Id, expr: &Expr, ret: ty::Id) -> u64 {
|
||||||
self.ct.activate();
|
self.ct.activate();
|
||||||
let scope = self
|
let prev = self.pool.push_ci(file, parent, Some(ret), self.tys.tasks.len(), &mut self.ci);
|
||||||
.ci
|
|
||||||
.scope
|
prev.scope
|
||||||
.vars
|
.vars
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|v| v.ty == ty::Id::TYPE)
|
.filter(|v| v.ty == ty::Id::TYPE)
|
||||||
.map(|v| (self.ci.nodes.as_ty(v.value()), v.id))
|
.map(|v| (prev.nodes.as_ty(v.value()), v.id))
|
||||||
.collect::<Vec<_>>();
|
|
||||||
self.pool.push_ci(file, self.ci.parent, Some(ret), self.tys.tasks.len(), &mut self.ci);
|
|
||||||
self.ci.scope.vars = scope
|
|
||||||
.into_iter()
|
|
||||||
.map(|(v, id)| {
|
.map(|(v, id)| {
|
||||||
Variable::new(
|
Variable::new(
|
||||||
id,
|
id,
|
||||||
|
@ -5470,14 +5423,17 @@ impl<'a> Codegen<'a> {
|
||||||
&mut self.ci.nodes,
|
&mut self.ci.nodes,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.collect();
|
.collect_into(&mut self.ci.scope.vars);
|
||||||
|
|
||||||
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) });
|
||||||
|
|
||||||
let res =
|
let res = if self.finalize(prev_err_len) {
|
||||||
if self.finalize(prev_err_len) { self.emit_and_eval(file, ret, &mut []) } else { 1 };
|
self.emit_and_eval(file, ret, &mut [])
|
||||||
|
} else {
|
||||||
|
i64::from(ty::Id::UNDECLARED) as _
|
||||||
|
};
|
||||||
|
|
||||||
self.pool.pop_ci(&mut self.ci);
|
self.pool.pop_ci(&mut self.ci);
|
||||||
|
|
||||||
|
@ -5532,13 +5488,13 @@ impl<'a> Codegen<'a> {
|
||||||
|
|
||||||
fn error_low(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id {
|
fn error_low(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id {
|
||||||
let mut buf = self.errors.borrow_mut();
|
let mut buf = self.errors.borrow_mut();
|
||||||
write!(buf, "{}", self.files[file.index()].report(pos, msg)).unwrap();
|
write!(buf, "{}", self.files[file].report(pos, msg)).unwrap();
|
||||||
ty::Id::NEVER
|
ty::Id::NEVER
|
||||||
}
|
}
|
||||||
|
|
||||||
fn warn_low(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id {
|
fn warn_low(&self, file: Module, pos: Pos, msg: impl Display) -> ty::Id {
|
||||||
let mut buf = self.warnings.borrow_mut();
|
let mut buf = self.warnings.borrow_mut();
|
||||||
write!(buf, "(W) {}", self.files[file.index()].report(pos, msg)).unwrap();
|
write!(buf, "(W) {}", self.files[file].report(pos, msg)).unwrap();
|
||||||
ty::Id::NEVER
|
ty::Id::NEVER
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5551,23 +5507,14 @@ impl<'a> Codegen<'a> {
|
||||||
.map(|v| self.ci.nodes.as_ty(v.value()))
|
.map(|v| self.ci.nodes.as_ty(v.value()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_type_in_file(&mut self, pos: Pos, file: Module, id: Result<Ident, &str>) -> ty::Id {
|
|
||||||
self.find_type(pos, file, file, file.into(), id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_type_in_scope(&mut self, pos: Pos, id: Result<Ident, &str>) -> ty::Id {
|
|
||||||
self.find_type(pos, self.ci.file, self.ci.file, self.ci.parent, id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_type_as_value(
|
fn find_type_as_value(
|
||||||
&mut self,
|
&mut self,
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
file: Module,
|
|
||||||
parent: impl Into<ty::Id>,
|
parent: impl Into<ty::Id>,
|
||||||
id: Result<Ident, &str>,
|
id: impl Into<DeclId>,
|
||||||
ctx: Ctx,
|
ctx: Ctx,
|
||||||
) -> Option<Value> {
|
) -> Option<Value> {
|
||||||
match self.find_type(pos, self.ci.file, file, parent.into(), id).expand() {
|
match self.find_type(pos, self.ci.file, parent, id).expand() {
|
||||||
ty::Kind::NEVER => Value::NEVER,
|
ty::Kind::NEVER => Value::NEVER,
|
||||||
ty::Kind::Global(global) => self.gen_global(global),
|
ty::Kind::Global(global) => self.gen_global(global),
|
||||||
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
ty::Kind::Const(cnst) => self.gen_const(cnst, ctx),
|
||||||
|
@ -5579,21 +5526,29 @@ impl<'a> Codegen<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
from_file: Module,
|
from_file: Module,
|
||||||
file: Module,
|
parent: impl Into<ty::Id>,
|
||||||
parent: ty::Id,
|
id: impl Into<DeclId>,
|
||||||
id: Result<Ident, &str>,
|
|
||||||
) -> ty::Id {
|
) -> ty::Id {
|
||||||
let ty = if let Ok(id) = id
|
self.find_type_low(pos, from_file, parent.into(), id.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_type_low(&mut self, pos: Pos, from_file: Module, parent: ty::Id, id: DeclId) -> ty::Id {
|
||||||
|
let file = match parent.expand() {
|
||||||
|
ty::Kind::Module(m) => m,
|
||||||
|
_ => self.tys.type_base_of(parent).unwrap().file,
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = if let DeclId::Ident(id) = id
|
||||||
&& let Some(ty) = self.find_local_ty(id)
|
&& let Some(ty) = self.find_local_ty(id)
|
||||||
{
|
{
|
||||||
ty
|
ty
|
||||||
} else if let Ok(id) = id
|
} else if let DeclId::Ident(id) = id
|
||||||
&& let Some(&ty) = self.tys.syms.get(SymKey::Decl(parent, id), &self.tys.ins)
|
&& let Some(&ty) = self.tys.syms.get(SymKey::Decl(parent, id), &self.tys.ins)
|
||||||
{
|
{
|
||||||
self.on_reuse(ty);
|
self.on_reuse(ty);
|
||||||
ty
|
ty
|
||||||
} else {
|
} else {
|
||||||
let f = &self.files[file.index()];
|
let f = &self.files[file];
|
||||||
|
|
||||||
let mut piter = parent;
|
let mut piter = parent;
|
||||||
let Some((expr @ Expr::BinOp { left, right, .. }, name)) = (loop {
|
let Some((expr @ Expr::BinOp { left, right, .. }, name)) = (loop {
|
||||||
|
@ -5604,7 +5559,7 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some((captures, capture_tuple)) = self.tys.captures_of(piter, f)
|
if let Some((captures, capture_tuple)) = self.tys.captures_of(piter, f)
|
||||||
&& let Some(idx) = captures.iter().position(|&cid| Ok(cid) == id)
|
&& let Some(idx) = captures.iter().position(|&cid| DeclId::Ident(cid) == id)
|
||||||
{
|
{
|
||||||
return self.tys.ins.args[capture_tuple.range().start + idx];
|
return self.tys.ins.args[capture_tuple.range().start + idx];
|
||||||
}
|
}
|
||||||
|
@ -5620,11 +5575,11 @@ impl<'a> Codegen<'a> {
|
||||||
};
|
};
|
||||||
}) else {
|
}) else {
|
||||||
return match id {
|
return match id {
|
||||||
Ok(_) => {
|
DeclId::Ident(id) => {
|
||||||
debug_assert_eq!(from_file, file);
|
debug_assert_eq!(from_file, file, "{}", f.ident_str(id));
|
||||||
self.error_low(file, pos, "somehow this was not found")
|
self.error_low(file, pos, "somehow this was not found")
|
||||||
}
|
}
|
||||||
Err("main") => self.error_low(
|
DeclId::Name("main") => self.error_low(
|
||||||
from_file,
|
from_file,
|
||||||
pos,
|
pos,
|
||||||
format_args!(
|
format_args!(
|
||||||
|
@ -5634,7 +5589,7 @@ impl<'a> Codegen<'a> {
|
||||||
f.path
|
f.path
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Err(name) => self.error_low(
|
DeclId::Name(name) => self.error_low(
|
||||||
from_file,
|
from_file,
|
||||||
pos,
|
pos,
|
||||||
format_args!("undefined indentifier: {name}"),
|
format_args!("undefined indentifier: {name}"),
|
||||||
|
@ -5648,21 +5603,19 @@ impl<'a> Codegen<'a> {
|
||||||
} else {
|
} else {
|
||||||
let (is_ct, ty) = left
|
let (is_ct, 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 { .. }) {
|
||||||
is_ct,
|
self.tys
|
||||||
if is_ct && !matches!(right, Expr::Closure { .. }) {
|
.ins
|
||||||
self.tys
|
.consts
|
||||||
.ins
|
.push(ConstData { ast: ExprRef::new(expr), name, file, parent })
|
||||||
.consts
|
.into()
|
||||||
.push(ConstData { ast: ExprRef::new(expr), name, file, parent })
|
} else {
|
||||||
.into()
|
self.parse_ty(
|
||||||
} else {
|
TyScope { file, parent, name: Some(name), alloc_const: true },
|
||||||
self.parse_ty(
|
right,
|
||||||
TyScope { file, parent, name: Some(name), alloc_const: true },
|
)
|
||||||
right,
|
};
|
||||||
)
|
(is_ct, ty)
|
||||||
},
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.unwrap_or_else(|_| unreachable!());
|
.unwrap_or_else(|_| unreachable!());
|
||||||
if let ty::Kind::Func(f) = ty.expand()
|
if let ty::Kind::Func(f) = ty.expand()
|
||||||
|
@ -5715,11 +5668,11 @@ impl<'a> Codegen<'a> {
|
||||||
self.tys.make_opt(base)
|
self.tys.make_opt(base)
|
||||||
}
|
}
|
||||||
Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => bt.into(),
|
Expr::Ident { id, .. } if let Ok(bt) = ty::Builtin::try_from(id) => bt.into(),
|
||||||
Expr::Ident { id, pos, .. } => self.find_type(pos, sc.file, sc.file, sc.parent, Ok(id)),
|
Expr::Ident { id, pos, .. } => self.find_type(pos, sc.file, sc.parent, id),
|
||||||
Expr::Field { target, pos, name }
|
Expr::Field { target, pos, name }
|
||||||
if let ty::Kind::Module(inside) = self.parse_ty(sc.anon(), target).expand() =>
|
if let ty::Kind::Module(inside) = self.parse_ty(sc.anon(), target).expand() =>
|
||||||
{
|
{
|
||||||
self.find_type(pos, sc.file, inside, inside.into(), Err(name))
|
self.find_type(pos, sc.file, inside, name)
|
||||||
}
|
}
|
||||||
Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr),
|
Expr::Directive { name: "TypeOf", args: [expr], .. } => self.infer_type(expr),
|
||||||
Expr::Slice { size: None, item, .. } => {
|
Expr::Slice { size: None, item, .. } => {
|
||||||
|
@ -5732,8 +5685,9 @@ impl<'a> Codegen<'a> {
|
||||||
}
|
}
|
||||||
Expr::Slice { size, item, .. } => {
|
Expr::Slice { size, item, .. } => {
|
||||||
let ty = self.parse_ty(sc.anon(), item);
|
let ty = self.parse_ty(sc.anon(), item);
|
||||||
let len = size
|
let len = size.map_or(ArrayLen::MAX, |expr| {
|
||||||
.map_or(ArrayLen::MAX, |expr| self.eval_const(sc.file, expr, ty::Id::U32) as _);
|
self.eval_const(sc.file, sc.parent, expr, ty::Id::U32) as _
|
||||||
|
});
|
||||||
self.tys.make_array(ty, len)
|
self.tys.make_array(ty, len)
|
||||||
}
|
}
|
||||||
Expr::Struct { pos, fields, packed, captured, .. } => self.parse_base_ty(
|
Expr::Struct { pos, fields, packed, captured, .. } => self.parse_base_ty(
|
||||||
|
@ -5786,8 +5740,7 @@ impl<'a> Codegen<'a> {
|
||||||
sig: 'b: {
|
sig: 'b: {
|
||||||
let arg_base = self.tys.tmp.args.len();
|
let arg_base = self.tys.tmp.args.len();
|
||||||
for arg in args {
|
for arg in args {
|
||||||
let sym =
|
let sym = parser::find_symbol(&self.files[sc.file].symbols, arg.id);
|
||||||
parser::find_symbol(&self.files[sc.file.index()].symbols, arg.id);
|
|
||||||
if sym.flags & idfl::COMPTIME != 0 {
|
if sym.flags & idfl::COMPTIME != 0 {
|
||||||
self.tys.tmp.args.truncate(arg_base);
|
self.tys.tmp.args.truncate(arg_base);
|
||||||
break 'b None;
|
break 'b None;
|
||||||
|
@ -5815,7 +5768,9 @@ impl<'a> Codegen<'a> {
|
||||||
{
|
{
|
||||||
self.eval_global(sc.file, name, expr)
|
self.eval_global(sc.file, name, expr)
|
||||||
}
|
}
|
||||||
_ if sc.alloc_const => ty::Id::from(self.eval_const(sc.file, expr, ty::Id::TYPE)),
|
_ if sc.alloc_const => {
|
||||||
|
ty::Id::from(self.eval_const(sc.file, sc.parent, expr, ty::Id::TYPE))
|
||||||
|
}
|
||||||
ref e => {
|
ref e => {
|
||||||
self.error_unhandled_ast(e, "bruh");
|
self.error_unhandled_ast(e, "bruh");
|
||||||
ty::Id::NEVER
|
ty::Id::NEVER
|
||||||
|
|
|
@ -3,7 +3,7 @@ use {
|
||||||
ctx_map,
|
ctx_map,
|
||||||
lexer::TokenKind,
|
lexer::TokenKind,
|
||||||
parser::{self, CommentOr, Expr, ExprRef, Pos},
|
parser::{self, CommentOr, Expr, ExprRef, Pos},
|
||||||
utils::{self, Ent, EntVec},
|
utils::{self, Ent, EntSlice, EntVec},
|
||||||
Ident,
|
Ident,
|
||||||
},
|
},
|
||||||
alloc::{string::String, vec::Vec},
|
alloc::{string::String, vec::Vec},
|
||||||
|
@ -480,12 +480,12 @@ impl Default for Kind {
|
||||||
|
|
||||||
pub struct Display<'a> {
|
pub struct Display<'a> {
|
||||||
tys: &'a Types,
|
tys: &'a Types,
|
||||||
files: &'a [parser::Ast],
|
files: &'a EntSlice<Module, parser::Ast>,
|
||||||
ty: Id,
|
ty: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Display<'a> {
|
impl<'a> Display<'a> {
|
||||||
pub fn new(tys: &'a Types, files: &'a [parser::Ast], ty: Id) -> Self {
|
pub fn new(tys: &'a Types, files: &'a EntSlice<Module, parser::Ast>, ty: Id) -> Self {
|
||||||
Self { tys, files, ty }
|
Self { tys, files, ty }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,7 +500,7 @@ impl core::fmt::Display for Display<'_> {
|
||||||
match TK::from_ty(self.ty) {
|
match TK::from_ty(self.ty) {
|
||||||
TK::Module(idx) => {
|
TK::Module(idx) => {
|
||||||
f.write_str("@use(\"")?;
|
f.write_str("@use(\"")?;
|
||||||
self.files[idx.index()].path.fmt(f)?;
|
self.files[idx].path.fmt(f)?;
|
||||||
f.write_str(")[")?;
|
f.write_str(")[")?;
|
||||||
idx.fmt(f)?;
|
idx.fmt(f)?;
|
||||||
f.write_str("]")
|
f.write_str("]")
|
||||||
|
@ -532,7 +532,7 @@ impl core::fmt::Display for Display<'_> {
|
||||||
}
|
}
|
||||||
f.write_str("}")
|
f.write_str("}")
|
||||||
} else {
|
} else {
|
||||||
let file = &self.files[record.file.index()];
|
let file = &self.files[record.file];
|
||||||
f.write_str(file.ident_str(record.name))
|
f.write_str(file.ident_str(record.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -554,14 +554,14 @@ impl core::fmt::Display for Display<'_> {
|
||||||
}
|
}
|
||||||
f.write_str("}")
|
f.write_str("}")
|
||||||
} else {
|
} else {
|
||||||
let file = &self.files[record.file.index()];
|
let file = &self.files[record.file];
|
||||||
f.write_str(file.ident_str(record.name))
|
f.write_str(file.ident_str(record.name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TK::Enum(idx) => {
|
TK::Enum(idx) => {
|
||||||
let enm = &self.tys.ins.enums[idx];
|
let enm = &self.tys.ins.enums[idx];
|
||||||
debug_assert!(!enm.name.is_null());
|
debug_assert!(!enm.name.is_null());
|
||||||
let file = &self.files[enm.file.index()];
|
let file = &self.files[enm.file];
|
||||||
f.write_str(file.ident_str(enm.name))
|
f.write_str(file.ident_str(enm.name))
|
||||||
}
|
}
|
||||||
TK::Func(idx) => {
|
TK::Func(idx) => {
|
||||||
|
@ -570,7 +570,7 @@ impl core::fmt::Display for Display<'_> {
|
||||||
}
|
}
|
||||||
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.index()];
|
let file = &self.files[global.file];
|
||||||
f.write_str(file.ident_str(global.name))?;
|
f.write_str(file.ident_str(global.name))?;
|
||||||
f.write_str(" (global)")
|
f.write_str(" (global)")
|
||||||
}
|
}
|
||||||
|
@ -586,7 +586,7 @@ impl core::fmt::Display for Display<'_> {
|
||||||
}
|
}
|
||||||
TK::Const(idx) => {
|
TK::Const(idx) => {
|
||||||
let cnst = &self.tys.ins.consts[idx];
|
let cnst = &self.tys.ins.consts[idx];
|
||||||
let file = &self.files[cnst.file.index()];
|
let file = &self.files[cnst.file];
|
||||||
f.write_str(file.ident_str(cnst.name))?;
|
f.write_str(file.ident_str(cnst.name))?;
|
||||||
f.write_str(" (const)")
|
f.write_str(" (const)")
|
||||||
}
|
}
|
||||||
|
@ -1029,9 +1029,9 @@ impl Types {
|
||||||
self.struct_fields(s).iter().position(|f| f.name == name)
|
self.struct_fields(s).iter().position(|f| f.name == name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_union_field(&self, u: Union, name: &str) -> Option<usize> {
|
pub fn find_union_field(&self, u: Union, name: &str) -> Option<(usize, &StructField)> {
|
||||||
let name = self.names.project(name)?;
|
let name = self.names.project(name)?;
|
||||||
self.union_fields(u).iter().position(|f| f.name == name)
|
self.union_fields(u).iter().enumerate().find(|(_, f)| f.name == name)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
|
@ -1053,7 +1053,7 @@ impl Types {
|
||||||
debug_assert_eq!(self.tasks.len(), 0);
|
debug_assert_eq!(self.tasks.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_base_of(&self, id: Id) -> Option<&TypeBase> {
|
pub fn type_base_of(&self, id: Id) -> Option<&TypeBase> {
|
||||||
Some(match id.expand() {
|
Some(match id.expand() {
|
||||||
Kind::Struct(s) => &*self.ins.structs[s],
|
Kind::Struct(s) => &*self.ins.structs[s],
|
||||||
Kind::Enum(e) => &*self.ins.enums[e],
|
Kind::Enum(e) => &*self.ins.enums[e],
|
||||||
|
|
|
@ -559,6 +559,26 @@ pub trait Ent: Copy {
|
||||||
fn index(self) -> usize;
|
fn index(self) -> usize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
pub struct EntSlice<K: Ent, T> {
|
||||||
|
k: PhantomData<fn(K)>,
|
||||||
|
data: [T],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, K: Ent, T> From<&'a [T]> for &'a EntSlice<K, T> {
|
||||||
|
fn from(value: &'a [T]) -> Self {
|
||||||
|
unsafe { core::mem::transmute(value) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<K: Ent, T> core::ops::Index<K> for EntSlice<K, T> {
|
||||||
|
type Output = T;
|
||||||
|
|
||||||
|
fn index(&self, index: K) -> &Self::Output {
|
||||||
|
&self.data[index.index()]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EntVec<K: Ent, T> {
|
pub struct EntVec<K: Ent, T> {
|
||||||
data: ::alloc::vec::Vec<T>,
|
data: ::alloc::vec::Vec<T>,
|
||||||
k: PhantomData<fn(K)>,
|
k: PhantomData<fn(K)>,
|
||||||
|
|
Loading…
Reference in a new issue