Skip to content

Commit ce51e67

Browse files
authored
Merge pull request #68 from adrianwn/master
Add code documentation
2 parents 0d81def + c0e02ff commit ce51e67

File tree

8 files changed

+130
-49
lines changed

8 files changed

+130
-49
lines changed

vhdl_lang/src/analysis/lock.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,28 +4,36 @@
44
//
55
// Copyright (c) 2019, Olof Kraigher olof.kraigher@gmail.com
66

7-
///! This module contains structs to handle detecting circular dependencies
8-
///! during analysis of packages where the dependency tree is not known
7+
//! This module contains types to handle the analysis data in a thread-safe way,
8+
//! in particular when the dependencies between design units are not known.
9+
910
use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard, RwLockWriteGuard};
1011

12+
/// Combines an item to be analyzed (typically, a design unit) with the optional results
13+
/// of that analysis.
1114
struct AnalysisState<T, R> {
15+
/// Data gathered during analysis; `None` while not yet analyzed.
1216
result: Option<R>,
17+
18+
/// The subject of analysis; typically, this is a design unit.
1319
data: T,
1420
}
1521

22+
/// A thread-safe r/w-lock on an item to be analyzed (`T`) and the analysis results (`R`).
23+
///
24+
/// Ensures mutable access during analysis and immutable access after analysis.
1625
pub struct AnalysisLock<T, R> {
1726
state: RwLock<AnalysisState<T, R>>,
1827
}
1928

