microsoft/qdk

Public

mirrored from https://github.com/microsoft/qdkAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
billt/revert-mimalloc

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

compiler/qsc_hir/src/global.rs

172lines · modecode

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::{
5 hir::{Item, ItemId, ItemKind, ItemStatus, Package, PackageId, SpecBody, SpecGen, Visibility},
6 ty::Scheme,
7};
8use qsc_data_structures::index_map;
9use rustc_hash::FxHashMap;
10use std::rc::Rc;
11
12pub struct Global {
13 pub namespace: Rc<str>,
14 pub name: Rc<str>,
15 pub visibility: Visibility,
16 pub status: ItemStatus,
17 pub kind: Kind,
18}
19
20pub enum Kind {
21 Namespace,
22 Ty(Ty),
23 Term(Term),
24}
25
26pub struct Ty {
27 pub id: ItemId,
28}
29
30pub struct Term {
31 pub id: ItemId,
32 pub scheme: Scheme,
33 pub intrinsic: bool,
34}
35
36#[derive(Default)]
37pub struct Table {
38 tys: FxHashMap<Rc<str>, FxHashMap<Rc<str>, Ty>>,
39 terms: FxHashMap<Rc<str>, FxHashMap<Rc<str>, Term>>,
40}
41
42impl Table {
43 #[must_use]
44 pub fn resolve_ty(&self, namespace: &str, name: &str) -> Option<&Ty> {
45 self.tys.get(namespace).and_then(|terms| terms.get(name))
46 }
47
48 #[must_use]
49 pub fn resolve_term(&self, namespace: &str, name: &str) -> Option<&Term> {
50 self.terms.get(namespace).and_then(|terms| terms.get(name))
51 }
52}
53
54impl FromIterator<Global> for Table {
55 fn from_iter<T: IntoIterator<Item = Global>>(iter: T) -> Self {
56 let mut tys: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
57 let mut terms: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
58 for global in iter {
59 match global.kind {
60 Kind::Ty(ty) => {
61 tys.entry(global.namespace)
62 .or_default()
63 .insert(global.name, ty);
64 }
65 Kind::Term(term) => {
66 terms
67 .entry(global.namespace)
68 .or_default()
69 .insert(global.name, term);
70 }
71 Kind::Namespace => {}
72 }
73 }
74
75 Self { tys, terms }
76 }
77}
78
79pub struct PackageIter<'a> {
80 id: Option<PackageId>,
81 package: &'a Package,
82 items: index_map::Values<'a, Item>,
83 next: Option<Global>,
84}
85
86impl PackageIter<'_> {
87 fn global_item(&mut self, item: &Item) -> Option<Global> {
88 let parent = item.parent.map(|parent| {
89 &self
90 .package
91 .items
92 .get(parent)
93 .expect("parent should exist")
94 .kind
95 });
96 let id = ItemId {
97 package: self.id,
98 item: item.id,
99 };
100 let status = ItemStatus::from_attrs(item.attrs.as_ref());
101
102 match (&item.kind, &parent) {
103 (ItemKind::Callable(decl), Some(ItemKind::Namespace(namespace, _))) => Some(Global {
104 namespace: Rc::clone(&namespace.name),
105 name: Rc::clone(&decl.name.name),
106 visibility: item.visibility,
107 status,
108 kind: Kind::Term(Term {
109 id,
110 scheme: decl.scheme(),
111 intrinsic: decl.body.body == SpecBody::Gen(SpecGen::Intrinsic),
112 }),
113 }),
114 (ItemKind::Ty(name, def), Some(ItemKind::Namespace(namespace, _))) => {
115 self.next = Some(Global {
116 namespace: Rc::clone(&namespace.name),
117 name: Rc::clone(&name.name),
118 visibility: item.visibility,
119 status,
120 kind: Kind::Term(Term {
121 id,
122 scheme: def.cons_scheme(id),
123 intrinsic: false,
124 }),
125 });
126
127 Some(Global {
128 namespace: Rc::clone(&namespace.name),
129 name: Rc::clone(&name.name),
130 visibility: item.visibility,
131 status,
132 kind: Kind::Ty(Ty { id }),
133 })
134 }
135 (ItemKind::Namespace(ident, _), None) => Some(Global {
136 namespace: "".into(),
137 name: Rc::clone(&ident.name),
138 visibility: Visibility::Public,
139 status,
140 kind: Kind::Namespace,
141 }),
142 _ => None,
143 }
144 }
145}
146
147impl<'a> Iterator for PackageIter<'a> {
148 type Item = Global;
149
150 fn next(&mut self) -> Option<Self::Item> {
151 if let Some(global) = self.next.take() {
152 Some(global)
153 } else {
154 loop {
155 let item = self.items.next()?;
156 if let Some(global) = self.global_item(item) {
157 break Some(global);
158 }
159 }
160 }
161 }
162}
163
164#[must_use]
165pub fn iter_package(id: Option<PackageId>, package: &Package) -> PackageIter {
166 PackageIter {
167 id,
168 package,
169 items: package.items.values(),
170 next: None,
171 }
172}