Skip to content

Commit

Permalink
Rework PathStart (#13)
Browse files Browse the repository at this point in the history
Differentiate between `ast::PathStart` for syntax and `LookupStrategy`
for lookup.

Now a path that starts with `::` doesn't mean that it should not look
upwards the tree, but rather that it starts at the root of the tree.
  • Loading branch information
DasLixou authored May 9, 2024
1 parent 97ef7cd commit 16789a9
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 33 deletions.
8 changes: 4 additions & 4 deletions ohdlc/src/ast/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@ use crate::{span::Spanned, symbol::Ident};
#[derive(Debug)]
pub struct Path(pub Vec<PathSegment>, pub PathStart);

// TODO: don't we want this to be (or also be) root? maybe?
#[derive(Debug, Clone, Copy)]
pub enum PathStart {
/// Search directly in the given scope for the next path segment
/// Search in the root scope
/// e.g. `::path::path`
Direct,
Root,
/// Search in the current scope and upwards
/// e.g. `path::path`
Indirect,
Local,
}

#[derive(Debug, Clone, Copy)]
Expand Down
20 changes: 14 additions & 6 deletions ohdlc/src/ir/import_bucket.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use surotto::{simple::SimpleSurotto, simple_assoc::SimpleAssocSurotto, simple_key};

use crate::{ast::PathStart, span::Span, symbol::Ident};
use crate::{span::Span, symbol::Ident};

use super::name_lookup::ScopeId;

Expand Down Expand Up @@ -31,22 +31,30 @@ impl<'ir> ImportBucket<'ir> {

/// ```ohdl,ignore
/// mod scope {
/// // indirect
/// use path::path::path;
/// // direct
/// use ::path::path::path;
/// ^^^^ ~~~~ ~~~~
/// | \direct/
/// indirect
/// }
/// ```
#[derive(Debug)]
pub struct Import<'ir> {
/// The scope we take the path from
pub scope: ScopeId,
/// If the path starts directly or indirectly.
pub start: PathStart,
/// How the lookup of the first segment should be handled.
pub strategy: LookupStrategy,
/// The path we have to take from the source
pub path: &'ir [Ident],
/// The whole import span
pub span: Span,
/// The scope the import will be added to
pub target_scope: ScopeId,
}

#[derive(Debug, Clone, Copy)]
pub enum LookupStrategy {
/// Look only in the given scope.
Direct,
/// Look in the given scope and upwards.
Indirect,
}
20 changes: 11 additions & 9 deletions ohdlc/src/ir/name_lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@ use std::{
use surotto::{simple::SimpleSurotto, simple_key};

use crate::{
ast::PathStart,
ir::modules::ModuleId,
message::Message,
span::Span,
symbol::{Ident, Symbol},
MESSAGES,
};

use super::{import_bucket::ImportId, registry::TypeId};
use super::{
import_bucket::{ImportId, LookupStrategy},
registry::TypeId,
};

simple_key!(
pub struct ScopeId;
Expand Down Expand Up @@ -47,26 +49,26 @@ impl<L> NameLookup<L> {
})
}

pub fn lookup(&self, scope: ScopeId, lookup: &Ident, start: PathStart) -> Option<&L> {
self.lookup_ignore(scope, lookup, start, |_| false)
pub fn lookup(&self, scope: ScopeId, lookup: &Ident, strategy: LookupStrategy) -> Option<&L> {
self.lookup_ignore(scope, lookup, strategy, |_| false)
}

pub fn lookup_ignore<I: Fn(&L) -> bool>(
&self,
scope: ScopeId,
lookup: &Ident,
start: PathStart,
strategy: LookupStrategy,
ignore: I,
) -> Option<&L> {
let mut scope = &self[scope];
loop {
match scope.entries.get(lookup) {
Some(resolvable) if (ignore)(&resolvable.1) => match (scope.parent, start) {
(Some(p), PathStart::Indirect) => scope = &self[p],
Some(resolvable) if (ignore)(&resolvable.1) => match (scope.parent, strategy) {
(Some(p), LookupStrategy::Indirect) => scope = &self[p],
_ => return None,
},
None => match (scope.parent, start) {
(Some(p), PathStart::Indirect) => scope = &self[p],
None => match (scope.parent, strategy) {
(Some(p), LookupStrategy::Indirect) => scope = &self[p],
_ => return None,
},
Some((_, l)) => return Some(l),
Expand Down
9 changes: 4 additions & 5 deletions ohdlc/src/ir/stages/flatten_lookup/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::mem::MaybeUninit;

use crate::{
ast::PathStart,
ir::{
import_bucket::{ImportBucket, ImportId},
import_bucket::{ImportBucket, ImportId, LookupStrategy},
name_lookup::{
LookupScope, PostFlattenNameLookup, PreFlattenNameLookup, Resolvable, Resolved,
},
Expand Down Expand Up @@ -36,7 +35,7 @@ impl<'ir> FlattenLookupStage<'ir, '_, '_> {
.lookup_ignore(
import.scope,
&segment,
import.start,
import.strategy,
|r| matches!(r, Resolvable::Import(i) if *i == id),
)
.cloned()
Expand All @@ -61,7 +60,7 @@ impl<'ir> FlattenLookupStage<'ir, '_, '_> {
let module = &self.registry.modules[m];
let sub_path = &import.path[1..];
import.scope = module.scope;
import.start = PathStart::Direct;
import.strategy = LookupStrategy::Direct;
import.path = sub_path;

continue 'single_import;
Expand Down Expand Up @@ -124,7 +123,7 @@ impl<'ir> FlattenLookupStage<'ir, '_, '_> {
match self.name_lookup.lookup_ignore(
import.scope,
&import.path[0],
import.start,
import.strategy,
|r| matches!(r, Resolvable::Import(i) if *i == id),
) {
Some(Resolvable::Import(dep)) => self.import_bucket.dependants[*dep].push(id),
Expand Down
24 changes: 20 additions & 4 deletions ohdlc/src/ir/stages/refine_types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use bumpalo::Bump;
use crate::{
ast,
ir::{
import_bucket::LookupStrategy,
name_lookup::{PostFlattenNameLookup, Resolved, ScopeId},
registry::{ModuleRegistry, TypeId, TypeRegistry},
},
Expand Down Expand Up @@ -72,21 +73,34 @@ impl<'ir, 'ast> RefineTypesStage<'ir, '_> {
})
}

fn lookup_type(&self, mut scope: ScopeId, ty: &ast::Type) -> Option<TypeId> {
let mut path = ty.path.0 .0.iter().peekable();
fn lookup_type(&self, scope: ScopeId, ty: &ast::Type) -> Option<TypeId> {
let mut lookup_scope = match ty.path.0 .1 {
ast::PathStart::Root => self.name_lookup.root,
ast::PathStart::Local => scope,
};

let mut path = ty.path.0 .0.iter().peekable();
let mut is_start = true;
while let Some(segment) = path.next() {
let is_terminal = path.peek().is_none();
let segment = segment.0;

let lookup = self.name_lookup.lookup(scope, &segment, ty.path.0 .1);
let lookup = self.name_lookup.lookup(
lookup_scope,
&segment,
if is_start {
LookupStrategy::Indirect
} else {
LookupStrategy::Direct
},
);
match (is_terminal, lookup) {
(false, Some(Resolved::Type(_))) => {
MESSAGES.report(Message::use_continues_after_type(segment.1));
return None;
}
(false, Some(Resolved::Module(m))) => {
scope = self.module_registry[*m].scope;
lookup_scope = self.module_registry[*m].scope;
}

(true, Some(Resolved::Type(t))) => return Some(*t),
Expand All @@ -100,6 +114,8 @@ impl<'ir, 'ast> RefineTypesStage<'ir, '_> {
return None;
}
}

is_start = false;
}

return None;
Expand Down
12 changes: 9 additions & 3 deletions ohdlc/src/ir/stages/rough/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use bumpalo::Bump;
use crate::{
ast,
ir::{
import_bucket::{Import, ImportBucket},
import_bucket::{Import, ImportBucket, LookupStrategy},
modules::Module,
name_lookup::{PreFlattenNameLookup, Resolvable, Resolved, ScopeId},
registry::Registry,
Expand Down Expand Up @@ -44,9 +44,15 @@ impl<'ir, 'ast> RoughStage<'ir, '_, 'ast> {

fn lower_use(&mut self, scope: ScopeId, u: &'ast ast::Use) {
let Spanned(path, span) = &u.path;

let import_scope = match path.1 {
ast::PathStart::Root => self.name_lookup.root,
ast::PathStart::Local => scope,
};

let id = self.import_bucket.insert(Import {
scope,
start: path.1,
scope: import_scope,
strategy: LookupStrategy::Indirect,
path: self
.arena
.alloc_slice_fill_iter(path.0.iter().map(|seg| seg.0)),
Expand Down
4 changes: 2 additions & 2 deletions ohdlc/src/parser/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ impl<'s, 'a> Parser<'s, 'a> {

let path_start = if self.kind()? == TokenKind::ColonColon {
self.bump();
PathStart::Direct
PathStart::Root
} else {
PathStart::Indirect
PathStart::Local
};

segments.push(PathSegment(self.ident()?));
Expand Down

0 comments on commit 16789a9

Please sign in to comment.