conlang: Self is not a type, it's a path to a type

This commit is contained in:
2024-07-17 15:05:52 -05:00
parent ded100bf71
commit b3d62c09aa
11 changed files with 25 additions and 20 deletions

View File

@@ -105,8 +105,6 @@ pub enum TypeKind {
Empty,
/// The never type
Never,
/// The Self type
SelfTy,
/// An untyped module
Module,
}

View File

@@ -100,7 +100,6 @@ impl Display for TypeKind {
TypeKind::FnSig { args, rety } => write!(f, "fn (#{args}) -> #{rety}"),
TypeKind::Empty => f.write_str("()"),
TypeKind::Never => f.write_str("!"),
TypeKind::SelfTy => f.write_str("Self"),
TypeKind::Module => f.write_str("mod"),
}
}

View File

@@ -49,16 +49,10 @@ impl Default for Project<'_> {
kind: DefKind::Type(TypeKind::Empty),
node: Node::new(ROOT_PATH, None),
});
let selfty = pool.insert(Def {
module: module::Module::new(root),
kind: DefKind::Type(TypeKind::SelfTy),
node: Node::new(ROOT_PATH, None),
});
let mut anon_types = HashMap::new();
anon_types.insert(TypeKind::Empty, empty);
anon_types.insert(TypeKind::Never, never);
anon_types.insert(TypeKind::SelfTy, selfty);
Self { pool, root, anon_types }
}
@@ -68,6 +62,7 @@ impl<'a> Project<'a> {
pub fn parent_of(&self, module: DefID) -> Option<DefID> {
self[module].module.parent
}
pub fn root_of(&self, module: DefID) -> DefID {
match self.parent_of(module) {
Some(module) => self.root_of(module),
@@ -75,6 +70,15 @@ impl<'a> Project<'a> {
}
}
/// Returns the DefID of the Self type within the given DefID's context
pub fn selfty_of(&self, node: DefID) -> Option<DefID> {
match self[node].kind {
DefKind::Impl(id) => Some(id),
DefKind::Type(_) => Some(node),
_ => self.selfty_of(self.parent_of(node)?),
}
}
pub fn get<'p>(
&self,
path: Path<'p>,
@@ -93,6 +97,7 @@ impl<'a> Project<'a> {
let ty = self[within].module.get_type(*name)?;
self.get(path.pop_front()?, ty)
}
[PathPart::SelfTy, ..] => self.get(path.pop_front()?, self.selfty_of(within)?),
[PathPart::SelfKw, ..] => self.get(path.pop_front()?, within),
[PathPart::SuperKw, ..] => self.get(path.pop_front()?, self.parent_of(within)?),
}
@@ -108,6 +113,7 @@ impl<'a> Project<'a> {
match front {
PathPart::SelfKw => self.get_type(path.pop_front()?, within),
PathPart::SuperKw => self.get_type(path.pop_front()?, module.parent?),
PathPart::SelfTy => self.get_type(path.pop_front()?, self.selfty_of(within)?),
PathPart::Ident(name) => match module.types.get(name) {
Some(&submodule) => self.get_type(path.pop_front()?, submodule),
None => Some((within, path)),
@@ -189,7 +195,6 @@ pub mod evaluate {
// TODO: reduce duplication here
TyKind::Never => prj.anon_types[&TypeKind::Never],
TyKind::Empty => prj.anon_types[&TypeKind::Empty],
TyKind::SelfTy => prj.anon_types[&TypeKind::SelfTy],
// TyKind::Path must be looked up explicitly
TyKind::Path(path) => path.evaluate(prj, parent)?,
TyKind::Tuple(tup) => tup.evaluate(prj, parent)?,
@@ -280,6 +285,9 @@ pub mod evaluate {
.parent_of(parent)
.ok_or_else(|| "Attempt to get super of root".into()),
PathPart::SelfKw => Ok(parent),
PathPart::SelfTy => prj
.selfty_of(parent)
.ok_or_else(|| "Attempt to get Self outside a Self-able context".into()),
PathPart::Ident(name) => name.evaluate(prj, parent),
}
}