From b3d62c09aa4e424cb7f61b921ab4801bc278498b Mon Sep 17 00:00:00 2001 From: John Date: Wed, 17 Jul 2024 15:05:52 -0500 Subject: [PATCH] conlang: Self is not a type, it's a path to a type --- compiler/cl-ast/src/ast.rs | 2 +- compiler/cl-ast/src/ast_impl.rs | 2 +- compiler/cl-ast/src/ast_visitor/fold.rs | 2 +- compiler/cl-ast/src/ast_visitor/visit.rs | 2 +- compiler/cl-interpret/src/interpret.rs | 2 ++ compiler/cl-parser/src/parser.rs | 6 ++---- compiler/cl-repl/examples/yaml.rs | 2 +- compiler/cl-typeck/src/definition.rs | 2 -- compiler/cl-typeck/src/definition/display.rs | 1 - compiler/cl-typeck/src/project.rs | 22 +++++++++++++------- grammar.ebnf | 2 +- 11 files changed, 25 insertions(+), 20 deletions(-) diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index 93dd971..b9e9fff 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -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), } diff --git a/compiler/cl-ast/src/ast_impl.rs b/compiler/cl-ast/src/ast_impl.rs index cab7b6f..0006f4b 100644 --- a/compiler/cl-ast/src/ast_impl.rs +++ b/compiler/cl-ast/src/ast_impl.rs @@ -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), } } diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index 3ffe982..c2613ee 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -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(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)), diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index eaeb188..0efbc3b 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -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), diff --git a/compiler/cl-interpret/src/interpret.rs b/compiler/cl-interpret/src/interpret.rs index 79650bc..48f3aa9 100644 --- a/compiler/cl-interpret/src/interpret.rs +++ b/compiler/cl-interpret/src/interpret.rs @@ -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 { diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index 6509339..7072667 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -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)), }; diff --git a/compiler/cl-repl/examples/yaml.rs b/compiler/cl-repl/examples/yaml.rs index eb92cdb..af5e5e0 100644 --- a/compiler/cl-repl/examples/yaml.rs +++ b/compiler/cl-repl/examples/yaml.rs @@ -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), }; } diff --git a/compiler/cl-typeck/src/definition.rs b/compiler/cl-typeck/src/definition.rs index 34829d7..cf0696a 100644 --- a/compiler/cl-typeck/src/definition.rs +++ b/compiler/cl-typeck/src/definition.rs @@ -105,8 +105,6 @@ pub enum TypeKind { Empty, /// The never type Never, - /// The Self type - SelfTy, /// An untyped module Module, } diff --git a/compiler/cl-typeck/src/definition/display.rs b/compiler/cl-typeck/src/definition/display.rs index 848074f..923efd6 100644 --- a/compiler/cl-typeck/src/definition/display.rs +++ b/compiler/cl-typeck/src/definition/display.rs @@ -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"), } } diff --git a/compiler/cl-typeck/src/project.rs b/compiler/cl-typeck/src/project.rs index 495e7ac..e55892f 100644 --- a/compiler/cl-typeck/src/project.rs +++ b/compiler/cl-typeck/src/project.rs @@ -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 { 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 { + 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), } } diff --git a/grammar.ebnf b/grammar.ebnf index e186c07..0b02668 100644 --- a/grammar.ebnf +++ b/grammar.ebnf @@ -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 ;