Skip to content

Commit

Permalink
Move ItemStatus into resolver Res instead of ItemId
Browse files Browse the repository at this point in the history
  • Loading branch information
swernli committed Nov 9, 2023
1 parent ad41766 commit 97062fd
Show file tree
Hide file tree
Showing 15 changed files with 71 additions and 66 deletions.
5 changes: 2 additions & 3 deletions compiler/qsc_frontend/src/compile/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ use qsc_data_structures::span::Span;
use qsc_hir::{
global,
hir::{
Block, Expr, ExprKind, ItemId, ItemKind, ItemStatus, Lit, LocalItemId, NodeId, Res,
SpecBody, Stmt, StmtKind,
Block, Expr, ExprKind, ItemId, ItemKind, Lit, LocalItemId, NodeId, Res, SpecBody, Stmt,
StmtKind,
},
mut_visit::MutVisitor,
ty::{Prim, Ty},
Expand Down Expand Up @@ -268,7 +268,6 @@ fn entry_call_operation() {
&Res::Item(ItemId {
package: None,
item: LocalItemId::from(1),
status: ItemStatus::Normal,
}),
res
);
Expand Down
6 changes: 3 additions & 3 deletions compiler/qsc_frontend/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl With<'_> {
}

pub(super) fn lower_namespace(&mut self, namespace: &ast::Namespace) {
let Some(&resolve::Res::Item(hir::ItemId { item: id, .. })) =
let Some(&resolve::Res::Item(hir::ItemId { item: id, .. }, _)) =
self.names.get(namespace.name.id)
else {
panic!("namespace should have item ID");
Expand Down Expand Up @@ -167,7 +167,7 @@ impl With<'_> {
};

let resolve_id = |id| match self.names.get(id) {
Some(&resolve::Res::Item(item)) => item,
Some(&resolve::Res::Item(item, _)) => item,
_ => panic!("item should have item ID"),
};

Expand Down Expand Up @@ -714,7 +714,7 @@ impl With<'_> {

fn lower_path(&mut self, path: &ast::Path) -> hir::Res {
match self.names.get(path.id) {
Some(&resolve::Res::Item(item)) => hir::Res::Item(item),
Some(&resolve::Res::Item(item, _)) => hir::Res::Item(item),
Some(&resolve::Res::Local(node)) => hir::Res::Local(self.lower_id(node)),
Some(resolve::Res::PrimTy(_) | resolve::Res::UnitTy | resolve::Res::Param(_))
| None => hir::Res::Err,
Expand Down
52 changes: 29 additions & 23 deletions compiler/qsc_frontend/src/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ pub(super) type Names = IndexMap<NodeId, Res>;
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum Res {
/// A global item.
Item(ItemId),
Item(ItemId, ItemStatus),
/// A local variable.
Local(NodeId),
/// A type/functor parameter in the generics section of the parent callable decl.
Expand Down Expand Up @@ -244,11 +244,8 @@ impl Resolver {
}

fn check_item_status(&mut self, res: Res, name: String, span: Span) {
match res {
Res::Item(item) if item.status == ItemStatus::Unimplemented => {
self.errors.push(Error::Unimplemented(name, span));
}
_ => {}
if let Res::Item(_, ItemStatus::Unimplemented) = res {
self.errors.push(Error::Unimplemented(name, span));
}
}

Expand Down Expand Up @@ -334,13 +331,25 @@ impl Resolver {
ast::ItemKind::Open(name, alias) => self.bind_open(name, alias),
ast::ItemKind::Callable(decl) => {
let id = intrapackage(assigner.next_item());
self.names.insert(decl.name.id, Res::Item(id));
self.names.insert(
decl.name.id,
Res::Item(
id,
ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(&item.attrs)),
),
);
let scope = self.scopes.last_mut().expect("binding should have scope");
scope.terms.insert(Rc::clone(&decl.name.name), id);
}
ast::ItemKind::Ty(name, _) => {
let id = intrapackage(assigner.next_item());
self.names.insert(name.id, Res::Item(id));
self.names.insert(
name.id,
Res::Item(
id,
ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(&item.attrs)),
),
);
let scope = self.scopes.last_mut().expect("binding should have scope");
scope.tys.insert(Rc::clone(&name.name), id);
scope.terms.insert(Rc::clone(&name.name), id);
Expand Down Expand Up @@ -595,14 +604,14 @@ impl GlobalTable {
.tys
.entry(global.namespace)
.or_default()
.insert(global.name, Res::Item(ty.id));
.insert(global.name, Res::Item(ty.id, global.status));
}
global::Kind::Term(term) => {
self.scope
.terms
.entry(global.namespace)
.or_default()
.insert(global.name, Res::Item(term.id));
.insert(global.name, Res::Item(term.id, global.status));
}
global::Kind::Namespace => {
self.scope.namespaces.insert(global.name);
Expand All @@ -621,7 +630,7 @@ fn bind_global_items(
) {
names.insert(
namespace.name.id,
Res::Item(intrapackage(assigner.next_item())),
Res::Item(intrapackage(assigner.next_item()), ItemStatus::Normal),
);
scope.namespaces.insert(Rc::clone(&namespace.name.name));

Expand Down Expand Up @@ -686,9 +695,9 @@ fn bind_global_item(
) -> Result<(), Error> {
match &*item.kind {
ast::ItemKind::Callable(decl) => {
let mut item_id = next_id();
item_id.status = ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(item.attrs.as_ref()));
let res = Res::Item(item_id);
let item_id = next_id();
let status = ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(item.attrs.as_ref()));
let res = Res::Item(item_id, status);
names.insert(decl.name.id, res);
match scope
.terms
Expand All @@ -708,9 +717,9 @@ fn bind_global_item(
}
}
ast::ItemKind::Ty(name, _) => {
let mut item_id = next_id();
item_id.status = ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(item.attrs.as_ref()));
let res = Res::Item(item_id);
let item_id = next_id();
let status = ItemStatus::from_attrs(&ast_attrs_as_hir_attrs(item.attrs.as_ref()));
let res = Res::Item(item_id, status);
names.insert(name.id, res);
match (
scope
Expand Down Expand Up @@ -813,10 +822,8 @@ fn resolve(
// same name are both in scope without forcing the user to fully qualify the name.
let mut removals = Vec::new();
for res in candidates.keys() {
if let Res::Item(item) = res {
if item.status == ItemStatus::Unimplemented {
removals.push(*res);
}
if let Res::Item(_, ItemStatus::Unimplemented) = res {
removals.push(*res);
}
}
for res in removals {
Expand Down Expand Up @@ -872,7 +879,7 @@ fn resolve_scope_locals(
}

if let Some(&id) = scope.item(kind, name) {
return Some(Res::Item(id));
return Some(Res::Item(id, ItemStatus::Normal));
}

if let ScopeKind::Namespace(namespace) = &scope.kind {
Expand Down Expand Up @@ -920,7 +927,6 @@ fn intrapackage(item: LocalItemId) -> ItemId {
ItemId {
package: None,
item,
status: ItemStatus::Normal,
}
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/qsc_frontend/src/resolve/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ impl<'a> Renamer<'a> {
fn rename(&self, input: &mut String) {
for (span, res) in self.changes.iter().rev() {
let name = match res {
Res::Item(item) => match item.package {
Res::Item(item, _) => match item.package {
None => format!("item{}", item.item),
Some(package) => format!("package{package}_item{}", item.item),
},
Expand Down
7 changes: 3 additions & 4 deletions compiler/qsc_frontend/src/typeck/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use qsc_ast::{
};
use qsc_data_structures::index_map::IndexMap;
use qsc_hir::{
hir::{self, ItemId, ItemStatus, PackageId},
hir::{self, ItemId, PackageId},
ty::{FunctorSetValue, Scheme, Ty, Udt},
};
use rustc_hash::FxHashMap;
Expand All @@ -42,7 +42,6 @@ impl GlobalTable {
let item_id = ItemId {
package: Some(id),
item: item.id,
status: ItemStatus::from_attrs(&item.attrs),
};

match &item.kind {
Expand Down Expand Up @@ -203,7 +202,7 @@ impl Visitor<'_> for ItemCollector<'_> {
fn visit_item(&mut self, item: &ast::Item) {
match &*item.kind {
ast::ItemKind::Callable(decl) => {
let Some(&Res::Item(item)) = self.names.get(decl.name.id) else {
let Some(&Res::Item(item, _)) = self.names.get(decl.name.id) else {
panic!("callable should have item ID");
};

Expand All @@ -218,7 +217,7 @@ impl Visitor<'_> for ItemCollector<'_> {
}
ast::ItemKind::Ty(name, def) => {
let span = item.span;
let Some(&Res::Item(item)) = self.names.get(name.id) else {
let Some(&Res::Item(item, _)) = self.names.get(name.id) else {
panic!("type should have item ID");
};

Expand Down
2 changes: 1 addition & 1 deletion compiler/qsc_frontend/src/typeck/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ pub(crate) fn ty_from_ast(names: &Names, ty: &ast::Ty) -> (Ty, Vec<MissingTyErro
TyKind::Paren(inner) => ty_from_ast(names, inner),
TyKind::Path(path) => {
let ty = match names.get(path.id) {
Some(&resolve::Res::Item(item)) => Ty::Udt(hir::Res::Item(item)),
Some(&resolve::Res::Item(item, _)) => Ty::Udt(hir::Res::Item(item)),
Some(&resolve::Res::PrimTy(prim)) => Ty::Prim(prim),
Some(resolve::Res::UnitTy) => Ty::Tuple(Vec::new()),
// a path should never resolve to a parameter,
Expand Down
4 changes: 2 additions & 2 deletions compiler/qsc_frontend/src/typeck/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ impl<'a> Context<'a> {
TyKind::Hole => self.inferrer.fresh_ty(TySource::not_divergent(ty.span)),
TyKind::Paren(inner) => self.infer_ty(inner),
TyKind::Path(path) => match self.names.get(path.id) {
Some(&Res::Item(item)) => Ty::Udt(hir::Res::Item(item)),
Some(&Res::Item(item, _)) => Ty::Udt(hir::Res::Item(item)),
Some(&Res::PrimTy(prim)) => Ty::Prim(prim),
Some(Res::UnitTy) => Ty::Tuple(Vec::new()),
None => Ty::Err,
Expand Down Expand Up @@ -364,7 +364,7 @@ impl<'a> Context<'a> {
ExprKind::Paren(expr) => self.infer_expr(expr),
ExprKind::Path(path) => match self.names.get(path.id) {
None => converge(Ty::Err),
Some(Res::Item(item)) => {
Some(Res::Item(item, _)) => {
let scheme = self.globals.get(item).expect("item should have scheme");
let (ty, args) = self.inferrer.instantiate(scheme, expr.span);
self.table.generics.insert(expr.id, args);
Expand Down
30 changes: 15 additions & 15 deletions compiler/qsc_frontend/src/typeck/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1111,7 +1111,7 @@ fn ternop_update_udt_unknown_field_name() {
}
"},
"",
&expect![[r#"
&expect![[r##"
#19 79-81 "()" : Unit
#21 87-155 "{\n let p = Pair(1, 2);\n let q = p w/ Third <- 3;\n }" : Unit
#23 101-102 "p" : UDT<Item 1>
Expand All @@ -1125,8 +1125,8 @@ fn ternop_update_udt_unknown_field_name() {
#36 133-134 "p" : UDT<Item 1>
#39 138-143 "Third" : ?
#42 147-148 "3" : Int
Error(Type(Error(MissingClassHasField(Udt(Item(ItemId { package: None, item: LocalItemId(1), status: Normal })), "Third", Span { lo: 133, hi: 148 }))))
"#]],
Error(Type(Error(MissingClassHasField(Udt(Item(ItemId { package: None, item: LocalItemId(1) })), "Third", Span { lo: 133, hi: 148 }))))
"##]],
);
}

Expand All @@ -1146,7 +1146,7 @@ fn ternop_update_udt_unknown_field_name_known_global() {
}
"},
"",
&expect![[r#"
&expect![[r##"
#19 81-83 "()" : Unit
#21 89-91 "{}" : Unit
#25 109-111 "()" : Unit
Expand All @@ -1162,8 +1162,8 @@ fn ternop_update_udt_unknown_field_name_known_global() {
#42 163-164 "p" : UDT<Item 1>
#45 168-173 "Third" : ?
#48 177-178 "3" : Int
Error(Type(Error(MissingClassHasField(Udt(Item(ItemId { package: None, item: LocalItemId(1), status: Normal })), "Third", Span { lo: 163, hi: 178 }))))
"#]],
Error(Type(Error(MissingClassHasField(Udt(Item(ItemId { package: None, item: LocalItemId(1) })), "Third", Span { lo: 163, hi: 178 }))))
"##]],
);
}

Expand Down Expand Up @@ -2011,15 +2011,15 @@ fn newtype_does_not_match_base_ty() {
}
"},
"",
&expect![[r#"
&expect![[r##"
#12 56-58 "()" : Unit
#16 65-78 "{ NewInt(5) }" : UDT<Item 1>
#18 67-76 "NewInt(5)" : UDT<Item 1>
#19 67-73 "NewInt" : (Int -> UDT<Item 1>)
#22 73-76 "(5)" : Int
#23 74-75 "5" : Int
Error(Type(Error(TyMismatch(Prim(Int), Udt(Item(ItemId { package: None, item: LocalItemId(1), status: Normal })), Span { lo: 67, hi: 76 }))))
"#]],
Error(Type(Error(TyMismatch(Prim(Int), Udt(Item(ItemId { package: None, item: LocalItemId(1) })), Span { lo: 67, hi: 76 }))))
"##]],
);
}

Expand All @@ -2034,15 +2034,15 @@ fn newtype_does_not_match_other_newtype() {
}
"},
"",
&expect![[r#"
&expect![[r##"
#18 84-86 "()" : Unit
#22 97-111 "{ NewInt1(5) }" : UDT<Item 1>
#24 99-109 "NewInt1(5)" : UDT<Item 1>
#25 99-106 "NewInt1" : (Int -> UDT<Item 1>)
#28 106-109 "(5)" : Int
#29 107-108 "5" : Int
Error(Type(Error(TyMismatch(Udt(Item(ItemId { package: None, item: LocalItemId(2), status: Normal })), Udt(Item(ItemId { package: None, item: LocalItemId(1), status: Normal })), Span { lo: 99, hi: 109 }))))
"#]],
Error(Type(Error(TyMismatch(Udt(Item(ItemId { package: None, item: LocalItemId(2) })), Udt(Item(ItemId { package: None, item: LocalItemId(1) })), Span { lo: 99, hi: 109 }))))
"##]],
);
}

Expand Down Expand Up @@ -2104,16 +2104,16 @@ fn newtype_field_invalid() {
}
"},
"",
&expect![[r#"
&expect![[r##"
#13 59-68 "(x : Foo)" : UDT<Item 1>
#14 60-67 "x : Foo" : UDT<Item 1>
#20 74-106 "{\n let y = x::Nope;\n }" : Unit
#22 88-89 "y" : ?1
#24 92-99 "x::Nope" : ?1
#25 92-93 "x" : UDT<Item 1>
Error(Type(Error(MissingClassHasField(Udt(Item(ItemId { package: None, item: LocalItemId(1), status: Normal })), "Nope", Span { lo: 92, hi: 99 }))))
Error(Type(Error(MissingClassHasField(Udt(Item(ItemId { package: None, item: LocalItemId(1) })), "Nope", Span { lo: 92, hi: 99 }))))
Error(Type(Error(AmbiguousTy(Span { lo: 92, hi: 99 }))))
"#]],
"##]],
);
}

Expand Down
7 changes: 6 additions & 1 deletion compiler/qsc_hir/src/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub struct Global {
pub namespace: Rc<str>,
pub name: Rc<str>,
pub visibility: Visibility,
pub status: ItemStatus,
pub kind: Kind,
}

Expand Down Expand Up @@ -94,14 +95,15 @@ impl PackageIter<'_> {
let id = ItemId {
package: self.id,
item: item.id,
status: ItemStatus::from_attrs(item.attrs.as_ref()),
};
let status = ItemStatus::from_attrs(item.attrs.as_ref());

match (&item.kind, &parent) {
(ItemKind::Callable(decl), Some(ItemKind::Namespace(namespace, _))) => Some(Global {
namespace: Rc::clone(&namespace.name),
name: Rc::clone(&decl.name.name),
visibility: item.visibility,
status,
kind: Kind::Term(Term {
id,
scheme: decl.scheme(),
Expand All @@ -112,6 +114,7 @@ impl PackageIter<'_> {
namespace: Rc::clone(&namespace.name),
name: Rc::clone(&name.name),
visibility: item.visibility,
status,
kind: Kind::Term(Term {
id,
scheme: def.cons_scheme(id),
Expand All @@ -122,13 +125,15 @@ impl PackageIter<'_> {
namespace: Rc::clone(&namespace.name),
name: Rc::clone(&name.name),
visibility: item.visibility,
status,
kind: Kind::Ty(Ty { id }),
})
}
(ItemKind::Namespace(ident, _), None) => Some(Global {
namespace: "".into(),
name: Rc::clone(&ident.name),
visibility: Visibility::Public,
status,
kind: Kind::Namespace,
}),
_ => None,
Expand Down
Loading

0 comments on commit 97062fd

Please sign in to comment.