microsoft/qdk

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v1.25.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

source/compiler/qsc_fir/src/global.rs

164lines · modecode

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