20-
/// Ensure mutable access during analysis and immutable access after analysis
2129
impl<T, R> AnalysisLock<T, R> {
2230
pub fn new(data: T) -> AnalysisLock<T, R> {
2331
AnalysisLock {
2432
state: RwLock::new(AnalysisState { result: None, data }),
2533
}
2634
}
2735

28-
/// Get an immutable reference to the data if it is already been analyzed
36+
/// Returns an immutable reference to the data and result if it has already been analyzed.
2937
fn get(&self) -> Option<ReadGuard<T, R>> {
3038
let guard = self.state.read();
3139
if guard.result.is_some() {
@@ -35,17 +43,20 @@ impl<T, R> AnalysisLock<T, R> {
3543
}
3644
}
3745

46+
/// Returns an immutable reference to the data.
3847
pub fn read(&self) -> MappedRwLockReadGuard<'_, T> {
3948
RwLockReadGuard::map(self.state.read(), |data| &data.data)
4049
}
4150

42-
/// Reset analysis state, analysis needs to be redone
51+
/// Reset analysis state, analysis needs to be redone.
4352
pub fn reset(&self) {
4453
let mut guard = self.state.write();
4554
guard.result = None;
4655
}
4756

48-
/// Get an immmutable reference to the data, assuming it has already been analyzed
57+
/// Returns an immmutable reference to the data and result.
58+
///
59+
/// Panics if the analysis result is not available.
4960
pub fn expect_analyzed(&self) -> ReadGuard<T, R> {
5061
let guard = self.state.read();
5162

@@ -56,10 +67,11 @@ impl<T, R> AnalysisLock<T, R> {
5667
ReadGuard { guard }
5768
}
5869

59-
/// Get either:
60-
/// - A mutable reference to the data if not analyzed
61-
/// - An immmutable reference to the data if already analyzed
62-
/// - A Circular dependency error if such is detected
70+
/// Creates a view into this lock.
71+
///
72+
/// This view provides:
73+
/// - a mutable reference to the data if not analyzed
74+
/// - an immmutable reference to the data if already analyzed
6375
pub fn entry(&self) -> AnalysisEntry<T, R> {
6476
if let Some(guard) = self.get() {
6577
AnalysisEntry::Occupied(guard)
@@ -80,6 +92,12 @@ impl<T, R> AnalysisLock<T, R> {
8092
}
8193
}
8294

95+
/// A view into a thread-safe r/w-lock on an [`AnalysisState`](struct.AnalysisState.html).
96+
///
97+
/// Instances of this type are created by
98+
/// [`AnalysisLock::entry()`](struct.AnalysisLock.html#method.entry)
99+
/// and allow read-access to a completed analysis data and
100+
/// read/write-access to incomplete analysis data.
83101
pub enum AnalysisEntry<'a, T, R> {
84102
Occupied(ReadGuard<'a, T, R>),
85103
Vacant(WriteGuard<'a, T, R>),

vhdl_lang/src/analysis/named_entity.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -286,14 +286,17 @@ pub struct EntityId {
286286
id: usize,
287287
}
288288

289+
/// A named entity as defined in LRM 6.1.
290+
///
291+
/// Every declaration creates one or more named entities.
289292
#[derive(Debug)]
290293
pub struct NamedEntity {
291-
/// An unique id of the entity
292-
/// Entities with the same id will be the same
294+
/// A unique id of the entity.
295+
/// Entities with the same id will be the same.
293296
id: EntityId,
294297
implicit: bool,
295-
/// The location where the declaration was made
296-
/// Builtin and implicit declaration will not have a source position
298+
/// The location where the declaration was made.
299+
/// Builtin and implicit declaration will not have a source position.
297300
designator: Designator,
298301
kind: NamedEntityKind,
299302
decl_pos: Option<SrcPos>,

vhdl_lang/src/analysis/root.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ pub(super) struct AnalysisData {
2929
}
3030

3131
pub(super) type UnitReadGuard<'a> = ReadGuard<'a, AnyDesignUnit, AnalysisData>;
32+
33+
/// Wraps the AST of a [design unit](../../ast/enum.AnyDesignUnit.html) in a thread-safe
34+
/// r/w-lock for analysis.
3235
pub(super) struct LockedUnit {
3336
ident: Ident,
3437
unit_id: UnitId,
@@ -69,22 +72,25 @@ impl HasIdent for LockedUnit {
6972
}
7073
}
7174

75+
/// Represents a VHDL library containing zero or more design units.
76+
///
77+
/// This struct also keeps track of which source file contained which design units.
7278
struct Library {
7379
name: Symbol,
7480

75-
/// Named entity corresponding to the library
81+
/// Named entity corresponding to the library.
7682
ent: Arc<NamedEntity>,
7783

7884
units: FnvHashMap<UnitKey, LockedUnit>,
7985
units_by_source: FnvHashMap<Source, FnvHashSet<UnitId>>,
8086

81-
/// Units removed since last analysis
87+
/// Units removed since last analysis.
8288
removed: FnvHashSet<UnitId>,
83-
/// Units added since last analysis
89+
/// Units added since last analysis.
8490
added: FnvHashSet<UnitId>,
8591

86-
/// Design units which were not added since they were duplicates
87-
/// They need to be kept for later refresh which might make them not duplicates
92+
/// Design units which were not added since they were duplicates.
93+
/// They need to be kept for later refresh which might make them not duplicates.
8894
duplicates: Vec<(SrcPos, LockedUnit)>,
8995
}
9096

@@ -140,7 +146,7 @@ impl<'a> Library {
140146
}
141147
}
142148

143-
/// Refresh library after removing or adding new design units
149+
/// Refresh library after removing or adding new design units.
144150
fn refresh(&mut self, diagnostics: &mut dyn DiagnosticHandler) {
145151
self.append_duplicate_diagnostics(diagnostics);
146152
}
@@ -178,8 +184,8 @@ impl<'a> Library {
178184
}
179185
}
180186

181-
/// Remove all design units defined in source
182-
/// This is used for incremental analysis where only a single source file is updated
187+
/// Remove all design units defined in source.
188+
/// This is used for incremental analysis where only a single source file is updated.
183189
fn remove_source(&mut self, source: &Source) {
184190
let removed = &mut self.removed;
185191
self.units.retain(|_, value| {
@@ -207,8 +213,8 @@ impl<'a> Library {
207213
}
208214
}
209215

210-
/// Iterate over units in the order they appear in the file
211-
/// Ensures diagnostics does not have to be sorted later
216+
/// Iterate over units in the order they appear in the file.
217+
/// Ensures diagnostics do not have to be sorted later.
212218
fn sorted_unit_ids(&self) -> Vec<UnitId> {
213219
// @TODO insert sort when adding instead
214220
let mut result = Vec::new();
@@ -230,18 +236,23 @@ impl<'a> Library {
230236
}
231237
}
232238

239+
/// Contains the entire design state.
240+
///
241+
/// Besides all loaded libraries and design units, `DesignRoot` also keeps track of
242+
/// dependencies between design units.
233243
pub struct DesignRoot {
234244
symbols: Arc<Symbols>,
235245
libraries: FnvHashMap<Symbol, Library>,
236246

237-
// Dependency tracking for incremental analysis
238-
// user => set(users)
247+
// Dependency tracking for incremental analysis.
248+
// user => set(users)
239249
users_of: RwLock<FnvHashMap<UnitId, FnvHashSet<UnitId>>>,
240250

241-
// missing primary name => set(affected)
251+
// missing primary name => set(affected)
242252
missing_primary: RwLock<FnvHashMap<(Symbol, Symbol), FnvHashSet<UnitId>>>,
243253

244-
// library name => set(affected)
254+
// Tracks which units have a "use library.all;" clause.
255+
// library name => set(affected)
245256
users_of_library_all: RwLock<FnvHashMap<Symbol, FnvHashSet<UnitId>>>,
246257
}
247258

@@ -466,7 +477,8 @@ impl DesignRoot {
466477
}
467478
}
468479

469-
/// Reset all unit that need to be re-analyzed
480+
/// Resets the analysis state of all design units which need to be re-analyzed
481+
/// because another design unit has been added or removed.
470482
fn reset(&mut self) {
471483
let mut removed = FnvHashSet::default();
472484
let mut added = FnvHashSet::default();

vhdl_lang/src/ast.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ pub enum Expression {
249249
New(Box<WithPos<Allocator>>),
250250
}
251251

252+
/// An identifier together with the lexical source location it occurs in.
252253
pub type Ident = WithPos<Symbol>;
253254

254255
#[derive(PartialEq, Debug, Clone, Copy)]

vhdl_lang/src/ast/any_design_unit.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,18 @@ pub enum AnyKind {
2727
Secondary(SecondaryKind),
2828
}
2929

30-
/// Without Kind to get name conflict between different primary units
30+
/// Stores a design unit's name and, for secondary units,
31+
/// the name of its associated primary unit.
3132
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
3233
pub enum UnitKey {
3334
Primary(Symbol),
3435
Secondary(Symbol, Symbol),
3536
}
3637

38+
/// Identifies a design unit.
39+
///
40+
/// Additionally, a `UnitId` specifies a unit's name, kind, library,
41+
/// and, for secondary units, its associated primary unit.
3742
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
3843
pub struct UnitId {
3944
library_name: Symbol,
@@ -71,6 +76,8 @@ impl UnitId {
7176
&self.library_name
7277
}
7378

79+
/// For a secondary unit, returns the name of the associated primary unit;
80+
/// for a primary unit, returns its own name.
7481
pub fn primary_name(&self) -> &Symbol {
7582
match self.key {
7683
UnitKey::Primary(ref name) => name,

vhdl_lang/src/data/source.rs

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ use std::sync::Arc;
2020

2121
struct FileId {
2222
name: PathBuf,
23-
hash: u64, // Hash of name
23+
/// Hash value of `self.name`.
24+
hash: u64,
2425
}
2526

2627
impl FileId {
@@ -50,13 +51,14 @@ fn hash(value: &Path) -> u64 {
5051
hasher.finish()
5152
}
5253

54+
/// Represents a single source file and its contents.
5355
struct UniqueSource {
5456
file_id: FileId,
5557
contents: RwLock<Contents>,
5658
}
5759

5860
impl fmt::Debug for UniqueSource {
59-
/// Custom implementation to avoid large contents strings
61+
/// Custom implementation to avoid large contents strings.
6062
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
6163
write!(f, "Source {{file_name: {:?}}}", self.file_name())
6264
}
@@ -96,6 +98,8 @@ impl UniqueSource {
9698
}
9799
}
98100

101+
/// A thread-safe reference to a source file.
102+
/// Multiple objects of this type can refer to the same source.
99103
#[derive(Debug, Clone)]
100104
pub struct Source {
101105
source: Arc<UniqueSource>,
@@ -116,6 +120,10 @@ impl Hash for Source {
116120
}
117121

118122
impl Source {
123+
/// Creates a source from a (virtual) name and in-memory contents.
124+
///
125+
/// Note: For differing values of `contents`, the value of `file_name`
126+
/// *must* differ as well.
119127
pub fn inline(file_name: &Path, contents: &str) -> Source {
120128
Source {
121129
source: Arc::new(UniqueSource::inline(file_name, contents)),
@@ -160,9 +168,12 @@ impl Source {
160168
}
161169
}
162170

171+
/// A lexical position (line, column) in a source.
163172
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
164173
pub struct Position {
174+
/// Line (zero-based).
165175
pub line: u32,
176+
/// Column (zero-based).
166177
pub character: u32,
167178
}
168179

@@ -211,9 +222,12 @@ impl Position {
211222
}
212223
}
213224

225+
/// A lexical range in a source.
214226
#[derive(PartialEq, Eq, Clone, Copy, Hash, Debug)]
215227
pub struct Range {
228+
/// Start of the range (inclusive).
216229
pub start: Position,
230+
/// End of the range (exclusive).
217231
pub end: Position,
218232
}
219233

@@ -223,14 +237,15 @@ impl Range {
223237
}
224238
}
225239

226-
/// Lexical position in a file.
240+
/// A lexical range within a specific source file.
227241
#[derive(PartialEq, Clone, Debug, Eq, Hash)]
228242
pub struct SrcPos {
229-
/// The source
243+
/// The referenced source file.
230244
pub source: Source,
231245
range: Range,
232246
}
233247

248+
/// A generic object with an associated source file and lexical range.
234249
#[derive(PartialEq, Clone, Debug)]
235250
pub struct WithPos<T> {
236251
pub item: T,
@@ -261,6 +276,7 @@ impl<T> WithPos<T> {
261276
pos: self.pos,
262277
}
263278
}
279+
264280
pub fn try_map_into<F, U>(self, f: F) -> DiagnosticResult<WithPos<U>>
265281
where
266282
F: FnOnce(T) -> Result<U, String>,
@@ -422,7 +438,7 @@ impl SrcPos {
422438
(lineno_len, result)
423439
}
424440

425-
/// Create a string for pretty printing
441+
/// Create a string for pretty printing.
426442
pub fn code_context(&self) -> String {
427443
self.lineno_len_and_code_context().1
428444
}
@@ -457,8 +473,8 @@ impl SrcPos {
457473
result
458474
}
459475

460-
/// Combines two lexical positions into a larger legical position overlapping both
461-
/// The file name is assumed to be the same
476+
/// Combines two lexical positions into a larger lexical position overlapping both.
477+
/// The file name is assumed to be the same.
462478
pub fn combine_into(self, other: &dyn AsRef<Self>) -> Self {
463479
let other = other.as_ref();
464480
debug_assert!(self.source == other.source, "Assumes sources are equal");
@@ -493,6 +509,10 @@ impl SrcPos {
493509
}
494510
}
495511

512+
/// Denotes an item with an associated source file.
513+
///
514+
/// Most types that implement this trait do so through the blanket implementation
515+
/// on [`HasSrcPos`](trait.HasSrcPos.html).
496516
pub trait HasSource {
497517
fn source(&self) -> &Source;
498518
}
@@ -503,6 +523,7 @@ impl HasSource for Source {
503523
}
504524
}
505525

526+
/// Denotes an item with an associated lexical range in a source file.
506527
pub trait HasSrcPos {
507528
fn pos(&self) -> &SrcPos;
508529
}

0 commit comments

Comments
 (0)