Skip to content

Commit

Permalink
Add even more documentation for enums and traits
Browse files Browse the repository at this point in the history
- Move GlobalObjectKind to private scope
  • Loading branch information
VonTum committed Jan 14, 2025
1 parent 65e503b commit 651ca72
Show file tree
Hide file tree
Showing 16 changed files with 101 additions and 17 deletions.
9 changes: 7 additions & 2 deletions src/alloc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ use std::{
ops::{Index, IndexMut},
};

// TODO add custom niche for more efficient Options, wait until custom niches are stabilized (https://internals.rust-lang.org/t/nonmaxusize-and-niche-value-optimisation/19661)
// Maybe use NonZeroUsize (https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html)
/// UUIDs are type-safe integers. They are used for [FlatAlloc] and [ArenaAllocator]
///
/// They don't support arithmetic, as they're just meant to represent pointers.
///
/// TODO add custom niche for more efficient Options, wait until custom niches are stabilized (https://internals.rust-lang.org/t/nonmaxusize-and-niche-value-optimisation/19661)
/// Maybe use NonZeroUsize (https://doc.rust-lang.org/std/num/struct.NonZeroUsize.html)
pub struct UUID<IndexMarker>(usize, PhantomData<IndexMarker>);

impl<IndexMarker> Clone for UUID<IndexMarker> {
Expand All @@ -29,6 +33,7 @@ impl<IndexMarker> Hash for UUID<IndexMarker> {
}
}

/// See [UUID]
pub trait UUIDMarker {
const DISPLAY_NAME: &'static str;
}
Expand Down
1 change: 1 addition & 0 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::{InstantiatedModule, Linker, Module};

use std::{fs::{self, File}, io::Write, path::PathBuf, rc::Rc};

