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

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

View File

@ -252,7 +252,6 @@ pub struct Ty {
pub enum TyKind {
Never,
Empty,
SelfTy,
Path(Path),
Tuple(TyTuple),
Ref(TyRef),
@ -293,6 +292,7 @@ pub struct Path {
pub enum PathPart {
SuperKw,
SelfKw,
SelfTy,
Ident(Sym),
}

View File

@ -306,7 +306,6 @@ mod display {
match self {
TyKind::Never => "!".fmt(f),
TyKind::Empty => "()".fmt(f),
TyKind::SelfTy => "Self".fmt(f),
TyKind::Path(v) => v.fmt(f),
TyKind::Tuple(v) => v.fmt(f),
TyKind::Ref(v) => v.fmt(f),
@ -357,6 +356,7 @@ mod display {
match self {
PathPart::SuperKw => "super".fmt(f),
PathPart::SelfKw => "self".fmt(f),
PathPart::SelfTy => "Self".fmt(f),
PathPart::Ident(id) => id.fmt(f),
}
}

View File

@ -200,6 +200,7 @@ pub trait Fold {
match p {
PathPart::SuperKw => PathPart::SuperKw,
PathPart::SelfKw => PathPart::SelfKw,
PathPart::SelfTy => PathPart::SelfTy,
PathPart::Ident(i) => PathPart::Ident(self.fold_sym(i)),
}
}
@ -498,7 +499,6 @@ pub fn or_fold_ty_kind<F: Fold + ?Sized>(folder: &mut F, kind: TyKind) -> TyKind
match kind {
TyKind::Never => TyKind::Never,
TyKind::Empty => TyKind::Empty,
TyKind::SelfTy => TyKind::SelfTy,
TyKind::Path(p) => TyKind::Path(folder.fold_path(p)),
TyKind::Tuple(t) => TyKind::Tuple(folder.fold_ty_tuple(t)),
TyKind::Ref(t) => TyKind::Ref(folder.fold_ty_ref(t)),

View File

@ -169,6 +169,7 @@ pub trait Visit<'a>: Sized {
match p {
PathPart::SuperKw => {}
PathPart::SelfKw => {}
PathPart::SelfTy => {}
PathPart::Ident(i) => self.visit_sym(i),
}
}
@ -422,7 +423,6 @@ pub fn or_visit_ty_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a TyKind) {
match kind {
TyKind::Never => {}
TyKind::Empty => {}
TyKind::SelfTy => {}
TyKind::Path(p) => visitor.visit_path(p),
TyKind::Tuple(t) => visitor.visit_ty_tuple(t),
TyKind::Ref(t) => visitor.visit_ty_ref(t),

View File

@ -169,6 +169,7 @@ fn evaluate_place_expr<'e>(
match parts.last().expect("parts should not be empty") {
PathPart::SuperKw => Err(Error::NotAssignable),
PathPart::SelfKw => todo!("Assignment to `self`"),
PathPart::SelfTy => todo!("What does it mean to assign to capital-S Self?"),
PathPart::Ident(s) => env.get_mut(*s).map(|v| (v, *s)),
}
}
@ -375,6 +376,7 @@ impl Interpret for Path {
if parts.len() == 1 {
match parts.last().expect("parts should not be empty") {
PathPart::SuperKw | PathPart::SelfKw => todo!("Path navigation"),
PathPart::SelfTy => todo!("Path navigation to Self"),
PathPart::Ident(name) => env.get(*name),
}
} else {

View File

@ -672,10 +672,6 @@ impl<'t> Parser<'t> {
self.consume_peeked();
TyKind::Never
}
TokenKind::SelfTy => {
self.consume_peeked();
TyKind::SelfTy
}
TokenKind::Punct(Punct::Amp) | TokenKind::Punct(Punct::AmpAmp) => self.tyref()?.into(),
TokenKind::Punct(Punct::LParen) => {
let out = self.tytuple()?;
@ -751,6 +747,7 @@ macro literal_like() {
macro path_like() {
TokenKind::Super
| TokenKind::SelfKw
| TokenKind::SelfTy
| TokenKind::Identifier
| TokenKind::Punct(Punct::ColonColon)
}
@ -762,6 +759,7 @@ impl<'t> Parser<'t> {
let out = match self.peek_kind(PARSING)? {
TokenKind::Super => PathPart::SuperKw,
TokenKind::SelfKw => PathPart::SelfKw,
TokenKind::SelfTy => PathPart::SelfTy,
TokenKind::Identifier => PathPart::Ident(self.identifier()?),
t => return Err(self.error(Unexpected(t), PARSING)),
};

View File

@ -610,7 +610,6 @@ pub mod yamlify {
match self {
TyKind::Never => y.value("Never"),
TyKind::Empty => y.value("Empty"),
TyKind::SelfTy => y.value("Self"),
TyKind::Path(t) => y.yaml(t),
TyKind::Tuple(t) => y.yaml(t),
TyKind::Ref(t) => y.yaml(t),
@ -635,6 +634,7 @@ pub mod yamlify {
match self {
PathPart::SuperKw => y.value("super"),
PathPart::SelfKw => y.value("self"),
PathPart::SelfTy => y.value("Self"),
PathPart::Ident(i) => y.yaml(i),
};
}

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),
}
}

View File

@ -62,7 +62,7 @@ TyFn = "fn" TyTuple ('->' Ty)? ;
(* path *)
Path = PathPart ('::' PathPart)*
| '::' (PathPart ('::' PathPart)*)? ;
PathPart = "super" | "self" | Identifier ;
PathPart = "super" | "self" | "Self" | Identifier ;
Identifier = IDENTIFIER ;