calculations have been made

This commit is contained in:
2025-05-09 15:16:54 -04:00
parent 4586361000
commit 11ab9285f1
13 changed files with 410 additions and 423 deletions
+9 -10
View File
@@ -1,7 +1,4 @@
use crate::{
common::{CompilerMsg, CompilerOutput},
ir::RType,
};
use crate::common::{CompilerMsg, CompilerOutput};
use super::{
IdentStatus, KindTy, MemberTy, Origin, Res, ResBase, StructID, Type, TypeID, UProgram,
@@ -119,12 +116,14 @@ pub fn report_errs(p: &UProgram, output: &mut CompilerOutput, mut errs: Vec<ResE
}
}
for var in &p.vars {
match &p.types[var.ty] {
Type::Real(RType::Infer) => output.err(CompilerMsg::new(
format!("Type of {:?} cannot be inferred", var.name),
var.origin,
)),
_ => (),
if let Some(ty) = var.ty() {
match &p.types[ty] {
Type::Infer => output.err(CompilerMsg::new(
format!("Type of {:?} cannot be inferred", var.name),
var.origin,
)),
_ => (),
}
}
}
}
+105 -84
View File
@@ -1,5 +1,110 @@
use super::*;
impl UProgram {
pub fn resolve_idents(&mut self, errs: &mut Vec<ResErr>) -> ResolveRes {
let mut resolve_res = ResolveRes::Finished;
'main: for i in std::mem::take(&mut self.unres_idents) {
let mut j = i;
// take from ref if possible
while let IdentStatus::Ref(other) = &self.idents[j].status {
match &self.idents[other].status {
IdentStatus::Res(res) => self.idents[i].status = IdentStatus::Res(res.clone()),
&IdentStatus::Ref(id) => j = id,
IdentStatus::Unres { .. } => {
self.unres_idents.push(i);
continue 'main;
}
IdentStatus::Failed(..) => self.idents[i].status = IdentStatus::Cooked,
IdentStatus::Cooked => self.idents[i].status = IdentStatus::Cooked,
}
}
let status = &mut self.idents[i].status;
// TOOD: there are some clones here that shouldn't be needed
let IdentStatus::Unres { path, base } = status else {
continue;
};
while let Some(mem) = path.pop() {
let res = match base {
ResBase::Unvalidated(u) => {
match u.validate(
&self.fns,
&self.structs,
&self.generics,
&mut self.types,
errs,
) {
Ok(res) => res,
Err(err) => {
*status = IdentStatus::Failed(err);
continue 'main;
}
}
}
ResBase::Validated(res) => res.clone(),
};
*base = match (res, mem.ty) {
(Res::Module(id), MemberTy::Member) => {
let Some(m) = self.modules[id].members.get(&mem.name) else {
self.unres_idents.push(i);
continue 'main;
};
ResBase::Unvalidated(MemRes {
mem: m.clone(),
origin: mem.origin,
gargs: mem.gargs,
})
}
(Res::Var(id), MemberTy::Field) => {
// trait resolution here
let Some(&child) = self.vars[id].children.get(&mem.name) else {
self.unres_idents.push(i);
continue 'main;
};
ResBase::Unvalidated(MemRes {
mem: Member {
id: MemberID::Var(child),
},
origin: mem.origin,
gargs: mem.gargs,
})
}
_ => {
*status = IdentStatus::Failed(Some(ResErr::UnknownMember {
origin: mem.origin,
ty: mem.ty,
name: mem.name.clone(),
parent: base.clone(),
}));
continue 'main;
}
};
}
let res = match base {
ResBase::Unvalidated(u) => {
match u.validate(
&self.fns,
&self.structs,
&self.generics,
&mut self.types,
errs,
) {
Ok(res) => res,
Err(err) => {
*status = IdentStatus::Failed(err);
continue 'main;
}
}
}
ResBase::Validated(res) => res.clone(),
};
*status = IdentStatus::Res(res);
resolve_res = ResolveRes::Unfinished;
}
resolve_res
}
}
impl MemRes {
pub fn validate(
&self,
@@ -66,89 +171,6 @@ impl MemRes {
}
}
impl IdentID {
pub fn resolve(
self,
s: &mut Sources,
types: &mut Vec<Type>,
changed: &mut bool,
errs: &mut Vec<ResErr>,
) -> Result<Res, ResolveRes> {
let status = &mut s.idents[self].status;
// TOOD: there are some clones here that shouldn't be needed
Ok(match status {
IdentStatus::Res(r) => r.clone(),
IdentStatus::Unres { path, base } => {
while let Some(mem) = path.pop() {
let res = match base {
ResBase::Unvalidated(u) => {
match u.validate(s.fns, s.structs, s.generics, types, errs) {
Ok(res) => res,
Err(err) => {
*status = IdentStatus::Failed(err);
return Err(ResolveRes::Finished);
}
}
}
ResBase::Validated(res) => res.clone(),
};
*base = match (res, mem.ty) {
(Res::Module(id), MemberTy::Member) => {
let Some(m) = s.modules[id].members.get(&mem.name) else {
return Err(ResolveRes::Unfinished);
};
ResBase::Unvalidated(MemRes {
mem: m.clone(),
origin: mem.origin,
gargs: mem.gargs,
})
}
(Res::Var(id), MemberTy::Field) => {
// trait resolution here
let Some(&child) = s.vars[id].children.get(&mem.name) else {
return Err(ResolveRes::Unfinished);
};
ResBase::Unvalidated(MemRes {
mem: Member {
id: MemberID::Var(child),
},
origin: mem.origin,
gargs: mem.gargs,
})
}
_ => {
*status = IdentStatus::Failed(Some(ResErr::UnknownMember {
origin: mem.origin,
ty: mem.ty,
name: mem.name.clone(),
parent: base.clone(),
}));
return Err(ResolveRes::Finished);
}
};
}
let res = match base {
ResBase::Unvalidated(u) => {
match u.validate(s.fns, s.structs, s.generics, types, errs) {
Ok(res) => res,
Err(err) => {
*status = IdentStatus::Failed(err);
return Err(ResolveRes::Finished);
}
}
}
ResBase::Validated(res) => res.clone(),
};
*status = IdentStatus::Res(res.clone());
*changed = true;
res
}
IdentStatus::Cooked => return Err(ResolveRes::Finished),
IdentStatus::Failed(_) => return Err(ResolveRes::Finished),
})
}
}
pub fn validate_gargs(
dst: &[GenericID],
src: &[TypeID],
@@ -171,4 +193,3 @@ pub fn validate_gargs(
}
Ok(())
}
+19 -62
View File
@@ -10,13 +10,13 @@ pub fn inst_fn_var(
types: &mut Vec<Type>,
) -> VarID {
let name = fns[fi.id].name.clone();
let ty = push_id(types, RType::FnRef(fi).ty());
let ty = push_id(types, Type::FnInst(fi));
push_id(
vars,
UVar {
name,
origin,
ty,
ty: VarTy::Res(ty),
parent: None,
children: HashMap::new(),
},
@@ -31,53 +31,20 @@ pub fn inst_struct_var(
types: &mut Vec<Type>,
) -> VarID {
let name = structs[si.id].name.clone();
let ty = push_id(types, RType::Struct(si).ty());
let ty = push_id(types, Type::Struct(si));
let id = push_id(
vars,
UVar {
name,
origin,
ty,
ty: VarTy::Res(ty),
parent: None,
children: HashMap::new(),
},
);
inst_var(vars, structs, id, types);
id
}
pub fn inst_var(vars: &mut Vec<UVar>, structs: &[UStruct], id: VarID, types: &mut Vec<Type>) {
match real_type(types, vars[id].ty) {
RType::Struct(si) => {
let fields = &structs[si.id].fields;
let s_gargs = &structs[si.id].gargs;
let gmap = inst_gmap(s_gargs, &si.gargs);
let children = fields
.iter()
.map(|(name, f)| {
(name.clone(), {
let ty = inst_type(f.ty, types, &gmap);
let fid = push_id(
vars,
UVar {
name: name.clone(),
origin: f.origin,
ty,
parent: Some(id),
children: HashMap::new(),
},
);
inst_var(vars, structs, fid, types);
fid
})
})
.collect();
vars[id].children = children;
}
_ => (),
}
}
/// gargs assumed to be valid
pub fn inst_typedef(def: &TypeDef, gargs: &[TypeID], types: &mut Vec<Type>) -> TypeID {
let gmap = inst_gmap(&def.gargs, &gargs);
@@ -108,32 +75,23 @@ fn inst_type_(
gmap: &HashMap<GenericID, TypeID>,
) -> Option<TypeID> {
let ty = match types[id].clone() {
Type::Real(rty) => match rty {
RType::Bits(_) => return None,
RType::Struct(struct_ty) => RType::Struct(StructInst {
id: struct_ty.id,
gargs: inst_all(&struct_ty.gargs, types, gmap)?,
}),
RType::FnRef(fn_ty) => RType::FnRef(FnInst {
id: fn_ty.id,
gargs: inst_all(&fn_ty.gargs, types, gmap)?,
}),
RType::Ref(id) => RType::Ref(inst_type_(id, types, gmap)?),
RType::Slice(id) => RType::Slice(inst_type_(id, types, gmap)?),
RType::Array(id, len) => RType::Array(inst_type_(id, types, gmap)?, len),
RType::Unit => return None,
RType::Generic(gid) => {
return gmap
.get(&gid)
.map(|id| Some(*id))
.unwrap_or_else(|| None)
}
RType::Infer => RType::Infer,
}
.ty(),
Type::Bits(_) => return None,
Type::Struct(struct_ty) => Type::Struct(StructInst {
id: struct_ty.id,
gargs: inst_all(&struct_ty.gargs, types, gmap)?,
}),
Type::FnInst(fn_ty) => Type::FnInst(FnInst {
id: fn_ty.id,
gargs: inst_all(&fn_ty.gargs, types, gmap)?,
}),
Type::Ref(id) => Type::Ref(inst_type_(id, types, gmap)?),
Type::Slice(id) => Type::Slice(inst_type_(id, types, gmap)?),
Type::Array(id, len) => Type::Array(inst_type_(id, types, gmap)?, len),
Type::Unit => return None,
Type::Generic(gid) => return gmap.get(&gid).map(|id| Some(*id)).unwrap_or_else(|| None),
Type::Infer => Type::Infer,
Type::Deref(id) => Type::Deref(inst_type_(id, types, gmap)?),
Type::Ptr(id) => Type::Ptr(inst_type_(id, types, gmap)?),
Type::Unres(mod_path) => Type::Unres(mod_path.clone()),
Type::Error => return None,
};
Some(push_id(types, ty))
@@ -155,4 +113,3 @@ fn inst_all(
}
vec
}
+64 -20
View File
@@ -2,30 +2,79 @@ use std::collections::HashSet;
use super::*;
pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<()> {
let mut res = ResolveRes::Finished;
match &ctx.i.i {
pub enum UResEvent {
VarUse(VarID),
}
impl UProgram {
pub fn resolve_instrs(&mut self, errs: &mut Vec<ResErr>) -> ResolveRes {
let mut data = ResData {
changed: false,
types: &mut self.types,
s: Sources {
idents: &mut self.idents,
vars: &mut self.vars,
fns: &self.fns,
structs: &self.structs,
generics: &self.generics,
data: &self.data,
modules: &self.modules,
},
errs,
};
for ids in std::mem::take(&mut self.unres_instrs) {
if let ResolveRes::Unfinished = resolve_instr(ids, &mut self.instrs, &mut data) {
self.unres_instrs.push(ids);
};
}
ResolveRes::Finished
}
}
#[derive(Clone, Copy)]
struct ResolveCtx {
ret: IdentID,
breakable: bool,
i: InstrID,
}
pub fn resolve_instr<'a>(
(fi, ii): (FnID, InstrID),
instrs: &mut Vec<UInstrInst>,
data: &mut ResData<'a>,
) -> ResolveRes {
let instr = &mut instrs[ii];
match &mut instr.i {
UInstruction::Call { dst, f, args } => {
let fi = data.res_id::<UFunc>(f, ctx)?;
let f = &data.s.fns[fi.id];
for (src, &dest) in args.iter().zip(&f.args) {
res |= data.match_types::<UVar, UVar>(dest, src, src);
let fi = data.res::<UFunc>(*f);
for &a in args {
data.res::<UVar>(a);
}
res |= data.match_types::<UVar, Type>(dst, f.ret, dst);
data.res::<UVar>(dst);
match fi {
Ok(fi) => {
let f = &data.s.fns[fi.id];
for (&src, &dst) in args.iter().zip(&f.args) {
data.s.constraints.push(UResEvent::AssignVVI { dst, src });
}
}
Err(r) => return r,
}
ResolveRes::Finished
}
UInstruction::Mv { dst, src } => {
res |= data.match_types::<UVar, UVar>(dst, src, src);
}
UInstruction::Ref { dst, src } => {
let dstty = data.res_var_ty(dst, ctx)?.0;
let &RType::Ref(dest_ty) = dstty else {
let dstty = &data.types[data.res_var_ty(dst)?];
let &Type::Ref(dest_ty) = dstty else {
compiler_error()
};
res |= data.match_types::<Type, UVar>(dest_ty, src, src);
}
UInstruction::Deref { dst, src } => {
let (srcty, srcid) = data.res_var_ty(src, ctx)?;
let &RType::Ref(src_ty) = srcty else {
let srcid = data.res_var_ty(src)?;
let &Type::Ref(src_ty) = data.types[srcid] else {
let origin = src.origin(data);
data.errs.push(ResErr::CannotDeref { origin, ty: srcid });
return None;
@@ -38,11 +87,11 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
}
UInstruction::LoadSlice { dst, src } => {
let (dstty, dstid) = data.res_var_ty(dst, ctx)?;
let &RType::Slice(dstty) = dstty else {
let &Type::Slice(dstty) = dstty else {
compiler_error()
};
let srcid = src.type_id(&data.s);
let Type::Real(RType::Array(srcty, _)) = data.types[srcid] else {
let Type::Array(srcty, _) = data.types[srcid] else {
compiler_error()
};
res |= data.match_types(dstty, srcty, dst);
@@ -54,7 +103,7 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
res |= data.match_types::<Type, UVar>(ctx.ret, src, src);
}
UInstruction::Construct { dst, struc, fields } => {
let si = data.res_id::<UStruct>(dst, ctx)?;
let si = data.res::<UStruct>(dst, ctx)?;
let sid = si.id;
let st = &data.s.structs[sid];
let mut used = HashSet::new();
@@ -130,9 +179,4 @@ pub fn resolve_instr<'a>(data: &mut ResData<'a>, ctx: ResolveCtx<'a>) -> Option<
}
}
}
match res {
ResolveRes::Finished => (),
ResolveRes::Unfinished => data.unfinished.push(ctx),
}
return None;
}
+48 -41
View File
@@ -1,31 +1,33 @@
use super::*;
pub fn match_types(data: &mut ResData, dst: impl TypeIDed, src: impl TypeIDed) -> MatchRes {
let dstid = dst.type_id(&data.s);
let srcid = src.type_id(&data.s);
let dstty = data.real_ty(&dst)?.clone();
let srcty = data.real_ty(&src)?.clone();
let error = || {
MatchRes::Error(vec![TypeMismatch {
dst: dstid,
src: srcid,
}])
pub fn match_types(data: &mut ResData, dst: TypeID, src: TypeID) -> MatchRes {
let Some(dst) = clean_type(data.types, dst) else {
return MatchRes::Finished;
};
match (dstty, srcty) {
let Some(src) = clean_type(data.types, src) else {
return MatchRes::Finished;
};
// prevents this from blowing up I think:
// let mut x, y;
// x = y;
// y = x;
if dst == src {
return MatchRes::Finished;
}
let error = || MatchRes::Error(vec![TypeMismatch { dst, src }]);
match (data.types[dst].clone(), data.types[src].clone()) {
// prefer changing dst over src
(RType::Infer, _) => {
(Type::Infer, _) => {
data.changed = true;
data.types[dstid] = Type::Ptr(srcid);
dst.finish(&mut data.s, data.types);
data.types[dst] = Type::Ptr(src);
MatchRes::Finished
}
(_, RType::Infer) => {
(_, Type::Infer) => {
data.changed = true;
data.types[srcid] = Type::Ptr(dstid);
src.finish(&mut data.s, data.types);
data.types[src] = Type::Ptr(dst);
MatchRes::Finished
}
(RType::Struct(dest), RType::Struct(src)) => {
(Type::Struct(dest), Type::Struct(src)) => {
if dest.id != src.id {
return error();
}
@@ -45,9 +47,9 @@ pub fn match_types(data: &mut ResData, dst: impl TypeIDed, src: impl TypeIDed) -
// let src = src_args.into_iter().chain(once(src_ret));
// match_all(data, dst, src)
// }
(RType::Ref(dest), RType::Ref(src)) => match_types(data, dest, src),
(RType::Slice(dest), RType::Slice(src)) => match_types(data, dest, src),
(RType::Array(dest, dlen), RType::Array(src, slen)) => {
(Type::Ref(dest), Type::Ref(src)) => match_types(data, dest, src),
(Type::Slice(dest), Type::Slice(src)) => match_types(data, dest, src),
(Type::Array(dest, dlen), Type::Array(src, slen)) => {
if dlen == slen {
match_types(data, dest, src)
} else {
@@ -84,22 +86,14 @@ fn match_all(
}
impl<'a> ResData<'a> {
pub fn match_types<Dst: ResKind, Src: ResKind>(
pub fn match_types(
&mut self,
dst: impl Resolvable<Dst>,
src: impl Resolvable<Src>,
dst: impl MaybeTypeID,
src: impl MaybeTypeID,
origin: impl HasOrigin,
) -> ResolveRes
where
Dst::Res: TypeIDed,
Src::Res: TypeIDed,
{
let dst = dst
.try_res(&mut self.s, self.types, &mut self.errs, &mut self.changed)?
.type_id(&self.s);
let src = src
.try_res(&mut self.s, self.types, &mut self.errs, &mut self.changed)?
.type_id(&self.s);
) -> ResolveRes {
let dst = dst.type_id(&self.s)?;
let src = src.type_id(&self.s)?;
let res = match_types(self, dst, src);
match res {
MatchRes::Unfinished => ResolveRes::Unfinished,
@@ -115,12 +109,6 @@ impl<'a> ResData<'a> {
}
}
}
pub fn real_ty(&mut self, x: &impl TypeIDed) -> Result<&RType, MatchRes> {
real_type(self.types, x.type_id(&self.s)).map_err(|res| match res {
ResolveRes::Finished => MatchRes::Finished,
ResolveRes::Unfinished => MatchRes::Unfinished,
})
}
}
pub enum MatchRes {
@@ -137,3 +125,22 @@ impl FromResidual<Result<Infallible, MatchRes>> for MatchRes {
}
}
}
pub trait MaybeTypeID {
fn type_id(&self, s: &Sources) -> Result<TypeID, ResolveRes>;
}
impl<T: TypeIDed> MaybeTypeID for T {
fn type_id(&self, s: &Sources) -> Result<TypeID, ResolveRes> {
Ok(self.type_id(s))
}
}
impl MaybeTypeID for VarID {
fn type_id(&self, s: &Sources) -> Result<TypeID, ResolveRes> {
match s.vars[self].ty {
VarTy::Ident(id) => todo!(),
VarTy::Res(id) => Ok(id),
}
}
}
+44 -100
View File
@@ -9,73 +9,40 @@ use std::{
};
mod error;
mod instr;
mod matc;
mod ident;
mod instantiate;
mod instr;
mod matc;
pub use error::*;
use instr::*;
use instantiate::*;
impl UProgram {
pub fn resolve(&mut self, output: &mut CompilerOutput) {
let mut unfinished = Vec::new();
let mut data = ResData {
unfinished: Vec::new(),
changed: false,
types: &mut self.types,
s: Sources {
idents: &mut self.idents,
vars: &mut self.vars,
fns: &self.fns,
structs: &self.structs,
generics: &self.generics,
data: &self.data,
modules: &self.modules,
},
errs: Vec::new(),
};
self.unres_instrs = (0..self.instrs.len()).map(|i| InstrID::from(i)).collect();
let mut res = ResolveRes::Unfinished;
let mut errs = Vec::new();
while res == ResolveRes::Unfinished {
res = ResolveRes::Finished;
res |= self.resolve_idents(&mut errs);
res |= self.resolve_instrs(&mut errs);
}
for (fid, f) in self.fns.iter().enumerate() {
for i in &f.instructions {
resolve_instr(
&mut data,
ResolveCtx {
ret: f.ret,
breakable: false,
i,
},
);
}
// this currently works bc expressions create temporary variables
// although you can't do things like loop {return 3} (need to analyze control flow)
if data.types[f.ret] != RType::Unit.ty()
if let Some(ty) = self.res_ty(f.ret)
&& self.types[ty] != Type::Unit
&& f.instructions
.last()
.is_none_or(|i| !matches!(i.i, UInstruction::Ret { .. }))
.is_none_or(|i| !matches!(self.instrs[i].i, UInstruction::Ret { .. }))
{
data.errs.push(ResErr::NoReturn { fid });
errs.push(ResErr::NoReturn { fid });
}
}
while !data.unfinished.is_empty() && data.changed {
data.changed = false;
std::mem::swap(&mut data.unfinished, &mut unfinished);
for ctx in unfinished.drain(..) {
resolve_instr(&mut data, ctx);
}
}
let errs = data.errs;
report_errs(self, output, errs);
}
}
#[derive(Clone, Copy)]
struct ResolveCtx<'a> {
ret: TypeID,
breakable: bool,
i: &'a UInstrInst,
}
fn compiler_error() -> ! {
// TODO: this is probably a compiler error / should never happen
panic!("how could this happen to me (you)");
@@ -92,46 +59,33 @@ struct Sources<'a> {
}
struct ResData<'a> {
unfinished: Vec<ResolveCtx<'a>>,
changed: bool,
types: &'a mut Vec<Type>,
s: Sources<'a>,
errs: Vec<ResErr>,
errs: &'a mut Vec<ResErr>,
}
impl<'a> ResData<'a> {
pub fn try_res_id<K: ResKind>(&mut self, x: impl Resolvable<K>) -> Result<K::Res, ResolveRes> {
x.try_res(
&mut self.s,
&mut self.types,
&mut self.errs,
&mut self.changed,
)
}
pub fn res_var_ty<'b: 'a>(
&mut self,
x: impl Resolvable<UVar>,
ctx: ResolveCtx<'b>,
) -> Option<(&RType, TypeID)> {
let id = self.res_id::<UVar>(x, ctx).map(|i| i.type_id(&self.s))?;
real_type(self.types, id).ok().map(|ty| (ty, id))
}
pub fn res_id<'b: 'a, K: ResKind>(
&mut self,
x: impl Resolvable<K>,
ctx: ResolveCtx<'b>,
) -> Option<K::Res> {
match self.try_res_id(x) {
Ok(id) => return Some(id),
Err(ResolveRes::Unfinished) => self.unfinished.push(ctx),
Err(ResolveRes::Finished) => (),
}
None
pub fn res<K: ResKind>(&mut self, i: IdentID) -> Result<K::Res, ResolveRes> {
i.res_as::<K>(&mut self.s, &mut self.types)
}
pub fn res_ty(&mut self, x: impl Resolvable<Type>) -> Result<TypeID, ResolveRes> {
let id = Resolvable::<Type>::try_res(&x, &mut self.s, self.types, self.errs)?;
resolved_type(self.types, id)
}
pub fn res_var_ty(&mut self, i: IdentID) -> Result<TypeID, ResolveRes> {
let id = self.res::<UVar>(i)?;
let id = match self.s.vars[id].ty {
VarTy::Res(t) => Ok(t),
VarTy::Ident(i) => i.res_as::<Type>(&mut self.s, self.types),
}?;
resolved_type(self.types, id)
}
}
#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ResolveRes {
Finished,
Unfinished,
@@ -158,28 +112,31 @@ trait Resolvable<K: ResKind> {
s: &mut Sources,
types: &mut Vec<Type>,
errs: &mut Vec<ResErr>,
changed: &mut bool,
) -> Result<K::Res, ResolveRes>;
}
impl<K: ResKind> Resolvable<K> for IdentID {
fn try_res(
impl IdentID {
fn res_as<K: ResKind>(
&self,
s: &mut Sources,
types: &mut Vec<Type>,
errs: &mut Vec<ResErr>,
changed: &mut bool,
) -> Result<K::Res, ResolveRes> {
let origin = s.idents[self].origin;
let res = self.resolve(s, types, changed, errs)?;
let res = match &s.idents[self].status {
IdentStatus::Res(res) => res.clone(),
IdentStatus::Ref { .. } => return Err(ResolveRes::Unfinished),
IdentStatus::Unres { .. } => return Err(ResolveRes::Unfinished),
IdentStatus::Failed(..) => return Err(ResolveRes::Finished),
IdentStatus::Cooked => return Err(ResolveRes::Finished),
};
match K::from_res(res, types, s, origin) {
Ok(res) => Ok(res),
Err(res) => {
errs.push(ResErr::KindMismatch {
s.idents[self].status = IdentStatus::Failed(Some(ResErr::KindMismatch {
origin,
expected: K::ty(),
found: res,
});
}));
Err(ResolveRes::Finished)
}
}
@@ -192,9 +149,8 @@ impl<K: ResKind> Resolvable<K> for &IdentID {
s: &mut Sources,
types: &mut Vec<Type>,
errs: &mut Vec<ResErr>,
changed: &mut bool,
) -> Result<K::Res, ResolveRes> {
Resolvable::<K>::try_res(*self, s, types, errs, changed)
Resolvable::<K>::try_res(*self, s, types, errs)
}
}
@@ -204,7 +160,6 @@ impl Resolvable<UVar> for VarID {
s: &mut Sources,
types: &mut Vec<Type>,
errs: &mut Vec<ResErr>,
changed: &mut bool,
) -> Result<<UVar as ResKind>::Res, ResolveRes> {
Ok(*self)
}
@@ -216,7 +171,6 @@ impl Resolvable<Type> for TypeID {
s: &mut Sources,
types: &mut Vec<Type>,
errs: &mut Vec<ResErr>,
changed: &mut bool,
) -> Result<<Type as ResKind>::Res, ResolveRes> {
Ok(*self)
}
@@ -290,7 +244,7 @@ impl ResKind for Type {
_: Origin,
) -> Result<Self::Res, Res> {
Ok(match res {
Res::Struct(si) => push_id(types, RType::Struct(si).ty()),
Res::Struct(si) => push_id(types, Type::Struct(si)),
Res::Type(id) => id,
_ => return Err(res),
})
@@ -299,7 +253,6 @@ impl ResKind for Type {
pub trait TypeIDed {
fn type_id(&self, s: &Sources) -> TypeID;
fn finish(&self, s: &mut Sources, types: &mut Vec<Type>) {}
}
impl TypeIDed for TypeID {
@@ -308,15 +261,6 @@ impl TypeIDed for TypeID {
}
}
impl TypeIDed for VarID {
fn type_id(&self, s: &Sources) -> TypeID {
s.vars[self].ty
}
fn finish(&self, s: &mut Sources, types: &mut Vec<Type>) {
inst_var(s.vars, s.structs, *self, types);
}
}
impl TypeIDed for DataID {
fn type_id(&self, s: &Sources) -> TypeID {
s.data[self].ty