Skip to content

Commit

Permalink
Implemented resolving for user-defined types
Browse files Browse the repository at this point in the history
feat: Added a `resolve_namespace()` query
  • Loading branch information
Michael-F-Bryan committed Apr 7, 2024
1 parent 6cff4f5 commit d27595a
Show file tree
Hide file tree
Showing 10 changed files with 379 additions and 80 deletions.
12 changes: 12 additions & 0 deletions crates/wit-compiler/src/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,18 @@ pub enum AnyFuncItemIndex {
StaticMethod(ScopeIndex, ResourceIndex, StaticResourceMethodIndex),
}

impl AnyFuncItemIndex {
/// Get the scope this [`crate::hir::FuncItem`] is defined in.
pub fn scope(self) -> ScopeIndex {
match self {
AnyFuncItemIndex::TopLevel(i, _) => ScopeIndex::Interface(i),
AnyFuncItemIndex::Method(scope, _, _) | AnyFuncItemIndex::StaticMethod(scope, _, _) => {
scope
}
}
}
}

impl GetByIndex<WorldIndex> for Items {
type Metadata = WorldMetadata;

Expand Down
39 changes: 17 additions & 22 deletions crates/wit-compiler/src/ast/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,10 @@ impl<'tree> super::AstNode<'tree> for BlockComment<'tree> {
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct BorrowedHandle<'tree>(tree_sitter::Node<'tree>);
impl<'tree> BorrowedHandle<'tree> {
pub fn name(&self) -> Option<Identifier<'tree>> {
self.0.child_by_field_name("name").and_then(<Identifier as super::AstNode>::cast)
}
}
impl super::HasIdent for BorrowedHandle<'_> {
fn identifier(self, src: &str) -> Option<&str> {
let node = self.name()?.0;
let ident = node.utf8_text(src.as_bytes()).unwrap();
Some(ident)
pub fn user_defined_type(self) -> Option<UserDefinedType<'tree>> {
super::children(self.0)
.filter_map(<UserDefinedType as super::AstNode<'_>>::cast)
.next()
}
}
impl<'tree> super::AstNode<'tree> for BorrowedHandle<'tree> {
Expand Down Expand Up @@ -962,15 +957,10 @@ impl<'tree> super::AstNode<'tree> for Option_<'tree> {
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct OwnedHandle<'tree>(tree_sitter::Node<'tree>);
impl<'tree> OwnedHandle<'tree> {
pub fn name(&self) -> Option<Identifier<'tree>> {
self.0.child_by_field_name("name").and_then(<Identifier as super::AstNode>::cast)
}
}
impl super::HasIdent for OwnedHandle<'_> {
fn identifier(self, src: &str) -> Option<&str> {
let node = self.name()?.0;
let ident = node.utf8_text(src.as_bytes()).unwrap();
Some(ident)
pub fn user_defined_type(self) -> Option<UserDefinedType<'tree>> {
super::children(self.0)
.filter_map(<UserDefinedType as super::AstNode<'_>>::cast)
.next()
}
}
impl<'tree> super::AstNode<'tree> for OwnedHandle<'tree> {
Expand Down Expand Up @@ -1724,10 +1714,15 @@ impl<'tree> super::AstNode<'tree> for UsePath<'tree> {
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct UserDefinedType<'tree>(tree_sitter::Node<'tree>);
impl<'tree> UserDefinedType<'tree> {
pub fn identifier(self) -> Option<Identifier<'tree>> {
super::children(self.0)
.filter_map(<Identifier as super::AstNode<'_>>::cast)
.next()
pub fn name(&self) -> Option<Identifier<'tree>> {
self.0.child_by_field_name("name").and_then(<Identifier as super::AstNode>::cast)
}
}
impl super::HasIdent for UserDefinedType<'_> {
fn identifier(self, src: &str) -> Option<&str> {
let node = self.name()?.0;
let ident = node.utf8_text(src.as_bytes()).unwrap();
Some(ident)
}
}
impl<'tree> super::AstNode<'tree> for UserDefinedType<'tree> {
Expand Down
2 changes: 1 addition & 1 deletion crates/wit-compiler/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ impl Diagnostic {
})
}

