diff --git a/front/error/src/error.rs b/front/error/src/error.rs index 6de4c9a6..bbce070f 100644 --- a/front/error/src/error.rs +++ b/front/error/src/error.rs @@ -1,3 +1,9 @@ +//! Structured Wave diagnostics and human/JSON rendering. +//! +//! [`WaveError`] is the canonical diagnostic record. Renderers consume the same +//! code, location, context, label, note, and help fields so machine-readable +//! output cannot diverge from terminal diagnostics. + #[derive(Debug, Clone, PartialEq)] pub enum WaveErrorKind { // Lexer errors diff --git a/front/error/src/lib.rs b/front/error/src/lib.rs index 5df18265..bce5065a 100644 --- a/front/error/src/lib.rs +++ b/front/error/src/lib.rs @@ -1,3 +1,8 @@ +//! Structured diagnostics shared by the Wave frontend and compiler driver. +//! +//! Diagnostics retain source locations, labels, notes, and machine-readable +//! error codes so human and JSON renderers report the same underlying failure. + pub mod error; pub use error::*; diff --git a/front/lexer/src/core.rs b/front/lexer/src/core.rs index 03db3d19..e601234d 100644 --- a/front/lexer/src/core.rs +++ b/front/lexer/src/core.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Core token and lexer state. +//! +//! Cursor positions are UTF-8 byte offsets, while diagnostic columns count +//! Unicode scalar values from `line_start`. Cursor helpers must preserve that +//! distinction. + use crate::token::TokenType; use error::{WaveError, WaveErrorKind}; diff --git a/front/lexer/src/cursor.rs b/front/lexer/src/cursor.rs index e0b63037..521caffe 100644 --- a/front/lexer/src/cursor.rs +++ b/front/lexer/src/cursor.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! UTF-8-safe cursor movement and lookahead for the lexer. +//! +//! `current` is a byte offset. All movement advances by the selected character's +//! encoded width; lookahead never treats it as a character index. + use crate::Lexer; impl<'a> Lexer<'a> { diff --git a/front/lexer/src/ident.rs b/front/lexer/src/ident.rs index 11d8caf4..798ec699 100644 --- a/front/lexer/src/ident.rs +++ b/front/lexer/src/ident.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Identifier scanning and keyword classification. +//! +//! The lexer first consumes the complete identifier spelling, then maps exact +//! language keywords to dedicated tokens. Context-sensitive names such as +//! `ptr` and `array` remain identifiers for the parser's type grammar. + use crate::token::*; use crate::{Lexer, Token}; diff --git a/front/lexer/src/lib.rs b/front/lexer/src/lib.rs index cd62d86e..bdf96868 100644 --- a/front/lexer/src/lib.rs +++ b/front/lexer/src/lib.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Wave source lexer. +//! +//! The lexer converts UTF-8 source text into positioned tokens. Token spelling +//! is preserved for diagnostics, while literal and identifier modules perform +//! the validation needed before parsing begins. + // Lexer errors intentionally retain complete diagnostic context for rendering. #![allow(clippy::result_large_err)] diff --git a/front/lexer/src/literals.rs b/front/lexer/src/literals.rs index 766bb2b2..d190dec9 100644 --- a/front/lexer/src/literals.rs +++ b/front/lexer/src/literals.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! String, character, and numeric literal scanners. +//! +//! Literal escape validation belongs here rather than in the parser so invalid +//! source spellings retain precise lexer locations and diagnostic suggestions. + use super::Lexer; use error::{WaveError, WaveErrorKind}; diff --git a/front/lexer/src/scan.rs b/front/lexer/src/scan.rs index c6a2c7fa..dcdb9164 100644 --- a/front/lexer/src/scan.rs +++ b/front/lexer/src/scan.rs @@ -10,12 +10,19 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Top-level token dispatch for the Wave lexer. +//! +//! Trivia is consumed before every token. Multi-character operators must be +//! recognized before their one-character prefixes so the parser receives one +//! unambiguous token for each source operator. + use crate::token::*; use crate::{Lexer, Token}; use error::{WaveError, WaveErrorKind}; impl<'a> Lexer<'a> { #[allow(clippy::never_loop)] + /// Scans the next non-trivia token while preserving its source line. pub fn next_token(&mut self) -> Result { loop { self.skip_trivia()?; diff --git a/front/lexer/src/token.rs b/front/lexer/src/token.rs index bb9bd592..8566a0d9 100644 --- a/front/lexer/src/token.rs +++ b/front/lexer/src/token.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Token vocabulary produced by the lexer and consumed by the parser. +//! +//! Built-in type spellings have dedicated variants, while user-defined types +//! remain `TypeCustom`. Preserve that distinction when adding keywords because +//! type parsing and context-sensitive identifier handling depend on it. + use std::fmt; #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] diff --git a/front/lexer/src/trivia.rs b/front/lexer/src/trivia.rs index a33361fe..afa67c6a 100644 --- a/front/lexer/src/trivia.rs +++ b/front/lexer/src/trivia.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Whitespace and comment consumption with line tracking. +//! +//! Block comments may nest. Every consumed newline updates both the logical line +//! and byte offset used for later token columns, including newlines inside +//! comments. + use super::Lexer; use error::WaveError; use error::WaveErrorKind; diff --git a/front/parser/src/arch/aarch64.rs b/front/parser/src/arch/aarch64.rs index ee51fae3..8d2e8b66 100644 --- a/front/parser/src/arch/aarch64.rs +++ b/front/parser/src/arch/aarch64.rs @@ -10,6 +10,8 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Canonical AArch64 name and accepted target-attribute aliases. + pub(super) const NAME: &str = "aarch64"; pub(super) fn recognizes(value: &str) -> bool { diff --git a/front/parser/src/arch/mod.rs b/front/parser/src/arch/mod.rs index efd4b641..35bd3788 100644 --- a/front/parser/src/arch/mod.rs +++ b/front/parser/src/arch/mod.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Canonical architecture names used by target-attribute preprocessing. +//! +//! Common host/toolchain aliases normalize to stable Wave spellings. Unknown +//! values are preserved in lowercase so future targets can still participate in +//! string-based conditions before receiving a dedicated enum variant. + mod aarch64; mod riscv64; mod x86_64; diff --git a/front/parser/src/arch/riscv64.rs b/front/parser/src/arch/riscv64.rs index 7e5ca26c..0bb58e71 100644 --- a/front/parser/src/arch/riscv64.rs +++ b/front/parser/src/arch/riscv64.rs @@ -10,6 +10,8 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Canonical RISC-V 64-bit name used by target attributes. + pub(super) const NAME: &str = "riscv64"; pub(super) fn recognizes(value: &str) -> bool { diff --git a/front/parser/src/arch/x86_64.rs b/front/parser/src/arch/x86_64.rs index c0c9d75d..09b9baaf 100644 --- a/front/parser/src/arch/x86_64.rs +++ b/front/parser/src/arch/x86_64.rs @@ -10,6 +10,8 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Canonical x86-64 name and accepted target-attribute aliases. + pub(super) const NAME: &str = "x86_64"; pub(super) fn recognizes(value: &str) -> bool { diff --git a/front/parser/src/ast.rs b/front/parser/src/ast.rs index 3e49a3a0..837b8ec6 100644 --- a/front/parser/src/ast.rs +++ b/front/parser/src/ast.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Source-level syntax tree shared by parsing, semantic analysis, and codegen. +//! +//! Nodes describe Wave concepts, not LLVM storage or ABI decisions. Generic +//! monomorphization rewrites this representation before backend entry, so new +//! node forms must be handled by both semantic passes and that rewrite where +//! they may contain types or expressions. + use std::collections::HashMap; #[derive(Debug, Clone)] diff --git a/front/parser/src/expr/assign.rs b/front/parser/src/expr/assign.rs index c7013864..8af46f47 100644 --- a/front/parser/src/expr/assign.rs +++ b/front/parser/src/expr/assign.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Assignment expressions at the lowest precedence level. +//! +//! The right-hand side recurses at the same level, making chained assignment +//! right-associative. Assignability and mutability are validated after parsing. + use crate::ast::{AssignOperator, Expression}; use crate::expr::binary::parse_logical_or_expression; use lexer::token::TokenType; diff --git a/front/parser/src/expr/binary.rs b/front/parser/src/expr/binary.rs index 31803113..3d25b460 100644 --- a/front/parser/src/expr/binary.rs +++ b/front/parser/src/expr/binary.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Precedence-climbing entry points for binary and cast expressions. +//! +//! Precedence is encoded by the call chain rather than a numeric table: each +//! function parses its tighter-binding child, then folds operators at its own +//! level from left to right. Insert a new operator at the intended layer instead +//! of handling it in the primary-expression parser. + use crate::ast::{Expression, Operator}; use crate::expr::unary::parse_unary_expression; use crate::types::parse_type_from_stream; diff --git a/front/parser/src/expr/helpers.rs b/front/parser/src/expr/helpers.rs index 1669e5d2..9b4f6347 100644 --- a/front/parser/src/expr/helpers.rs +++ b/front/parser/src/expr/helpers.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Shared expression predicates and lvalue reconstruction helpers. +//! +//! Assignability is a syntax property here: variables, dereferences, fields, and +//! indices may form storage targets. Mutability and type legality are checked by +//! semantic validation. + use crate::ast::Expression; use crate::expr::parse_expression; use crate::expr::unary::parse_unary_expression; diff --git a/front/parser/src/expr/mod.rs b/front/parser/src/expr/mod.rs index d30667ee..92c1f24e 100644 --- a/front/parser/src/expr/mod.rs +++ b/front/parser/src/expr/mod.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Wave expression grammar from assignment down to primary expressions. +//! +//! The module split mirrors precedence and postfix/prefix roles. Callers enter +//! through [`parse_expression`] rather than selecting an internal precedence +//! layer directly. + mod assign; mod binary; mod helpers; diff --git a/front/parser/src/expr/postfix.rs b/front/parser/src/expr/postfix.rs index b1d7193a..5d0fcf77 100644 --- a/front/parser/src/expr/postfix.rs +++ b/front/parser/src/expr/postfix.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Postfix chaining for fields, methods, indices, calls, and increment/decrement. +//! +//! The loop repeatedly wraps the expression parsed so far, allowing chains such +//! as field access followed by indexing. Postfix mutation is accepted only for +//! expressions classified as assignable by the shared expression helper. + use std::iter::Peekable; use lexer::token::TokenType; diff --git a/front/parser/src/expr/primary.rs b/front/parser/src/expr/primary.rs index c2465380..ea572aad 100644 --- a/front/parser/src/expr/primary.rs +++ b/front/parser/src/expr/primary.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Primary expressions at the base of the precedence parser. +//! +//! This layer distinguishes literals, names, calls, struct literals, grouping, +//! and other atomic forms before postfix and binary operators are applied. + use std::iter::Peekable; use lexer::token::TokenType; diff --git a/front/parser/src/expr/unary.rs b/front/parser/src/expr/unary.rs index 481a49fe..860becb3 100644 --- a/front/parser/src/expr/unary.rs +++ b/front/parser/src/expr/unary.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Prefix unary parsing before primary and postfix expressions. +//! +//! Unary operators associate right-to-left through recursion. Address-of and +//! prefix increment/decrement additionally require an assignable operand. + use crate::ast::{Expression, IncDecKind, Literal, Operator}; use crate::expr::is_assignable; use crate::expr::primary::parse_primary_expression; diff --git a/front/parser/src/format.rs b/front/parser/src/format.rs index ec94ed1d..0fb607ee 100644 --- a/front/parser/src/format.rs +++ b/front/parser/src/format.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Splitting simple `{}` format strings into literal and placeholder AST parts. +//! +//! Only an empty brace pair is a placeholder here; other opening braces remain +//! literal text. + use crate::ast::FormatPart; pub fn parse_format_string(s: &str) -> Vec { diff --git a/front/parser/src/generics.rs b/front/parser/src/generics.rs index 65f069de..4bc77ee8 100644 --- a/front/parser/src/generics.rs +++ b/front/parser/src/generics.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Ahead-of-time generic monomorphization for the Wave AST. +//! +//! Generic templates are removed from the emitted AST and replaced by concrete +//! instances discovered while rewriting non-generic roots. Instance names are +//! deterministic so repeated references resolve to one generated definition. + use crate::ast::{ ASTNode, EnumNode, Expression, ExternFunctionNode, FunctionNode, Literal, MatchArm, MatchPattern, ParameterNode, ProtoImplNode, StatementNode, StructNode, TypeAliasNode, Value, @@ -20,6 +26,8 @@ use std::collections::{BTreeMap, HashMap, HashSet}; #[derive(Default)] struct GenericEnv { + // Templates are source definitions; instances are fully substituted nodes + // that may be emitted. BTreeMap keeps generated output deterministic. function_templates: HashMap, function_parameters: HashMap>, struct_templates: HashMap, @@ -31,9 +39,17 @@ struct GenericEnv { struct_in_progress: HashSet, } +/// Rewrites a parsed program into an AST containing only concrete generic instances. +/// +/// Callers must run this after import expansion and before concrete-AST +/// validation or code generation. A template-aware semantic pass may run first, +/// but later phases do not accept unresolved generic parameters in emitted +/// function and struct definitions. pub fn monomorphize_generics(ast: Vec) -> Result, String> { let mut env = GenericEnv::default(); + // Pass one records every callable signature and generic template before any + // body is rewritten, allowing forward references between declarations. for node in &ast { match node { ASTNode::Function(f) => { @@ -74,6 +90,8 @@ pub fn monomorphize_generics(ast: Vec) -> Result, String> let mut out: Vec = Vec::new(); let empty_subst: HashMap = HashMap::new(); + // Pass two rewrites concrete roots. Referenced generic instances are added + // to the environment recursively and appended after source declarations. for node in ast { match node { ASTNode::Function(f) => { @@ -720,6 +738,9 @@ fn ensure_struct_instance( if env.struct_instances.contains_key(&inst_name) { return Ok(inst_name); } + // Recursive types may refer to their own mangled name while the body is + // still being rewritten. Returning the reserved name breaks the recursion + // without emitting a duplicate definition. if env.struct_in_progress.contains(&inst_name) { return Ok(inst_name); } @@ -769,6 +790,7 @@ fn ensure_function_instance( if env.function_instances.contains_key(&inst_name) { return Ok(inst_name); } + // Recursive generic calls reuse the symbol reserved by the outer rewrite. if env.function_in_progress.contains(&inst_name) { return Ok(inst_name); } @@ -827,6 +849,9 @@ fn parse_wave_type_from_str(raw: &str) -> Result { } fn mangle_instance_name(base: &str, args: &[WaveType]) -> String { + // This is an internal compiler symbol scheme, not a public Wave ABI. Each + // type component is encoded explicitly to avoid collisions between nested + // pointer, array, scalar, and struct arguments. let mut out = String::with_capacity(base.len() + 16); out.push_str(base); out.push_str("$g"); diff --git a/front/parser/src/import.rs b/front/parser/src/import.rs index 50eb5dc9..dd153bd2 100644 --- a/front/parser/src/import.rs +++ b/front/parser/src/import.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Target-aware source preprocessing and recursive import expansion. +//! +//! Target attributes are resolved before lexing while preserving line structure +//! for diagnostics. Import expansion tracks canonical paths to detect cycles, +//! retains each source unit for later error mapping, and resolves local, +//! dependency, and standard-library roots through explicit configuration. + use crate::arch; use crate::ast::ASTNode; use crate::{parse_syntax_only, ParseError}; diff --git a/front/parser/src/lib.rs b/front/parser/src/lib.rs index 1173c7d4..3964ade0 100644 --- a/front/parser/src/lib.rs +++ b/front/parser/src/lib.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Wave syntax, AST, import expansion, generic specialization, and semantic validation. +//! +//! Parsing intentionally produces a source-oriented AST first. Imports and +//! generics are expanded before the semantic verifier establishes the typed +//! program contract consumed by code generation. + // These legacy parser APIs are being migrated incrementally; keep new lints fatal // without forcing risky mechanical rewrites into a release hardening change. #![allow( diff --git a/front/parser/src/parser/asm.rs b/front/parser/src/parser/asm.rs index 855b53a5..7c92807e 100644 --- a/front/parser/src/parser/asm.rs +++ b/front/parser/src/parser/asm.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Inline-assembly syntax for instruction, input, output, and clobber clauses. +//! +//! This parser validates clause shape and assignable output expressions. Target +//! register names and stack contracts are intentionally deferred to the +//! architecture-aware backend planner. + use crate::ast::{ASTNode, Expression, Literal, StatementNode}; use crate::expr::is_assignable; use lexer::token::TokenType; diff --git a/front/parser/src/parser/control.rs b/front/parser/src/parser/control.rs index ea4170b9..b763d018 100644 --- a/front/parser/src/parser/control.rs +++ b/front/parser/src/parser/control.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Parsing for conditional, loop, and match statements. +//! +//! Control-flow parsers delegate bodies to the shared block parser and return +//! syntax-only nodes. Match-arm `=>` is currently represented by two lexer +//! tokens, so this module owns consuming that pair as one delimiter. + use crate::ast::{ ASTNode, Expression, MatchArm, MatchPattern, Mutability, StatementNode, VariableNode, }; diff --git a/front/parser/src/parser/decl.rs b/front/parser/src/parser/decl.rs index f88caf24..f489fbb7 100644 --- a/front/parser/src/parser/decl.rs +++ b/front/parser/src/parser/decl.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Variable, external function, type-alias, and enum declarations. +//! +//! Declaration parsing records source types and ABI annotations without making +//! backend layout decisions. Nested generic text is consumed with delimiter +//! depth so inner commas and closing chevrons cannot terminate the outer type. + use crate::ast::{ ASTNode, EnumNode, EnumVariantNode, Expression, ExternFunctionNode, Mutability, TypeAliasNode, VariableNode, WaveType, diff --git a/front/parser/src/parser/expr.rs b/front/parser/src/parser/expr.rs index e36d0ce6..6819c1ce 100644 --- a/front/parser/src/parser/expr.rs +++ b/front/parser/src/parser/expr.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compatibility helpers for token-slice function calls and parenthesized spans. +//! +//! The main precedence parser handles current expression syntax. Keep these +//! helpers isolated so older parser consumers do not influence operator or +//! generic-call parsing. + use crate::ast::Expression; use crate::expr::parse_expression; use lexer::token::TokenType; diff --git a/front/parser/src/parser/functions.rs b/front/parser/src/parser/functions.rs index e46160f0..a1631f95 100644 --- a/front/parser/src/parser/functions.rs +++ b/front/parser/src/parser/functions.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Function declarations, generic parameters, parameters, and function bodies. +//! +//! Function parsing establishes syntax and declared types only. Duplicate names +//! within generic parameter lists are rejected here; program-wide symbol and +//! body type checks remain the semantic verifier's responsibility. + use crate::ast::{ASTNode, ExportAttribute, FunctionNode, ParameterNode, StatementNode, Value}; use crate::expr::parse_expression; use crate::parser::asm::*; diff --git a/front/parser/src/parser/io.rs b/front/parser/src/parser/io.rs index 6149e313..5a45cf97 100644 --- a/front/parser/src/parser/io.rs +++ b/front/parser/src/parser/io.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Parsing of `print`, `println`, and `input` statements. +//! +//! Placeholder counts are checked while parsing so the AST distinguishes plain +//! literal output from formatted calls. Argument types and C format conversion +//! remain semantic/backend responsibilities. + use crate::ast::{ASTNode, StatementNode}; use crate::expr::parse_expression; use lexer::token::TokenType; @@ -18,7 +24,6 @@ use std::iter::Peekable; use std::slice::Iter; use utils::formatx::*; -// PRINTLN parsing pub fn parse_println(tokens: &mut Peekable>) -> Option { if tokens.peek()?.token_type != TokenType::Lparen { println!("Error: Expected '(' after 'println'"); diff --git a/front/parser/src/parser/items.rs b/front/parser/src/parser/items.rs index cc0124f2..5d711bc8 100644 --- a/front/parser/src/parser/items.rs +++ b/front/parser/src/parser/items.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Parsers for top-level imports, proto implementations, and structures. +//! +//! These item parsers consume their complete declaration, including the closing +//! delimiter or semicolon. Method bodies reuse the function parser so parameter, +//! generic, and return-type grammar stays consistent across item kinds. + use crate::ast::{ASTNode, ProtoImplNode, StatementNode, StructNode, WaveType}; use crate::parser::functions::{parse_function, parse_generic_param_names}; use crate::types::parse_type_from_stream; diff --git a/front/parser/src/parser/mod.rs b/front/parser/src/parser/mod.rs index 52d9f904..23831ea2 100644 --- a/front/parser/src/parser/mod.rs +++ b/front/parser/src/parser/mod.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Syntax parser modules and public parsing entry points. +//! +//! Submodules consume complete grammar units. `parse_syntax_only` exposes the +//! source-oriented AST used before import expansion and semantic validation. + pub mod asm; pub mod control; pub mod decl; diff --git a/front/parser/src/parser/parse.rs b/front/parser/src/parser/parse.rs index 6a2c9bf9..e56e823e 100644 --- a/front/parser/src/parser/parse.rs +++ b/front/parser/src/parser/parse.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Parser entry points and top-level declaration dispatch. +//! +//! These routines construct a source-oriented AST only. Import expansion, +//! generic specialization, and semantic type validation are later phases and +//! must not be silently performed while consuming syntax. + use crate::ast::ASTNode; use crate::parser::decl::*; use crate::parser::functions::{parse_export, parse_function}; diff --git a/front/parser/src/parser/stmt.rs b/front/parser/src/parser/stmt.rs index 8444a40e..333a0332 100644 --- a/front/parser/src/parser/stmt.rs +++ b/front/parser/src/parser/stmt.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Statement parsing and statement-level recovery boundaries. +//! +//! A statement parser consumes its complete terminator or block. Keeping that +//! ownership local prevents a failed statement from shifting the token stream +//! seen by the following declaration. + use crate::ast::{ASTNode, AssignOperator, Expression, StatementNode}; use crate::expr::{is_assignable, parse_expression, parse_expression_from_token}; use crate::parser::control::{parse_for, parse_if, parse_match, parse_while}; diff --git a/front/parser/src/parser/types.rs b/front/parser/src/parser/types.rs index 8b0b37e8..b402ee65 100644 --- a/front/parser/src/parser/types.rs +++ b/front/parser/src/parser/types.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Wave type grammar used by declarations and explicit type arguments. +//! +//! Nested pointer, array, and generic forms are parsed structurally so commas +//! and closing chevrons are interpreted at the correct nesting depth. + use crate::ast::WaveType; use crate::decl::collect_generic_inner; use lexer::token::*; diff --git a/front/parser/src/stdlib.rs b/front/parser/src/stdlib.rs index 83c7078b..473c8eef 100644 --- a/front/parser/src/stdlib.rs +++ b/front/parser/src/stdlib.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Registry of standard-library module signatures known to the frontend. +//! +//! Strict mode requires imports to name a registered module. Non-strict mode is +//! retained for environments that resolve standard-library source externally. + use crate::ast::{FunctionSignature, WaveType}; use std::collections::{HashMap, HashSet}; diff --git a/front/parser/src/verification.rs b/front/parser/src/verification.rs index 30415a6a..28e6fdfd 100644 --- a/front/parser/src/verification.rs +++ b/front/parser/src/verification.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Whole-program semantic validation and expression type analysis. +//! +//! The verifier runs after imports and generics have been expanded. It first +//! collects declarations into a program-wide type environment, then validates +//! bodies with lexical scopes and expected types. It reports source-oriented +//! hints instead of retaining parser token positions in the AST. + use crate::ast::{ ASTNode, AssignOperator, Expression, FunctionNode, IncDecKind, Literal, MatchPattern, Mutability, Operator, StatementNode, WaveType, @@ -68,6 +75,8 @@ struct FunctionType { #[derive(Clone, Debug)] enum ExpressionType { + // Literal and null states stay distinct until an expected type supplies the + // width, signedness, element type, or pointer pointee required to commit. Known(WaveType), IntLiteral(String), FloatLiteral, @@ -95,6 +104,8 @@ impl ProgramTypes { fn collect(nodes: &[ASTNode]) -> Result)> { let mut out = Self::default(); + // Reserve all type names and generic parameters first. The second pass + // can then resolve forward references without depending on source order. for (index, node) in nodes.iter().enumerate() { let type_name = match node { ASTNode::Struct(structure) => Some(structure.name.as_str()), @@ -136,6 +147,8 @@ impl ProgramTypes { let mut value_names = HashSet::new(); + // Values, fields, methods, aliases, and constants need their complete + // signatures before any function body is checked. for (index, node) in nodes.iter().enumerate() { let failure = |message: String, primary: Option| (index, message, primary); diff --git a/front/parser/tests/parse_var_and_generics.rs b/front/parser/tests/parse_var_and_generics.rs index 5dde675a..9d374641 100644 --- a/front/parser/tests/parse_var_and_generics.rs +++ b/front/parser/tests/parse_var_and_generics.rs @@ -1,3 +1,5 @@ +//! Regression coverage for variable declarations and generic type syntax. + use lexer::Lexer; use parser::parse_syntax_only; diff --git a/llvm/src/backend.rs b/llvm/src/backend.rs index 2a7df027..0f29303b 100644 --- a/llvm/src/backend.rs +++ b/llvm/src/backend.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! External LLVM tool and native-linker orchestration. +//! +//! In-process IR generation lives in `codegen`; this module translates resolved +//! backend options into `llc` and linker invocations, locates bundled tools, and +//! supplies platform startup/default-library arguments. + use crate::codegen::target::{target_spec_for_triple, CodegenTarget}; use std::env; use std::path::PathBuf; diff --git a/llvm/src/codegen/abi_c.rs b/llvm/src/codegen/abi_c.rs index c7f858bb..5044f0b6 100644 --- a/llvm/src/codegen/abi_c.rs +++ b/llvm/src/codegen/abi_c.rs @@ -10,7 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. -// src/llvm_temporary/llvm_codegen/abi_c.rs +//! Target-specific C calling-convention classification. +//! +//! Wave object representation and C ABI transport representation are separate: +//! an aggregate may be passed directly, split across registers, ignored, or +//! addressed indirectly without changing its in-memory layout. Classification +//! happens here; call and function emission only apply the resulting contract. use inkwell::attributes::{Attribute, AttributeLoc}; use inkwell::context::Context; use inkwell::targets::TargetData; @@ -27,17 +32,30 @@ use super::types::{wave_type_to_llvm_type, TypeFlavor}; #[derive(Clone)] pub enum ParamLowering<'ctx> { Ignore, - Direct(BasicTypeEnum<'ctx>), // pass as this llvm type - Split(Vec>), // pass as multiple params - Indirect { ty: AnyTypeEnum<'ctx> }, // pass a pointer without byval - ByVal { ty: AnyTypeEnum<'ctx>, align: u32 }, // pass ptr + byval + align + /// Pass the value as one LLVM parameter of this transport type. + Direct(BasicTypeEnum<'ctx>), + /// Decompose one Wave parameter into multiple LLVM parameters. + Split(Vec>), + /// Pass a pointer without attaching the C `byval` attribute. + Indirect { + ty: AnyTypeEnum<'ctx>, + }, + /// Pass a pointer carrying the C `byval` size/alignment contract. + ByVal { + ty: AnyTypeEnum<'ctx>, + align: u32, + }, } #[derive(Clone)] pub enum RetLowering<'ctx> { Void, Direct(BasicTypeEnum<'ctx>), - SRet { ty: AnyTypeEnum<'ctx>, align: u32 }, // hidden first param + /// Return through a hidden first parameter with the `sret` attribute. + SRet { + ty: AnyTypeEnum<'ctx>, + align: u32, + }, } #[derive(Clone, Copy)] @@ -48,13 +66,18 @@ pub enum IntegerExtension { #[derive(Clone)] pub struct ExternCInfo<'ctx> { - pub llvm_name: String, // actual LLVM symbol name - pub wave_ret: WaveType, // Wave-level return type (needed when sret => llvm void) + /// Actual symbol name emitted to LLVM. + pub llvm_name: String, + /// Source return type, retained when an `sret` function returns LLVM void. + pub wave_ret: WaveType, pub ret: RetLowering<'ctx>, pub ret_extension: Option, - pub params: Vec>, // per-wave param - pub param_extensions: Vec>, // per-wave param - pub llvm_param_types: Vec>, // final lowered param list (including sret ptr, split, byval ptr) + /// One classification for each source-level parameter. + pub params: Vec>, + /// Narrow-integer extension contract for each source-level parameter. + pub param_extensions: Vec>, + /// Final LLVM parameter list, including hidden, split, and indirect values. + pub llvm_param_types: Vec>, pub variadic: bool, pub variadic_integer_extension: Option, } diff --git a/llvm/src/codegen/address.rs b/llvm/src/codegen/address.rs index 73a17895..10f68fd4 100644 --- a/llvm/src/codegen/address.rs +++ b/llvm/src/codegen/address.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Address calculation for assignable expressions. +//! +//! LLVM pointers are opaque, so lvalue lowering must recover pointee and field +//! types from Wave semantic types rather than from the LLVM pointer itself. +//! This module returns both the address and its storage type to keep subsequent +//! loads and stores consistent. + use inkwell::builder::Builder; use inkwell::context::Context; use inkwell::module::Module; diff --git a/llvm/src/codegen/arch/aarch64.rs b/llvm/src/codegen/arch/aarch64.rs index 3b6553df..c7ba3bc9 100644 --- a/llvm/src/codegen/arch/aarch64.rs +++ b/llvm/src/codegen/arch/aarch64.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! AArch64 register aliases, inline-assembly clobbers, and stack effects. +//! +//! The platform register (`x18`), stack pointer, and zero register are excluded +//! from general operand allocation even though they are valid assembler names. + #[cfg(any(feature = "llvm-target-all", feature = "llvm-target-aarch64"))] pub(crate) const CPUS: &[&str] = &["generic", "cortex-a53", "cortex-a72"]; #[cfg(any(feature = "llvm-target-all", feature = "llvm-target-aarch64"))] diff --git a/llvm/src/codegen/arch/mod.rs b/llvm/src/codegen/arch/mod.rs index fc0c2a58..42288210 100644 --- a/llvm/src/codegen/arch/mod.rs +++ b/llvm/src/codegen/arch/mod.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Architecture-specific inline-assembly contracts. +//! +//! The shared codegen layer dispatches through this module for register aliases, +//! operand eligibility, clobbers, dialect selection, and conservative stack +//! analysis. Target-specific spelling must stay in the architecture modules so +//! accepting syntax for one ISA cannot silently affect another. + pub(crate) mod aarch64; pub(crate) mod riscv64; pub(crate) mod x86_64; @@ -95,6 +102,8 @@ pub(crate) struct StackAnalysis { } pub(crate) fn instruction_text(line: &str, hash_is_comment: bool) -> String { + // `#` starts a comment on x86/RISC-V but introduces immediates on AArch64. + // Callers choose the rule before labels and mnemonics are normalized. let without_slash_comment = line.split_once("//").map(|(code, _)| code).unwrap_or(line); let line = if hash_is_comment { without_slash_comment @@ -127,6 +136,8 @@ pub(crate) fn mnemonic(code: &str) -> &str { } pub(crate) fn stack_analysis(architecture: Architecture, line: &str) -> StackAnalysis { + // This is deliberately conservative. Unknown writes reject an inline-asm + // contract instead of pretending that stack balance can be proven. match architecture { Architecture::X86_64 => x86_64::stack_analysis(line), Architecture::Aarch64 => aarch64::stack_analysis(line), diff --git a/llvm/src/codegen/arch/riscv64.rs b/llvm/src/codegen/arch/riscv64.rs index 4b50da0a..59ceb398 100644 --- a/llvm/src/codegen/arch/riscv64.rs +++ b/llvm/src/codegen/arch/riscv64.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! RISC-V 64-bit target features, ABI names, registers, and stack effects. +//! +//! Integer and floating-point ABI aliases are normalized to physical register +//! numbers. Feature-to-ISA spelling lives here; compatibility between the +//! selected ISA and LP64/LP64F/LP64D is enforced by the target resolver. + #[cfg(any(feature = "llvm-target-all", feature = "llvm-target-riscv"))] pub(crate) const CPUS: &[&str] = &["generic", "generic-rv64", "rocket-rv64", "sifive-u74"]; #[cfg(any(feature = "llvm-target-all", feature = "llvm-target-riscv"))] @@ -36,6 +42,8 @@ pub(crate) fn isa_name( zicsr: bool, zifencei: bool, ) -> String { + // Prefer the standard `g` shorthand only when the complete general-purpose + // extension set is present; otherwise preserve the precise extension set. if m && a && f && d && c && zicsr && zifencei { return "rv64gc".to_string(); } diff --git a/llvm/src/codegen/arch/x86_64.rs b/llvm/src/codegen/arch/x86_64.rs index f01e8b20..57ae44a1 100644 --- a/llvm/src/codegen/arch/x86_64.rs +++ b/llvm/src/codegen/arch/x86_64.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! x86-64 register aliases, inline-assembly clobbers, and stack effects. +//! +//! Register groups collapse partial-register spellings to their physical +//! register so constraint and clobber validation cannot allocate overlapping +//! operands independently. + #[cfg(any(feature = "llvm-target-all", feature = "llvm-target-x86"))] pub(crate) const CPUS: &[&str] = &["generic", "x86-64", "x86-64-v2", "x86-64-v3"]; #[cfg(any(feature = "llvm-target-all", feature = "llvm-target-x86"))] diff --git a/llvm/src/codegen/consts.rs b/llvm/src/codegen/consts.rs index 3602704f..87e3d949 100644 --- a/llvm/src/codegen/consts.rs +++ b/llvm/src/codegen/consts.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compile-time evaluation of Wave constants into LLVM constant values. +//! +//! Evaluation is intentionally separate from runtime expression lowering: +//! globals require LLVM constants and cannot emit instructions. Unknown names +//! are reported distinctly so module construction can resolve forward constant +//! references in dependency rounds. + use inkwell::context::Context; use inkwell::types::{BasicTypeEnum, StringRadix, StructType}; use inkwell::values::{BasicValue, BasicValueEnum}; diff --git a/llvm/src/codegen/format.rs b/llvm/src/codegen/format.rs index 72b5b290..07b32b49 100644 --- a/llvm/src/codegen/format.rs +++ b/llvm/src/codegen/format.rs @@ -10,16 +10,19 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Translation of Wave formatting placeholders to C `printf`/`scanf` formats. +//! +//! Format selection combines LLVM value types with Wave-level pointer meaning; +//! opaque LLVM pointers alone cannot distinguish C strings from other pointers. + use inkwell::context::Context; use inkwell::types::BasicTypeEnum; use parser::ast::WaveType; -/// Wave format string -> C printf format string +/// Converts a Wave format string into a C `printf` format string. /// -/// NOTE: -/// - Inkwell (opaque pointers) cannot extract the element type from PointerType. -/// - Therefore, determining "whether this pointer is a C string" cannot be done solely with LLVM types. -/// - The caller (io.rs) must also pass arg_is_cstr. +/// `arg_types` and `arg_is_cstr` are parallel arrays. The latter carries the +/// semantic pointer information unavailable from LLVM opaque pointer types. pub fn wave_format_to_c<'ctx>( context: &'ctx Context, format: &str, diff --git a/llvm/src/codegen/ir.rs b/llvm/src/codegen/ir.rs index 5d61080f..2af6d24c 100644 --- a/llvm/src/codegen/ir.rs +++ b/llvm/src/codegen/ir.rs @@ -10,6 +10,14 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Construction and emission of a complete LLVM module. +//! +//! This is the backend assembly point: it resolves named types, installs the +//! semantic expression-type table, lowers C ABI boundaries, emits functions, +//! and applies the selected optimization pipeline. Target +//! initialization is process-wide, while each compilation receives its own LLVM +//! context and module. + use inkwell::attributes::{Attribute, AttributeLoc}; use inkwell::context::Context; use inkwell::module::{FlagBehavior, Linkage, Module}; @@ -145,6 +153,10 @@ fn rebuild_split_abi_value<'ctx>( .unwrap(); builder.build_store(part_ptr, *part).unwrap(); let offset_value = context.i64_type().const_int(offset, false); + // SAFETY: `target_ptr` is an opaque pointer to a live stack allocation; + // using `i8` makes this a byte offset. When the offset reaches or passes + // the allocation size, `copy_size` is zero and the pointer is not used + // for a memory access. let destination = unsafe { builder .build_gep( @@ -455,6 +467,13 @@ fn apply_function_codegen_attrs<'ctx>( } } +/// Builds an LLVM module and returns its textual representation. +/// +/// # Safety +/// +/// This function retains an unsafe signature for compatibility with the +/// compiler driver's LLVM boundary. It imposes no additional caller-side +/// memory-safety requirements. pub unsafe fn generate_ir( ast_nodes: &[ASTNode], opt_flag: &str, @@ -464,6 +483,13 @@ pub unsafe fn generate_ir( generated.module.print_to_string().to_string() } +/// Builds a module and emits one target-machine output file. +/// +/// # Safety +/// +/// This function retains an unsafe signature for compatibility with the +/// compiler driver's LLVM boundary. It imposes no additional caller-side +/// memory-safety requirements. pub unsafe fn emit_codegen_file( ast_nodes: &[ASTNode], opt_flag: &str, @@ -510,6 +536,11 @@ fn build_module( codegen_trace("initialize targets"); initialize_llvm_targets(); + // Inkwell ties every module and builder to its context through lifetimes. + // GeneratedModule crosses this function boundary, so these allocations live + // for the compiler process. The CLI is short-lived and never calls LLVM + // shutdown; a long-lived embedding API should replace this with an owned + // compilation-session object rather than copying this pattern. codegen_trace("create context"); let context: &'static Context = Box::leak(Box::new(Context::create())); codegen_trace("create module"); diff --git a/llvm/src/codegen/legacy.rs b/llvm/src/codegen/legacy.rs index 8e021c5b..780ad0dc 100644 --- a/llvm/src/codegen/legacy.rs +++ b/llvm/src/codegen/legacy.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compatibility helpers for the former token-based code-generation API. +//! +//! Current lowering uses semantic [`WaveType`](parser::ast::WaveType) values. +//! Do not extend this module with new language types; migrate remaining callers +//! to `codegen::types` instead. + use inkwell::context::Context; use inkwell::types::{BasicType, BasicTypeEnum}; use inkwell::values::{FunctionValue, PointerValue}; @@ -54,6 +60,12 @@ pub fn get_llvm_type<'a>(context: &'a Context, ty: &TokenType) -> BasicTypeEnum< } #[allow(dead_code)] +/// Creates a legacy `i32` stack slot at the builder's current insertion point. +/// +/// # Safety +/// +/// This function retains an unsafe signature for API compatibility and imposes +/// no additional caller-side memory-safety requirements. pub unsafe fn create_alloc<'a>( context: &'a Context, builder: &'a inkwell::builder::Builder<'a>, diff --git a/llvm/src/codegen/mod.rs b/llvm/src/codegen/mod.rs index d16f794a..77ef92da 100644 --- a/llvm/src/codegen/mod.rs +++ b/llvm/src/codegen/mod.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Public assembly point for LLVM code-generation services. +//! +//! New lowering belongs in a focused submodule. Re-export only the small set of +//! entry points required by the compiler driver and expression/statement layers. + pub mod abi_c; pub mod address; pub mod arch; diff --git a/llvm/src/codegen/plan.rs b/llvm/src/codegen/plan.rs index 0d2e16db..7bfcd9b6 100644 --- a/llvm/src/codegen/plan.rs +++ b/llvm/src/codegen/plan.rs @@ -10,7 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. -// codegen/asm/plan.rs +//! Architecture-aware validation and normalization of inline assembly. +//! +//! An [`AsmPlan`] is the checked boundary between source syntax and LLVM inline +//! assembly. It normalizes register aliases, orders constraints, detects +//! conflicting operands and clobbers, and verifies stack/noreturn declarations +//! against conservative instruction analysis. use crate::codegen::arch; use crate::codegen::target::CodegenTarget; use parser::ast::Expression; diff --git a/llvm/src/codegen/semantic.rs b/llvm/src/codegen/semantic.rs index 3a1f9663..30f345c5 100644 --- a/llvm/src/codegen/semantic.rs +++ b/llvm/src/codegen/semantic.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Thread-local bridge from frontend expression types to backend lowering. +//! +//! Keys are addresses of expressions in the exact AST allocation analyzed before +//! codegen. The table must be installed after the last AST clone or rewrite and +//! consumed on the same thread; a future typed AST should replace this bridge. + use parser::ast::{Expression, WaveType}; use std::cell::RefCell; use std::collections::HashMap; @@ -19,6 +25,8 @@ thread_local! { } pub(super) fn install_expression_types(types: HashMap) { + // Replace rather than extend so one compilation cannot observe entries from + // an earlier module built on the same worker thread. EXPRESSION_TYPES.with(|current| *current.borrow_mut() = types); } diff --git a/llvm/src/codegen/target.rs b/llvm/src/codegen/target.rs index 8b38efaa..801c6b29 100644 --- a/llvm/src/codegen/target.rs +++ b/llvm/src/codegen/target.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Supported-target registry and target-option contract validation. +//! +//! A [`TargetSpec`] is the single source of truth shared by CLI validation, +//! LLVM target-machine creation, inline assembly, and C ABI classification. +//! Keep exact triples here rather than accepting an architecture prefix: OS, +//! environment, and object format are ABI-relevant parts of a target. + use inkwell::module::Module; use inkwell::targets::TargetTriple; use std::collections::{BTreeMap, BTreeSet}; @@ -55,6 +62,11 @@ pub struct EffectiveTargetOptions { pub isa: Option, } +/// Resolves user overrides into the complete option set passed to LLVM. +/// +/// RISC-V ABI, floating-point extensions, and ISA spelling are coupled. This +/// function validates that contract once so later codegen does not need to +/// reinterpret partially specified options. pub fn resolve_target_options( spec: &TargetSpec, cpu: Option<&str>, @@ -93,6 +105,8 @@ pub fn resolve_target_options( .collect::>(); if spec.architecture == Architecture::Riscv64 { + // The ABI establishes the initial F/D state. Explicit feature settings + // are applied afterward and must still describe the same ABI. match abi.or(spec.default_abi) { Some("lp64") => { enabled.insert("f", false); @@ -151,6 +165,9 @@ pub fn resolve_target_options( let mut effective_abi = abi.or(spec.default_abi).map(str::to_string); let mut isa = None; if spec.architecture == Architecture::Riscv64 { + // LLVM requires the CSR extension for floating-point instructions. Add + // it implicitly unless the user explicitly disabled it, in which case + // the consistency check below produces a useful error. if enabled.get("f").copied().unwrap_or(false) && !explicitly_set.contains("zicsr") { enabled.insert("zicsr", true); } @@ -203,6 +220,9 @@ pub fn resolve_target_options( )); } + // RISC-V passes every supported feature with an explicit sign. Omitting a + // disabled F/D feature can let LLVM's CPU defaults silently contradict the + // effective ABI. let render_all_features = spec.architecture == Architecture::Riscv64; let features = spec .features @@ -411,6 +431,7 @@ const FREESTANDING_RISCV64: TargetSpec = TargetSpec { default_abi: Some(arch::riscv64::FREESTANDING_DEFAULT_ABI), }; +/// Returns the targets compiled into this backend, in deterministic order. pub fn supported_target_specs() -> Vec<&'static TargetSpec> { let mut specs: Vec<&'static TargetSpec> = Vec::new(); @@ -433,6 +454,7 @@ pub fn supported_target_specs() -> Vec<&'static TargetSpec> { specs } +/// Performs an exact lookup in the compiled target registry. pub fn target_spec_for_triple(triple: &str) -> Option<&'static TargetSpec> { supported_target_specs() .into_iter() diff --git a/llvm/src/codegen/types.rs b/llvm/src/codegen/types.rs index ca8db5dd..77bc9dcf 100644 --- a/llvm/src/codegen/types.rs +++ b/llvm/src/codegen/types.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Mapping between Wave semantic types and LLVM value/storage types. +//! +//! [`TypeFlavor`] keeps ordinary value lowering separate from C ABI-facing type +//! construction. Calling-convention transport decisions are not made here; the +//! C ABI classifier consumes these object representations afterward. + use inkwell::context::Context; use inkwell::types::{BasicType, BasicTypeEnum}; use inkwell::values::PointerValue; diff --git a/llvm/src/expression/lvalue.rs b/llvm/src/expression/lvalue.rs index 9fea22e8..f7d5b63a 100644 --- a/llvm/src/expression/lvalue.rs +++ b/llvm/src/expression/lvalue.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Loading values from Wave lvalue expressions. +//! +//! Variables, dereferences, indices, and fields first resolve to a typed storage +//! address. Loads then use the recovered Wave type, avoiding guesses from +//! LLVM's opaque pointer type and preserving aggregate storage representation. + use inkwell::targets::TargetData; use inkwell::{ builder::Builder, diff --git a/llvm/src/expression/mod.rs b/llvm/src/expression/mod.rs index c96e444e..625cc871 100644 --- a/llvm/src/expression/mod.rs +++ b/llvm/src/expression/mod.rs @@ -10,5 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! LLVM lowering split between storage addresses and computed values. +//! +//! Lvalue lowering answers where a value is stored; rvalue lowering answers what +//! value an expression produces. Keep that distinction explicit for aggregates +//! and opaque pointers. + pub mod lvalue; pub mod rvalue; diff --git a/llvm/src/expression/rvalue/arrays.rs b/llvm/src/expression/rvalue/arrays.rs index ea787154..b808bc66 100644 --- a/llvm/src/expression/rvalue/arrays.rs +++ b/llvm/src/expression/rvalue/arrays.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Array literal construction under an expected array type. +//! +//! LLVM opaque pointers cannot recover an array shape from a pointer expectation, +//! so literals require a concrete array type supplied by semantic context. + use super::ExprGenEnv; use inkwell::types::BasicTypeEnum; use inkwell::values::{BasicValue, BasicValueEnum}; @@ -57,6 +62,8 @@ Use a temp variable: `var tmp: array = [...]; foo(tmp);`" let idx = env.context.i32_type().const_int(i as u64, false); + // SAFETY: `i` ranges over the literal elements accepted for `arr_ty`; the + // semantic verifier guarantees the literal length matches the array type. let gep = unsafe { env.builder .build_in_bounds_gep(arr_ty, alloca, &[zero, idx], &format!("arr_gep_{}", i)) diff --git a/llvm/src/expression/rvalue/asm.rs b/llvm/src/expression/rvalue/asm.rs index 686b58d2..9dcd2ebc 100644 --- a/llvm/src/expression/rvalue/asm.rs +++ b/llvm/src/expression/rvalue/asm.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Inline-assembly expression lowering. +//! +//! [`AsmPlan`] performs target-specific validation before this module creates an +//! LLVM inline-asm value. Expressions may produce at most one value; statement +//! assembly handles the multi-output form separately. + use super::ExprGenEnv; use crate::codegen::arch; use crate::codegen::plan::*; @@ -66,6 +72,9 @@ pub(crate) fn gen<'ctx, 'a>( false, ); + // SAFETY: `create_inline_asm` returns an LLVM value whose type is exactly + // `fn_type`; wrapping that same value as a callee pointer preserves the + // context and function signature used by `build_indirect_call` below. let callee = unsafe { PointerValue::new(inline_asm.as_value_ref()) }; env.builder @@ -100,6 +109,8 @@ pub(crate) fn gen<'ctx, 'a>( false, ); + // SAFETY: The inline-asm value was created in this context with `fn_type`, + // which is also supplied to the indirect call immediately below. let callee = unsafe { PointerValue::new(inline_asm.as_value_ref()) }; let call = env diff --git a/llvm/src/expression/rvalue/assign.rs b/llvm/src/expression/rvalue/assign.rs index f3110b38..5b44f314 100644 --- a/llvm/src/expression/rvalue/assign.rs +++ b/llvm/src/expression/rvalue/assign.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Assignment and compound-assignment expression lowering. +//! +//! Lvalue type recovery happens before the right-hand side is generated so +//! literals and `null` receive the destination's semantic type. The destination +//! address is evaluated once, which is required for indexed and dereferenced +//! compound assignments with side effects. + use super::ExprGenEnv; use crate::codegen::types::TypeFlavor; use crate::codegen::{generate_address_ir, wave_type_to_llvm_type}; diff --git a/llvm/src/expression/rvalue/binary.rs b/llvm/src/expression/rvalue/binary.rs index 8623fad7..1ab8a557 100644 --- a/llvm/src/expression/rvalue/binary.rs +++ b/llvm/src/expression/rvalue/binary.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Binary-expression lowering, including numeric inference and pointer offsets. +//! +//! Unsuffixed numeric literals borrow a concrete LLVM type from the surrounding +//! expectation or the opposite operand. Pointer arithmetic is scaled by the +//! inferred pointee type and retains Wave's unchecked, C-like memory contract. + use super::{utils::to_bool, ExprGenEnv}; use crate::codegen::types::{wave_type_to_llvm_type, TypeFlavor}; use inkwell::types::{BasicType, BasicTypeEnum}; @@ -112,6 +118,9 @@ fn gep_with_i64_offset<'ctx, 'a>( tag: &str, ) -> PointerValue<'ctx> { let pointee_ty = infer_ptr_pointee_ty(env, ptr_expr); + // SAFETY: Wave pointer arithmetic is explicitly unchecked. A source program + // must keep an inbounds result within the original allocation (or one past + // it), which is the contract required by LLVM's `inbounds` GEP. unsafe { env.builder .build_in_bounds_gep(pointee_ty, ptr, &[idx_i64], tag) diff --git a/llvm/src/expression/rvalue/calls.rs b/llvm/src/expression/rvalue/calls.rs index be0b712d..cf10ea0e 100644 --- a/llvm/src/expression/rvalue/calls.rs +++ b/llvm/src/expression/rvalue/calls.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Function and method call lowering across Wave and C ABI boundaries. +//! +//! Ordinary Wave calls use source parameter types directly. `extern(c)` calls +//! instead apply the classifier's direct, split, indirect, or `sret` transport +//! plan and attach call-site attributes. Variadic arguments use semantic +//! expression types for C default promotions. + use super::ExprGenEnv; use crate::codegen::abi_c::{ apply_extern_c_callsite_attrs, apply_extern_c_variadic_callsite_attrs, ParamLowering, diff --git a/llvm/src/expression/rvalue/cast.rs b/llvm/src/expression/rvalue/cast.rs index 5036a1e0..2b02918e 100644 --- a/llvm/src/expression/rvalue/cast.rs +++ b/llvm/src/expression/rvalue/cast.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Explicit `as` cast lowering. +//! +//! Casts use the explicit coercion policy, which permits conversions that +//! implicit assignment rejects. Integer literals cast to pointers receive a +//! pointer-width source hint before conversion. + use super::ExprGenEnv; use crate::codegen::types::{wave_type_to_llvm_type, TypeFlavor}; use crate::statement::variable::{coerce_basic_value, CoercionMode}; @@ -29,8 +35,8 @@ pub(crate) fn gen<'ctx, 'a>( TypeFlavor::Value, ); - // Integer literals default to i32 with no context. - // For explicit cast to pointer, prefer i64 source width. + // Integer literals default to i32 without context. A pointer cast needs a + // width capable of carrying the supported 64-bit target addresses. let src_hint = match (expr, dst_ty) { (Expression::Literal(Literal::Int(_)), BasicTypeEnum::PointerType(_)) => { Some(env.context.i64_type().as_basic_type_enum()) diff --git a/llvm/src/expression/rvalue/dispatch.rs b/llvm/src/expression/rvalue/dispatch.rs index d254ec24..dc02d113 100644 --- a/llvm/src/expression/rvalue/dispatch.rs +++ b/llvm/src/expression/rvalue/dispatch.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Exhaustive dispatch from Wave expression nodes to specialized lowerers. +//! +//! New expression variants must be routed here and added to semantic analysis. +//! The expected LLVM type is forwarded only to forms whose value representation +//! may depend on surrounding context. + use super::*; use inkwell::types::BasicTypeEnum; use inkwell::values::BasicValueEnum; diff --git a/llvm/src/expression/rvalue/incdec.rs b/llvm/src/expression/rvalue/incdec.rs index 40602558..f16e5582 100644 --- a/llvm/src/expression/rvalue/incdec.rs +++ b/llvm/src/expression/rvalue/incdec.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Prefix and postfix increment/decrement lowering for assignable expressions. +//! +//! The target address is evaluated once, then the old and new values are kept +//! separate so postfix operations can store the update while returning the old +//! value. Pointer steps are scaled by their recovered Wave pointee type. + use super::ExprGenEnv; use crate::codegen::generate_address_ir; use crate::codegen::types::{wave_type_to_llvm_type, TypeFlavor}; @@ -227,6 +233,9 @@ pub(crate) fn gen<'ctx, 'a>( }; let pointee_ty = infer_ptr_pointee_type(env, target); + // SAFETY: Wave pointer arithmetic is unchecked and requires the + // source pointer and stepped result to satisfy LLVM's inbounds GEP + // contract for the same allocation. let gep = unsafe { env.builder .build_in_bounds_gep(pointee_ty, pv, &[idx], "pincdec") diff --git a/llvm/src/expression/rvalue/index.rs b/llvm/src/expression/rvalue/index.rs index 833595ae..73a979ae 100644 --- a/llvm/src/expression/rvalue/index.rs +++ b/llvm/src/expression/rvalue/index.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Reading an indexed array or pointer element. +//! +//! Address computation is shared with lvalue lowering. Aggregate elements remain +//! addresses so later field/index operations retain their storage identity; +//! scalar elements are loaded immediately. + use super::ExprGenEnv; use crate::codegen::generate_address_and_type_ir; use inkwell::values::{BasicValue, BasicValueEnum}; diff --git a/llvm/src/expression/rvalue/literals.rs b/llvm/src/expression/rvalue/literals.rs index 5c340991..d5c7e5b6 100644 --- a/llvm/src/expression/rvalue/literals.rs +++ b/llvm/src/expression/rvalue/literals.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! LLVM constants and globals for source literals. +//! +//! Unsuffixed numeric literals require an expected type when context determines +//! width or signedness. `null` likewise requires a pointer expectation; codegen +//! does not invent a pointee type for an untyped null literal. + use super::ExprGenEnv; use inkwell::types::{BasicTypeEnum, StringRadix}; use inkwell::values::{BasicValue, BasicValueEnum}; diff --git a/llvm/src/expression/rvalue/mod.rs b/llvm/src/expression/rvalue/mod.rs index 0e2f9366..e582dec8 100644 --- a/llvm/src/expression/rvalue/mod.rs +++ b/llvm/src/expression/rvalue/mod.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Shared environment and entry point for expression value lowering. +//! +//! [`ExprGenEnv`] carries the LLVM construction state plus Wave semantic tables. +//! An optional expected type flows downward to resolve literals, null pointers, +//! aggregates, and ABI-sensitive coercions without reconstructing types from AST +//! shape. + use crate::codegen::abi_c::ExternCInfo; use crate::codegen::VariableInfo; use inkwell::builder::Builder; diff --git a/llvm/src/expression/rvalue/pointers.rs b/llvm/src/expression/rvalue/pointers.rs index 02ae2e7f..4b7c5d63 100644 --- a/llvm/src/expression/rvalue/pointers.rs +++ b/llvm/src/expression/rvalue/pointers.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Address-of and dereference expression lowering. +//! +//! LLVM pointers are opaque, so dereference loads recover their value type from +//! the Wave expression and struct tables. Address-of returns the existing lvalue +//! address and never allocates replacement storage. + use super::ExprGenEnv; use crate::codegen::types::{wave_type_to_llvm_type, TypeFlavor}; use crate::codegen::{generate_address_and_type_ir, generate_address_ir}; diff --git a/llvm/src/expression/rvalue/structs.rs b/llvm/src/expression/rvalue/structs.rs index 93a74916..1ee8cac5 100644 --- a/llvm/src/expression/rvalue/structs.rs +++ b/llvm/src/expression/rvalue/structs.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Struct literal construction and field-value access. +//! +//! Field names are resolved through the declaration-built index map. Aggregate +//! fields remain addresses when required by later lowering; scalar fields are +//! loaded as values. + use super::ExprGenEnv; use crate::codegen::generate_address_and_type_ir; use inkwell::types::{BasicType, BasicTypeEnum}; diff --git a/llvm/src/expression/rvalue/unary.rs b/llvm/src/expression/rvalue/unary.rs index 1d2debf4..4499385d 100644 --- a/llvm/src/expression/rvalue/unary.rs +++ b/llvm/src/expression/rvalue/unary.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Numeric negation, logical negation, and bitwise complement lowering. +//! +//! Logical negation normalizes non-boolean integers by comparing them with zero; +//! bitwise complement preserves the operand width. + use super::ExprGenEnv; use inkwell::types::BasicTypeEnum; use inkwell::values::{BasicValue, BasicValueEnum}; diff --git a/llvm/src/expression/rvalue/utils.rs b/llvm/src/expression/rvalue/utils.rs index f97d590e..02987e3f 100644 --- a/llvm/src/expression/rvalue/utils.rs +++ b/llvm/src/expression/rvalue/utils.rs @@ -10,6 +10,8 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Small value-normalization helpers shared by expression lowerers. + use inkwell::builder::Builder; use inkwell::values::IntValue; use inkwell::IntPredicate; diff --git a/llvm/src/expression/rvalue/variables.rs b/llvm/src/expression/rvalue/variables.rs index 45086b11..752f6f35 100644 --- a/llvm/src/expression/rvalue/variables.rs +++ b/llvm/src/expression/rvalue/variables.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Resolution and loading of constants, locals, and static variables. +//! +//! Arrays evaluate to their storage address rather than an aggregate load, while +//! other variables load using their Wave type. Expected pointer types guide +//! opaque-pointer loads without redefining the variable's semantic type. + use super::ExprGenEnv; use inkwell::types::BasicTypeEnum; use inkwell::values::{BasicValue, BasicValueEnum}; diff --git a/llvm/src/importgen.rs b/llvm/src/importgen.rs index 794d845d..f37532e9 100644 --- a/llvm/src/importgen.rs +++ b/llvm/src/importgen.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compatibility entry point for recursively expanding local imports before codegen. +//! +//! The compiler driver uses the richer parser import expansion that retains +//! source origins and dependency configuration. This helper remains for callers +//! that already provide a parsed entry AST and need local imports only. + use std::collections::HashSet; use std::path::Path; diff --git a/llvm/src/lib.rs b/llvm/src/lib.rs index 3fdb7565..97cb83d4 100644 --- a/llvm/src/lib.rs +++ b/llvm/src/lib.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! LLVM backend for Wave. +//! +//! This crate lowers the verified Wave AST into target-specific LLVM IR, +//! applies ABI classifications, emits requested artifacts, and locates the +//! bundled toolchain components needed by the compiler driver. + // Backend lowering APIs mirror LLVM's explicit context and ABI structures. // Refactor these lints separately from release hardening to avoid ABI regressions. #![allow( @@ -37,8 +43,11 @@ pub mod importgen; pub mod statement; pub mod toolchain; +/// Returns the linked LLVM backend version reported by the LLVM C API. pub fn backend() -> Option { let (mut major, mut minor, mut patch) = (0_u32, 0_u32, 0_u32); + // SAFETY: LLVMGetVersion writes three integers to valid, uniquely borrowed + // stack locations and does not retain their addresses after returning. unsafe { llvm_sys::core::LLVMGetVersion(&mut major, &mut minor, &mut patch); } diff --git a/llvm/src/statement/asm.rs b/llvm/src/statement/asm.rs index 02f92f16..90e40b63 100644 --- a/llvm/src/statement/asm.rs +++ b/llvm/src/statement/asm.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Lowering of inline-assembly statements with inputs and multiple outputs. +//! +//! Target validation and constraint ordering come from [`AsmPlan`]. This module +//! evaluates input expressions, constructs the LLVM call, then stores returned +//! values into variables or memory operands using their recovered Wave types. + use crate::codegen::arch; use crate::codegen::plan::*; use crate::codegen::target::require_supported_target_from_module; diff --git a/llvm/src/statement/assign.rs b/llvm/src/statement/assign.rs index f773d4e0..be05016e 100644 --- a/llvm/src/statement/assign.rs +++ b/llvm/src/statement/assign.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Lowering for the legacy name-based assignment statement node. +//! +//! General lvalue assignment is represented as an expression and handled by +//! `expression::rvalue::assign`. This path accepts only a named mutable variable +//! and rejects constants and immutable bindings. + use crate::codegen::abi_c::ExternCInfo; use crate::codegen::types::TypeFlavor; use crate::codegen::{wave_type_to_llvm_type, VariableInfo}; diff --git a/llvm/src/statement/control.rs b/llvm/src/statement/control.rs index 48149236..d3182e73 100644 --- a/llvm/src/statement/control.rs +++ b/llvm/src/statement/control.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! LLVM lowering for control-flow statements and Wave truthiness. +//! +//! Wave conditions intentionally accept integers, floats, and pointers. Every +//! such value is normalized to an LLVM `i1` here before branches are built. +//! Loop termination analysis distinguishes a break for the current loop from a +//! break nested inside another loop. + use crate::codegen::abi_c::ExternCInfo; use crate::codegen::VariableInfo; use crate::expression::rvalue::generate_expression_ir; @@ -30,6 +37,8 @@ fn truthy_to_i1<'ctx>( v: BasicValueEnum<'ctx>, name: &str, ) -> inkwell::values::IntValue<'ctx> { + // Floating-point truthiness uses ordered comparison: NaN does not compare + // as a non-zero value. Keep this choice explicit when changing semantics. match v { BasicValueEnum::IntValue(iv) => { if iv.get_type().get_bit_width() == 1 { diff --git a/llvm/src/statement/expr_stmt.rs b/llvm/src/statement/expr_stmt.rs index 0e82c7b7..15bceb81 100644 --- a/llvm/src/statement/expr_stmt.rs +++ b/llvm/src/statement/expr_stmt.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Lowering for expressions evaluated only for side effects. +//! +//! The expression still goes through normal value lowering; its result is +//! intentionally discarded by the statement context. + use crate::codegen::abi_c::ExternCInfo; use crate::codegen::VariableInfo; use crate::expression::rvalue::generate_expression_ir; diff --git a/llvm/src/statement/io.rs b/llvm/src/statement/io.rs index ae20ffff..76b1217c 100644 --- a/llvm/src/statement/io.rs +++ b/llvm/src/statement/io.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Lowering of Wave print and input statements to C vararg calls. +//! +//! Format conversion uses Wave semantic types because opaque LLVM pointers do +//! not reveal whether an argument is a C string. `printf` arguments receive C +//! default promotions, while `scanf` arguments must resolve to writable lvalues. + use crate::codegen::abi_c::ExternCInfo; use crate::codegen::types::{wave_type_to_llvm_type, TypeFlavor}; use crate::codegen::{wave_format_to_c, wave_format_to_scanf, VariableInfo}; diff --git a/llvm/src/statement/mod.rs b/llvm/src/statement/mod.rs index 1e8a76ae..e01987a7 100644 --- a/llvm/src/statement/mod.rs +++ b/llvm/src/statement/mod.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Statement dispatcher for LLVM lowering. +//! +//! Specialized modules own each statement family; this module carries shared +//! function state and prevents emission after the current basic block has been +//! terminated. Adding a statement kind requires updating this dispatch as well +//! as semantic validation. + pub mod asm; pub mod assign; pub mod control; @@ -45,6 +52,8 @@ pub fn generate_statement_ir<'ctx>( target_data: &'ctx TargetData, extern_c_info: &HashMap>, ) { + // A return, break, continue, or unconditional branch may have terminated the + // block while walking a source-level list. LLVM rejects a second terminator. if builder .get_insert_block() .is_some_and(|block| block.get_terminator().is_some()) diff --git a/llvm/src/statement/variable.rs b/llvm/src/statement/variable.rs index ac40268c..a8e4c87d 100644 --- a/llvm/src/statement/variable.rs +++ b/llvm/src/statement/variable.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Local variable storage, initialization, and value coercion. +//! +//! Allocations are placed in the function entry block even when declarations +//! appear in nested control flow. Coercion behavior is selected explicitly for +//! implicit assignment, explicit casts, and inline-assembly operands. + use crate::codegen::abi_c::ExternCInfo; use crate::codegen::types::TypeFlavor; use crate::codegen::{wave_type_to_llvm_type, VariableInfo}; diff --git a/llvm/src/toolchain.rs b/llvm/src/toolchain.rs index 93e8c1ac..9fbd742a 100644 --- a/llvm/src/toolchain.rs +++ b/llvm/src/toolchain.rs @@ -10,15 +10,30 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Discovery of CRT objects bundled with Wave distributions. +//! +//! Search order supports explicit overrides, installed compiler layouts, and the +//! repository build tree. This module only locates files; target-specific link +//! planning decides which CRT objects are required. + use std::env; use std::path::{Path, PathBuf}; +/// Finds the first existing Wave-bundled Linux CRT object for a target. +/// +/// Candidate order is significant: explicit environment overrides take +/// precedence over paths relative to the running compiler and the build-time +/// fallback directory. pub fn find_bundled_linux_crt(target: &str, abi: Option<&str>, name: &str) -> Option { bundled_linux_crt_candidates(target, abi, name) .into_iter() .find(|path| path.is_file()) } +/// Returns the highest-priority path where a bundled CRT object is expected. +/// +/// Unlike [`find_bundled_linux_crt`], this function does not require the file +/// to exist. Diagnostics use the result to report the path that was searched. pub fn expected_bundled_linux_crt(target: &str, abi: Option<&str>, name: &str) -> PathBuf { bundled_linux_crt_candidates(target, abi, name) .into_iter() @@ -30,6 +45,8 @@ fn bundled_linux_crt_candidates(target: &str, abi: Option<&str>, name: &str) -> let mut paths = Vec::new(); let relative = crt_relative_path(target, abi, name); + // A file-specific override exists for compatibility with release and CI + // environments that supply only the conventional process entry object. if name == "crt1.o" { if let Ok(path) = env::var("WAVE_LINUX_CRT1_OBJECT") { if !path.trim().is_empty() { @@ -44,6 +61,8 @@ fn bundled_linux_crt_candidates(target: &str, abi: Option<&str>, name: &str) -> } } + // Installed archives place CRT files either beside wavec or below the + // installation prefix. Keep these layouts ahead of the build-tree path. if let Ok(exe) = env::current_exe() { if let Some(dir) = exe.parent() { paths.push(dir.join("crt").join(&relative)); @@ -62,6 +81,8 @@ fn crt_relative_path(target: &str, abi: Option<&str>, name: &str) -> PathBuf { if target == "riscv64-unknown-linux-gnu" { path.push(abi.unwrap_or("lp64d")); } + // Accept only the final component so a caller cannot escape the target CRT + // directory by passing a path instead of an object-file name. path.push(Path::new(name).file_name().unwrap_or_default()); path } diff --git a/src/cli.rs b/src/cli.rs index 8719c765..2f9a2221 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -10,6 +10,13 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! `wavec` command-line parsing, validation, and execution planning. +//! +//! Raw arguments are converted into a `BuildRequest` before compilation +//! starts. Target and output contracts are validated here so the runner receives +//! a coherent request and dry-run output describes the same plan that execution +//! would follow. + use crate::errors::CliError; use crate::flags::{ validate_opt_flag, DebugFlags, DepFlags, DepPackage, LinkFlags, LlvmFlags, WhaleFlags, diff --git a/src/errors.rs b/src/errors.rs index 3eb41f21..8c323fd5 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Errors produced while parsing or executing the `wavec` command line. +//! +//! CLI failures are separate from source diagnostics because they have no Wave +//! source span. Stable `kind` and exit-code mappings are shared by human and JSON +//! output. + use std::fmt; use std::path::PathBuf; diff --git a/src/flags.rs b/src/flags.rs index 8fee895a..281b4ad9 100644 --- a/src/flags.rs +++ b/src/flags.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Typed option groups passed from CLI planning to compiler phases. +//! +//! These structures contain parsed values only. Cross-option contracts such as +//! target CPU, feature, ABI, and output compatibility are validated in the CLI +//! and target resolver before use. + #[derive(Default, Clone, Copy)] pub struct DebugFlags { pub tokens: bool, diff --git a/src/lib.rs b/src/lib.rs index f4131fff..61e65e57 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compiler-driver services shared by the `wavec` binary and integration tools. +//! +//! This crate owns command-line planning, source preparation, diagnostics, and +//! link orchestration. Language parsing lives in the frontend crates, while +//! target-specific lowering lives in the `llvm` crate. + // CLI tables and compiler phase boundaries intentionally favor explicit data. #![allow( clippy::print_literal, diff --git a/src/link_validation/elf.rs b/src/link_validation/elf.rs index 97c8c521..f6bb74bf 100644 --- a/src/link_validation/elf.rs +++ b/src/link_validation/elf.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Minimal read-only ELF and Unix archive metadata inspection. +//! +//! Pre-link validation needs only machine and `e_flags`, so this module avoids a +//! full object-file parser while supporting direct ELF objects plus GNU and BSD +//! archive member naming. It never rewrites linker inputs. + use std::fmt; use std::fs; use std::path::{Path, PathBuf}; @@ -90,7 +96,8 @@ fn inspect_input( } else if bytes.starts_with(AR_MAGIC) { inspect_archive(path, bytes, metadata)?; } - // LLVM bitcode and linker scripts do not carry ELF e_flags. + // LLVM bitcode and linker scripts do not carry ELF e_flags. They remain + // valid linker inputs and are intentionally ignored by metadata validation. Ok(()) } diff --git a/src/link_validation/mod.rs b/src/link_validation/mod.rs index 97205d3f..31a6f3aa 100644 --- a/src/link_validation/mod.rs +++ b/src/link_validation/mod.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Target-specific validation performed before invoking the native linker. +//! +//! Metadata inspection is kept separate from linker command construction so the +//! checks can move to Whale without coupling them to the current external linker. + mod elf; mod riscv; diff --git a/src/link_validation/riscv.rs b/src/link_validation/riscv.rs index 34e7add1..b13f7c4e 100644 --- a/src/link_validation/riscv.rs +++ b/src/link_validation/riscv.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Pre-link RISC-V floating-point ABI compatibility checks. +//! +//! ELF `e_flags` distinguish LP64, LP64F, and LP64D objects. Every RISC-V member +//! discovered in direct objects or archives must agree with the effective Wave +//! target ABI; inputs for other architectures are left to the linker. + use super::elf::{inspect_link_inputs, LinkInputInspectionError}; use std::fmt; @@ -101,6 +107,8 @@ pub fn validate_riscv_link_inputs( target_abi: RiscvFloatAbi, inputs: &[String], ) -> Result<(), AbiValidationError> { + // Inspect every archive member rather than trusting the archive filename: + // one incompatible member is sufficient to make the final link invalid. for metadata in inspect_link_inputs(inputs).map_err(AbiValidationError::Inspection)? { if metadata.machine != EM_RISCV { continue; diff --git a/src/main.rs b/src/main.rs index a7bacbcf..ae53e8ad 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Process entry point for `wavec`. +//! +//! Argument handling lives in the library crate. This binary selects the error +//! renderer, prints usage for usage failures, and preserves the CLI error's +//! stable exit code. + use std::process; fn main() { diff --git a/src/runner.rs b/src/runner.rs index 8e41c88d..6be5e75b 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -10,6 +10,14 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compiler-driver orchestration from source loading through native execution. +//! +//! This module owns user-facing phase boundaries and diagnostics. Frontend work +//! must finish in the order target preprocessing, parsing, import expansion, +//! semantic validation, monomorphization, and concrete-AST validation before an +//! AST reaches LLVM. Backend panics are caught here and translated into Wave +//! diagnostics; lower layers should not duplicate that presentation policy. + use crate::{DebugFlags, DepFlags, LinkFlags, LlvmFlags}; use ::error::*; use ::parser::ast::*; @@ -993,6 +1001,9 @@ fn frontend_prepare_wave_ast( println!("\n===== AST =====\n{:#?}", parsed_ast); } + // Imports are expanded before monomorphization so generic references may + // resolve across source files. The expanded AST retains source ownership + // long enough to report semantic errors against the originating file. let import_config = build_import_config(dep, target); let expanded = match expand_imports_for_codegen(file_path, &code, parsed_ast, &import_config) { Ok(a) => a, @@ -1001,6 +1012,8 @@ fn frontend_prepare_wave_ast( process::exit(1); } }; + // Validate both sides of monomorphization: templates must be semantically + // sound, and generated concrete nodes must satisfy the same language rules. validate_expanded_ast_or_exit(&expanded); let ast = match monomorphize_generics(expanded.ast) { Ok(a) => a, diff --git a/src/std.rs b/src/std.rs index ce4fb52b..d8262cf9 100644 --- a/src/std.rs +++ b/src/std.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Installation and update commands for the separately licensed Wave standard library. +//! +//! Only the repository's `std` subtree is fetched. Its manifest is validated +//! before files are copied into the per-user Wave library directory so an +//! unexpected repository layout is not installed as the standard library. + use crate::errors::CliError; use std::path::{Path, PathBuf}; use std::process::Command; diff --git a/src/version.rs b/src/version.rs index 1ae20e54..1f831d49 100644 --- a/src/version.rs +++ b/src/version.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Compiler version and host operating-system display information. +//! +//! The compiler version comes from Cargo package metadata. OS probing is used +//! only for human-readable diagnostics and falls back cleanly when platform +//! commands or release files are unavailable. + use std::process::Command; const VERSION: &str = env!("CARGO_PKG_VERSION"); diff --git a/utils/src/colorex.rs b/utils/src/colorex.rs index 166b7783..205acd06 100644 --- a/utils/src/colorex.rs +++ b/utils/src/colorex.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Minimal ANSI styling used by command-line diagnostics. +//! +//! All formatting honors the conventional `NO_COLOR`, `CLICOLOR`, and +//! `CLICOLOR_FORCE` environment variables. Styling methods therefore return +//! plain text when color is disabled and never make rendering a requirement. + pub struct Color(u8, u8, u8); fn colors_enabled() -> bool { diff --git a/utils/src/formatx.rs b/utils/src/formatx.rs index 90ec42c6..51eb0c83 100644 --- a/utils/src/formatx.rs +++ b/utils/src/formatx.rs @@ -10,18 +10,17 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. -// utils/formatx.rs -// -// Wave internal format utilities. -// This module replaces regex usage for placeholder detection. -// Supported pattern: `{ ... }` (non-nested, no escape) +//! Lightweight Wave format-placeholder scanning without regular expressions. +//! +//! The supported form is a non-nested `{...}` pair with no escape processing. +//! Unterminated opening braces are ignored rather than counted as placeholders. #[derive(Debug, Clone)] pub struct Placeholder { pub spec: String, } -// "{c}" -> spec="c", "{}" -> spec="" +/// Returns placeholders in source order, trimming the text inside each pair. pub fn parse_placeholders(input: &str) -> Vec { let bytes = input.as_bytes(); let mut i = 0; diff --git a/utils/src/json.rs b/utils/src/json.rs index bd7164bf..ee6b804e 100644 --- a/utils/src/json.rs +++ b/utils/src/json.rs @@ -10,6 +10,12 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Small JSON parser and writer used where a full serialization dependency is unnecessary. +//! +//! Objects preserve insertion order and duplicate keys in their representation; +//! lookup returns the first matching key. Callers that require schema guarantees +//! must validate the parsed tree explicitly. + use std::io; use std::io::Write; diff --git a/utils/src/lib.rs b/utils/src/lib.rs index 43b1cb9a..53519f5c 100644 --- a/utils/src/lib.rs +++ b/utils/src/lib.rs @@ -10,6 +10,11 @@ // SPDX-License-Identifier: MPL-2.0 // AI TRAINING NOTICE: Prohibited without prior written permission. No use for machine learning or generative AI training, fine-tuning, distillation, embedding, or dataset creation. +//! Small dependency-free utilities shared across Wave compiler crates. +//! +//! Keep this crate independent of frontend and backend types so formatting, +//! terminal color, and JSON helpers remain reusable at every compiler layer. + pub mod colorex; pub mod formatx; pub mod json;