/// Implemented for SystemVerilog [self::system_verilog] or VHDL [self::vhdl]
pub trait CodeGenBackend {
fn file_extension(&self) -> &str;
fn output_dir_name(&self) -> &str;
Expand Down
1 change: 1 addition & 0 deletions src/compiler_top.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use crate::flattening::{

const STD_LIB_PATH: &str = env!("SUS_COMPILER_STD_LIB_PATH");

/// Any extra operations that should happen when files are added or removed from the linker. Such as caching line offsets.
pub trait LinkerExtraFileInfoManager {
/// This is there to give an acceptable identifier that can be printed
fn convert_filename(&self, path : &PathBuf) -> String {
Expand Down
2 changes: 2 additions & 0 deletions src/dev_aid/lsp/tree_walk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,15 @@ use crate::typing::template::{
ParameterKind, TypeParameterKind,
};

/// See [LocationInfo]
#[derive(Clone, Copy, Debug)]
pub enum InModule<'linker> {
NamedLocal(&'linker Declaration),
NamedSubmodule(&'linker SubModuleInstance),
Temporary(&'linker Expression),
}

/// Information about an object in the source code. Used for hovering, completions, syntax highlighting etc.
#[derive(Clone, Copy, Debug)]
pub enum LocationInfo<'linker> {
InModule(ModuleUUID, &'linker Module, FlatID, InModule<'linker>),
Expand Down
1 change: 1 addition & 0 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ pub trait ErrorInfoObject {
fn make_info(&self, file: FileUUID) -> ErrorInfo;
}

/// This represents objects that can be given as info to an error in a straight-forward way.
pub trait FileKnowingErrorInfoObject {
fn make_global_info(
&self,
Expand Down
7 changes: 7 additions & 0 deletions src/flattening/initialization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,13 @@ pub fn gather_initial_file_data(mut builder: FileBuilder) {
);
}


enum GlobalObjectKind {
Module,
Const,
Struct
}

fn initialize_global_object(builder: &mut FileBuilder, parsing_errors: ErrorCollector, span: Span, cursor: &mut Cursor) {
let is_extern = match cursor.optional_field(field!("extern_marker")).then(|| cursor.kind()) {
None => IsExtern::Normal,
Expand Down
9 changes: 2 additions & 7 deletions src/flattening/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,6 @@ use crate::typing::{
template::GlobalReference,
};

#[derive(Debug)]
pub enum GlobalObjectKind {
Module,
Const,
Struct
}

/// Modules are compiled in 4 stages. All modules must pass through each stage before advancing to the next stage.
///
/// 1. Initialization: initial name resolution and port discovery. The Module objects themselves are constructed.
Expand Down Expand Up @@ -309,6 +302,8 @@ impl Interface {
}

/// An element in a [WireReference] path. Could be array accesses, slice accesses, field accesses, etc
///
/// When executing, this turns into [crate::instantiation::RealWirePathElem]
#[derive(Debug, Clone, Copy)]
pub enum WireReferencePathElement {
ArrayAccess {
Expand Down
6 changes: 4 additions & 2 deletions src/instantiation/latency_algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub struct SpecifiedLatency {
pub latency: i64,
}

/// All the ways [solve_latencies] can go wrong
#[derive(Debug)]
pub enum LatencyCountingError {
ConflictingSpecifiedLatencies {
Expand Down Expand Up @@ -60,8 +61,9 @@ struct LatencyStackElem<'d> {
remaining_fanout: std::slice::Iter<'d, FanInOut>,
}

// Attempt 3 for Latency Counting
// TODO make this only take up 8 bytes with bitfield
/// The node for the latency-counting graph. See [solve_latencies]
///
/// TODO make this only take up 8 bytes with bitfield
#[derive(Clone, Copy)]
struct LatencyNode {
abs_lat: i64,
Expand Down
3 changes: 3 additions & 0 deletions src/instantiation/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ use self::latency_algorithm::SpecifiedLatency;
// Temporary value before proper latency is given
pub const CALCULATE_LATENCY_LATER: i64 = i64::MIN;

/// See [MultiplexerSource]
///
/// This is the post-instantiation equivalent of [crate::flattening::WireReferencePathElement]
#[derive(Debug, Clone)]
pub enum RealWirePathElem {
ArrayAccess { span: BracketSpan, idx_wire: WireID },
Expand Down
7 changes: 7 additions & 0 deletions src/linker/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,23 @@ impl Documentation {
}
}

/// [Module], [StructType], or [NamedConstant] annotation that specifies exceptions to code generation.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum IsExtern {
/// Code is generated for this through the regular channel (See [crate::codegen])
///
/// ```sus
/// module md {}
/// ```
Normal,
/// Modules that are provided externally, and thus no code should be generated for these
///
/// ```sus
/// extern module md {}
/// ```
Extern,
/// Builtins, like escape hatches for Latency Counting & domains
///
/// ```sus
/// __builtin__ module md {}
/// ```
Expand Down
1 change: 1 addition & 0 deletions src/to_string.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub fn map_to_type_names(parameters: &Parameters) -> FlatAlloc<String, TemplateI
parameters.map(|(_id, v)| v.name.clone())
}

/// For [Display::fmt] implementations on types: [ConcreteType], [WrittenType], [AbstractType]
pub trait TemplateNameGetter {
fn get_template_name(&self, id: TemplateID) -> &str;
}
Expand Down
25 changes: 22 additions & 3 deletions src/typing/abstract_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,28 @@ use crate::flattening::{BinaryOperator, StructType, TypingAllocator, UnaryOperat
use crate::linker::get_builtin_type;
use crate::to_string::map_to_type_names;

/// This contains only the information that can be easily type-checked.
/// This contains only the information that can be type-checked before template instantiation.
///
/// Its most important components are the names and structure of types.
///
/// What isn't included are the parameters of types. So Array Sizes for example.
///
/// This is such that useful information can still be given for modules that haven't been instantiated.
///
/// Not to be confused with [WrittenType], which is the in-source text representation.
///
/// Not to be confused with [crate::typing::concrete_type::ConcreteType], which is the
/// post-instantiation type.
///
/// [AbstractType]s don't actually get converted to [crate::typing::concrete_type::ConcreteType]s.
/// Instead [crate::typing::concrete_type::ConcreteType] gets created from [WrittenType] directly.
#[derive(Debug, Clone)]
pub enum AbstractType {
Template(TemplateID),
Named(TypeUUID),
Array(Box<AbstractType>),
/// Referencing [AbstractType::Unknown] is a strong code smell.
/// It is likely you should use [TypeSubstitutor::unify] instead
/// It is likely you should use [TypeSubstitutor::unify_must_succeed] or [TypeSubstitutor::unify_report_error] instead
///
/// It should only occur in creation `AbstractType::Unknown(self.type_substitutor.alloc())`
Unknown(TypeVariableID),
Expand All @@ -29,6 +39,15 @@ pub enum AbstractType {
pub const BOOL_TYPE: AbstractType = AbstractType::Named(get_builtin_type("bool"));
pub const INT_TYPE: AbstractType = AbstractType::Named(get_builtin_type("int"));

/// These represent (clock) domains. While clock domains are included under this umbrella, domains can use the same clock.
/// The use case for non-clock-domains is to separate Latency Counting domains. So different pipelines where it doesn't
/// necessarily make sense that their values are related by a fixed number of clock cycles.
///
/// Domains are resolved pre-instantiation, because dynamic domain merging doesn't seem like a valuable use case.
///
/// As a convenience, we make [DomainType::Generative] a special case for a domain.
///
/// The fun thing is that we can now use this domain info for syntax highlighting, giving wires in different domains a different color.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DomainType {
/// Generative conflicts with nothing
Expand All @@ -41,7 +60,7 @@ pub enum DomainType {
/// They always point to non-generative domains.
///
/// Referencing [DomainType::Unknown] is a strong code smell.
/// It is likely you should use [TypeSubstitutor::unify] instead
/// It is likely you should use [TypeSubstitutor::unify_must_succeed] or [TypeSubstitutor::unify_report_error] instead
///
/// It should only occur in creation `DomainType::Unknown(self.domain_substitutor.alloc())`
Unknown(DomainVariableID)
Expand Down
10 changes: 9 additions & 1 deletion src/typing/concrete_type.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,21 @@ use super::type_inference::ConcreteTypeVariableID;
pub const BOOL_CONCRETE_TYPE: ConcreteType = ConcreteType::Named(get_builtin_type("bool"));
pub const INT_CONCRETE_TYPE: ConcreteType = ConcreteType::Named(get_builtin_type("int"));

/// A post-instantiation type. These fully define what wires should be generated for a given object.
/// So as opposed to [crate::typing::abstract_type::AbstractType], type parameters are filled out with concrete values.
///
/// Examples: `bool[3]`, `int #(MAX: 20)`
///
/// Not to be confused with [crate::typing::abstract_type::AbstractType] which represents pre-instantiation types,
/// or [crate::flattening::WrittenType] which represents the textual in-editor data.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ConcreteType {
Named(TypeUUID),
Value(Value),
Array(Box<(ConcreteType, ConcreteType)>),
/// Referencing [ConcreteType::Unknown] is a strong code smell.
/// It is likely you should use [crate::typing::type_inference::TypeSubstitutor::unify] instead
/// It is likely you should use [crate::typing::type_inference::TypeSubstitutor::unify_must_succeed]
/// or [crate::typing::type_inference::TypeSubstitutor::unify_report_error] instead
///
/// It should only occur in creation `ConcreteType::Unknown(self.type_substitutor.alloc())`
Unknown(ConcreteTypeVariableID)
Expand Down
5 changes: 5 additions & 0 deletions src/typing/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ pub struct GenerativeParameterKind {
pub struct TypeParameterKind {}

/// See [Parameter]
///
/// Must match the [TemplateArgKind] that is passed
#[derive(Debug)]
pub enum ParameterKind {
Type(TypeParameterKind),
Expand Down Expand Up @@ -91,6 +93,9 @@ pub struct TemplateArg {
pub kind: TemplateArgKind,
}

/// See [TemplateArg]
///
/// The argument kind passed to [ParameterKind], which it must match
#[derive(Debug)]
pub enum TemplateArgKind {
Type(WrittenType),
Expand Down
27 changes: 25 additions & 2 deletions src/typing/type_inference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,13 +178,29 @@ impl<MyType: HindleyMilner<VariableIDMarker>, VariableIDMarker: UUIDMarker> Drop
}
}

/// See [HindleyMilner]
///
/// `TypeFuncIdent` is a value object, that is a "terminal". Basically, it's an atom that can either be equal or not.
///
/// Usually this is type names: `int` `bool`, or "array of" without the containing type.
///
/// Basically, when unifying, `int` isn't equal to "array of", and thus a type error is generated
///
/// This enum itself then is either such a terminal, or a type variable that can be unified (IE substituted)
#[derive(Debug, Clone, Copy)]
pub enum HindleyMilnerInfo<TypeFuncIdent, VariableIDMarker : UUIDMarker> {
/// Just a marker. Use [HindleyMilner::unify_all_args]
TypeFunc(TypeFuncIdent),
TypeVar(UUID<VariableIDMarker>)
}

/// Implements Hindley-Milner type unification for various types in the SUS language
///
/// Unification is roughly based on this video: https://www.youtube.com/watch?v=KNbRLTLniZI
/// The other HM videos are also highly recommended to understand this
///
/// Though this implementation does eager unification as much as possible, while unifications that cannot
/// be performed eagerly are handled by [DelayedConstraintsList].
pub trait HindleyMilner<VariableIDMarker: UUIDMarker> : Sized {
type TypeFuncIdent<'slf> : Eq where Self : 'slf;

Expand All @@ -203,7 +219,7 @@ pub trait HindleyMilner<VariableIDMarker: UUIDMarker> : Sized {
fn fully_substitute(&mut self, substitutor: &TypeSubstitutor<Self, VariableIDMarker>) -> bool;
}


/// [HindleyMilnerInfo] `TypeFuncIdent` for [AbstractType]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AbstractTypeHMInfo {
Template(TemplateID),
Expand Down Expand Up @@ -276,6 +292,7 @@ impl HindleyMilner<DomainVariableIDMarker> for DomainType {
}


/// [HindleyMilnerInfo] `TypeFuncIdent` for [ConcreteType]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConcreteTypeHMInfo<'slf> {
Named(TypeUUID),
Expand Down Expand Up @@ -326,14 +343,20 @@ impl HindleyMilner<ConcreteTypeVariableIDMarker> for ConcreteType {
}
}


/// See [DelayedConstraintsList::resolve_delayed_constraints]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum DelayedConstraintStatus {
/// The constraint can be removed
Resolved,
/// Progress was made, (potentially enabling other parts to continue), but the constraint cannot be removed
Progress,
/// No progress was made, if all constraints return [DelayedConstraintStatus::NoProgress] then type resolution deadlocked and cannot finish.
NoProgress
}

/// Implement this for any typing constraints that can't be resolved immediately.
///
/// See [DelayedConstraintsList]
pub trait DelayedConstraint<T> {
fn try_apply(&mut self, shared_object : &mut T) -> DelayedConstraintStatus;
fn report_could_not_resolve_error(&self, shared_object : &T);
Expand Down
4 changes: 4 additions & 0 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,15 @@ use crate::typing::{
type_inference::{ConcreteTypeVariableIDMarker, TypeSubstitutor}
};

/// Top type for any kind of compiletime value while executing.
///
/// These are used during execution ([crate::instantiation::execute])
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Value {
Bool(bool),
Integer(BigInt),
Array(Box<[Value]>),
/// The initial [Value] a variable has, before it's been set. (translates to `'x` don't care)
Unset,
Error,
}
Expand Down

0 comments on commit 651ca72

Please sign in to comment.