pub fn unknown_name(name: Text, filename: Text, range: Range) -> Self {
pub fn unknown_name(filename: FilePath, name: Text, range: Range) -> Self {
Diagnostic::UnknownName(UnknownName {
name,
location: Location::new(filename, range),
Expand Down
68 changes: 66 additions & 2 deletions crates/wit-compiler/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use im::{OrdMap, Vector};

use crate::{
access::{
AnyFuncItemIndex, EnumIndex, FlagsIndex, InterfaceIndex, RecordIndex, ResourceIndex,
TypeAliasIndex, VariantIndex, WorldIndex,
AnyFuncItemIndex, EnumIndex, FlagsIndex, FuncItemIndex, InterfaceIndex, RecordIndex,
ResourceIndex, ScopeIndex, TypeAliasIndex, VariantIndex, WorldIndex,
},
queries::FilePath,
Text,
};

Expand Down Expand Up @@ -156,6 +157,7 @@ pub enum Type {
Builtin(Builtin),
Handle {
borrowed: bool,
ty: Box<Type>,
},
List(Box<Type>),
Option(Box<Type>),
Expand All @@ -164,9 +166,71 @@ pub enum Type {
err: Option<Box<Type>>,
},
Tuple(Vector<Type>),
UserDefinedType(ItemReference),
Error,
}

/// A reference to an item defined elsewhere.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ItemReference {
pub file: FilePath,
pub scope: ScopeIndex,
pub item: ItemReferenceKind,
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum ItemReferenceKind {
Enum(EnumIndex),
Variant(VariantIndex),
Flags(FlagsIndex),
Record(RecordIndex),
Resource(ResourceIndex),
Func(FuncItemIndex),
TypeAlias(TypeAliasIndex),
}

impl From<EnumIndex> for ItemReferenceKind {
fn from(v: EnumIndex) -> Self {
Self::Enum(v)
}
}

impl From<TypeAliasIndex> for ItemReferenceKind {
fn from(v: TypeAliasIndex) -> Self {
Self::TypeAlias(v)
}
}

impl From<FuncItemIndex> for ItemReferenceKind {
fn from(v: FuncItemIndex) -> Self {
Self::Func(v)
}
}

impl From<ResourceIndex> for ItemReferenceKind {
fn from(v: ResourceIndex) -> Self {
Self::Resource(v)
}
}

impl From<RecordIndex> for ItemReferenceKind {
fn from(v: RecordIndex) -> Self {
Self::Record(v)
}
}

impl From<FlagsIndex> for ItemReferenceKind {
fn from(v: FlagsIndex) -> Self {
Self::Flags(v)
}
}

impl From<VariantIndex> for ItemReferenceKind {
fn from(v: VariantIndex) -> Self {
Self::Variant(v)
}
}

impl From<Builtin> for Type {
fn from(value: Builtin) -> Self {
Type::Builtin(value)
Expand Down
4 changes: 3 additions & 1 deletion crates/wit-compiler/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,17 @@ pub struct Jar(
crate::queries::Items,
crate::queries::lower,
crate::queries::lowering::lower_enum,
crate::queries::lowering::lower_flags,
crate::queries::lowering::lower_func_item,
crate::queries::lowering::lower_interface,
crate::queries::lowering::lower_record,
crate::queries::lowering::lower_resource,
crate::queries::lowering::lower_type_alias,
crate::queries::lowering::lower_variant,
crate::queries::lowering::lower_world,
crate::queries::lowering::lower_flags,
crate::queries::parse,
crate::queries::resolve_name,
crate::queries::resolve_namespace,
crate::queries::selection_ranges,
crate::queries::SourceFile,
crate::queries::Workspace,
Expand Down
41 changes: 32 additions & 9 deletions crates/wit-compiler/src/queries/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use crate::{
},
ast::{self, AstNode, HasIdent},
diagnostics::{Diagnostic, Diagnostics, Location},
hir,
queries::SourceFile,
Db, Text,
};
Expand Down Expand Up @@ -45,7 +46,7 @@ pub fn file_items(db: &dyn Db, file: SourceFile) -> Items {
} else if let Some(interface) = top_level_item.interface_item() {
if let Some((name, interface)) = walk_interface(db, interface, src, file) {
if names.insert(name.clone(), node) {
let ix = InterfaceIndex::from_raw(RawIndex::new(worlds.len()));
let ix = InterfaceIndex::from_raw(RawIndex::new(interfaces.len()));
interfaces.push_back(interface);
interfaces_by_name.insert(name, ix);
}
Expand Down Expand Up @@ -475,15 +476,37 @@ impl ItemDefinitionMetadata {
iter(&self.variants)
}

pub fn reference_kinds(&self) -> impl Iterator<Item = (&Text, hir::ItemReferenceKind)> {
let ItemDefinitionMetadata {
enums_by_name,
flags_by_name,
functions_by_name,
records_by_name,
resources_by_name,
typedefs_by_name,
variants_by_name,
..
} = self;

fn m<'a, Ix>((name, ix): (&'a Text, &Ix)) -> (&'a Text, hir::ItemReferenceKind)
where
Ix: Into<hir::ItemReferenceKind> + Clone,
{
(name, ix.clone().into())
}

std::iter::empty()
.chain(enums_by_name.iter().map(m))
.chain(flags_by_name.iter().map(m))
.chain(functions_by_name.iter().map(m))
.chain(records_by_name.iter().map(m))
.chain(resources_by_name.iter().map(m))
.chain(typedefs_by_name.iter().map(m))
.chain(variants_by_name.iter().map(m))
}

pub fn names(&self) -> impl Iterator<Item = &Text> {
self.enums_by_name
.keys()
.chain(self.flags_by_name.keys())
.chain(self.functions_by_name.keys())
.chain(self.records_by_name.keys())
.chain(self.resources_by_name.keys())
.chain(self.typedefs_by_name.keys())
.chain(self.variants_by_name.keys())
self.reference_kinds().map(|(n, _)| n)
}
}

Expand Down
Loading

0 comments on commit d27595a

Please sign in to comment.