Skip to content

Commit

Permalink
Merge a5f54c1 into 8f00e81
Browse files Browse the repository at this point in the history
  • Loading branch information
sezna committed May 21, 2024
2 parents 8f00e81 + a5f54c1 commit de39c3f
Show file tree
Hide file tree
Showing 14 changed files with 1,101 additions and 37 deletions.
4 changes: 2 additions & 2 deletions compiler/qsc/src/interpret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -936,11 +936,11 @@ impl<'a> Visitor<'a> for BreakpointCollector<'a> {
fn visit_stmt(&mut self, stmt: StmtId) {
let stmt_res = self.get_stmt(stmt);
match stmt_res.kind {
qsc_fir::fir::StmtKind::Expr(expr) | qsc_fir::fir::StmtKind::Local(_, _, expr) => {
fir::StmtKind::Expr(expr) | fir::StmtKind::Local(_, _, expr) => {
self.add_stmt(stmt_res);
visit::walk_expr(self, expr);
}
qsc_fir::fir::StmtKind::Item(_) | qsc_fir::fir::StmtKind::Semi(_) => {
fir::StmtKind::Item(_) | fir::StmtKind::Semi(_) => {
self.add_stmt(stmt_res);
}
};
Expand Down
100 changes: 100 additions & 0 deletions compiler/qsc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,16 @@ pub struct Namespace {
pub items: Box<[Box<Item>]>,
}

impl Namespace {
/// Returns an iterator over the items in the namespace that are exported.
pub fn exports(&self) -> impl Iterator<Item = &ExportItem> {
self.items.iter().flat_map(|i| match i.kind.as_ref() {
ItemKind::Export(export) => &export.items[..],
_ => &[],
})
}
}

impl Display for Namespace {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let mut indent = set_indentation(indented(f), 0);
Expand Down Expand Up @@ -262,6 +272,8 @@ pub enum ItemKind {
Open(Idents, Option<Box<Ident>>),
/// A `newtype` declaration.
Ty(Box<Ident>, Box<TyDef>),
/// An export declaration
Export(ExportDecl),
}

impl Display for ItemKind {
Expand All @@ -274,6 +286,7 @@ impl Display for ItemKind {
None => write!(f, "Open ({name})")?,
},
ItemKind::Ty(name, t) => write!(f, "New Type ({name}): {t}")?,
ItemKind::Export(export) => write!(f, "Export ({export})")?,
}
Ok(())
}
Expand Down Expand Up @@ -1684,3 +1697,90 @@ pub enum SetOp {
/// The set intersection.
Intersect,
}

#[derive(Clone, Debug, PartialEq, Eq)]
/// Represents an export declaration.
pub struct ExportDecl {
/// The node ID.
pub id: NodeId,
/// The span.
pub span: Span,
/// The items being exported from this namespace.
pub items: Box<[ExportItem]>,
}

impl Display for ExportDecl {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let items_str = self
.items
.iter()
.map(std::string::ToString::to_string)
.collect::<Vec<_>>()
.join(", ");
write!(f, "ExportDecl {}: [{items_str}]", self.span)
}
}

impl ExportDecl {
/// Returns an iterator over the items being exported from this namespace.
pub fn items(&self) -> impl Iterator<Item = &ExportItem> {
self.items.iter()
}
}

/// An individual item within an [`ExportDecl`]. This can be a path or a path with an alias.
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct ExportItem {
/// The path to the item being exported.
pub path: Path,
/// An optional alias for the item being exported.
pub alias: Option<Ident>,
}

impl Display for ExportItem {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let ExportItem {
ref path,
ref alias,
} = self;
match alias {
Some(alias) => write!(f, "{path} as {alias}"),
None => write!(f, "{path}"),
}
}
}

impl WithSpan for ExportItem {
fn with_span(self, span: Span) -> Self {
ExportItem {
path: self.path.with_span(span),
alias: self.alias.map(|x| x.with_span(span)),
}
}
}

impl ExportItem {
/// Returns the span of the export item. This includes the path and , if any exists, the alias.
#[must_use]
pub fn span(&self) -> Span {
match self.alias {
Some(ref alias) => {
// join the path and alias spans
Span {
lo: self.path.span.lo,
hi: alias.span.hi,
}
}
None => self.path.span,
}
}

/// Returns the alias ident, if any, or the name from the path if no alias is present.
#[must_use]
pub fn name(&self) -> &Ident {
match self.alias {
Some(ref alias) => alias,
None => &self.path.name,
}
}
}
7 changes: 7 additions & 0 deletions compiler/qsc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,13 @@ pub fn walk_item(vis: &mut impl MutVisitor, item: &mut Item) {
vis.visit_ident(ident);
vis.visit_ty_def(def);
}
ItemKind::Export(export) => {
vis.visit_span(&mut export.span);
export
.items
.iter_mut()
.for_each(|i| vis.visit_path(&mut i.path));
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/qsc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ pub fn walk_item<'a>(vis: &mut impl Visitor<'a>, item: &'a Item) {
vis.visit_ident(ident);
vis.visit_ty_def(def);
}
ItemKind::Export(export) => {
export.items.iter().for_each(|i| vis.visit_path(&i.path));
}
}
}

Expand Down
1 change: 1 addition & 0 deletions compiler/qsc_codegen/src/qsharp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ impl<W: Write> Visitor<'_> for QSharpGen<W> {
self.visit_ty_def(def);
self.writeln(";");
}
ItemKind::Export(_) => (),
}
}

Expand Down
6 changes: 6 additions & 0 deletions compiler/qsc_frontend/src/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -514,8 +514,14 @@ fn resolve_all(
dropped_names.extend(unit.dropped_names.iter().cloned());
}

// bind all symbols in `add_local_package`
let mut errors = globals.add_local_package(assigner, package);
let mut resolver = Resolver::new(globals, dropped_names);

// bind all exported symbols in a follow-on step
resolver.resolve_exports(package);

// resolve all symbols
resolver.with(assigner).visit_package(package);
let (names, locals, mut resolver_errors, _namespaces) = resolver.into_result();
errors.append(&mut resolver_errors);
Expand Down
7 changes: 5 additions & 2 deletions compiler/qsc_frontend/src/lower.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl With<'_> {
};

self.lowerer.parent = Some(id);
let items = namespace
let items: Vec<LocalItemId> = namespace
.items
.iter()
.filter_map(|i| self.lower_item(ItemScope::Global, i))
Expand Down Expand Up @@ -171,7 +171,10 @@ impl With<'_> {
};

let (id, kind) = match &*item.kind {
ast::ItemKind::Err | ast::ItemKind::Open(..) => return None,
ast::ItemKind::Err | ast::ItemKind::Open(..) |
// exports are handled in namespace resolution (see resolve.rs) -- we don't need them in any lowered representations

ast::ItemKind::Export(_) => return None,
ast::ItemKind::Callable(callable) => {
let id = resolve_id(callable.name.id);
let grandparent = self.lowerer.parent;
Expand Down
Loading

0 comments on commit de39c3f

Please sign in to comment.