How the KCL Compiler Pipeline Processes Code from Lexing to Evaluation
The KCL compiler pipeline transforms source code into executable configuration through four distinct stages: lexical analysis in crates/lexer, parsing into an AST in crates/parser, semantic resolution and type checking in crates/sema, and final evaluation in crates/evaluator, all orchestrated by the driver in crates/driver.
The KCL compiler pipeline is the core engine behind the KCL (Kubernetes Configuration Language) project, hosted at kcl-lang/kcl. It converts declarative configuration files into concrete JSON or YAML output through a rigorous multi-stage process. Understanding this pipeline—from raw text tokens to evaluated runtime values—is essential for debugging performance issues, extending the language, or integrating KCL into custom toolchains.
1. Lexical Analysis
The pipeline begins in crates/lexer/src/lib.rs, where the lexer scans source characters and categorizes them into a stream of Token objects.
Key components include:
parse_token_streams(located inlexer/mod.rs): The primary entry point invoked by the parser. It accepts aParseSession, source string, and starting position, returning a vector ofTokeninstances.Cursor(incursor.rs): Manages byte offsets and tracks line/column positions during scanning.TokenKind: An enum defining all lexical categories—identifiers, string literals, numeric literals, punctuation, keywords, and comment tokens.
The lexer performs minimal error recovery; invalid identifiers or malformed literals are flagged with specific token flags (e.g., InvalidIdent) rather than halting compilation.
2. Parsing
The token stream flows into crates/parser/src/lib.rs, where the recursive-descent parser constructs an Abstract Syntax Tree (AST).
The parsing workflow:
- Initialize a
ParseSessioncontaining diagnostics and source-map information. - Create a
Parserinstance viaParser::new(&sess, stream). - Invoke
parse_moduleto generate anast::Modulerepresenting the top-level structure of a KCL file.
The resulting AST captures high-level constructs including import declarations, schema definitions, rule blocks, and configuration expressions. This tree serves as the input for the semantic analysis phase.
3. Semantic Analysis (Sema)
Semantic resolution occurs in crates/sema/src/resolver/mod.rs. The resolver traverses the AST to bind identifiers to definitions, infer types, and validate constraints.
Core responsibilities:
- Name Resolution: Links variable references, schema names, and import paths to their declarations using scope-based symbol tables.
- Type Inference & Checking: Leverages the type system defined in
crates/sema/src/ty/mod.rsto compute concreteTyperepresentations, unify generic parameters, and detect type mismatches. - Constraint Validation: Evaluates
ruleblocks and schema constraints to ensure user-provided values satisfy defined invariants. - Plugin Loading: Processes
kclpluginimports through the plugin subsystem inkcl_sema::plugin.
The output is a resolved program (kcl_sema::Program) containing fully typed and validated definitions ready for execution.
4. Evaluation
The final stage executes the resolved program in crates/evaluator/src/lib.rs. The evaluator interprets the semantic model to produce concrete configuration values.
Key structures:
Context: Maintains runtime state including variable bindings, import caches, and schema instantiation records.Module: Represents an evaluated module containing resolved schemas, functions, and configuration data.Runtime: Executes statements, evaluates expressions, and applies schema defaults and overrides.Value(defined invalue.rs): A unified representation for all KCL runtime values including primitives, lists, dictionaries, and schema instances.
Evaluation produces a value tree that the runtime serializes to JSON or YAML output formats.
5. Driver Orchestration
The crates/driver crate coordinates the entire pipeline. The primary entry point is kcl_driver::run, implemented in crates/driver/src/toolchain.rs.
Orchestration flow:
- Load Files: Initialize a
ParseSessionand load source files. - Parse: Invoke
parse_file_with_sessionto generate the AST. - Resolve: Call
sema::resolver::Resolver::resolveto perform semantic analysis. - Evaluate: Execute
evaluator::run_programto generate runtime values. - Return: Deliver the final value or emit collected diagnostics.
The driver abstracts the complexity of stage management, error propagation, and incremental compilation support.
Code Example: Running the Full Pipeline
You can invoke the KCL compiler pipeline programmatically using the driver API:
use kcl_driver::{run, DriverOptions};
use std::path::PathBuf;
fn main() -> anyhow::Result<()> {
// 1️⃣ Configure driver options (type checking, plugins, etc.)
let opts = DriverOptions::default();
// 2️⃣ Specify the entry KCL file
let entry = PathBuf::from("example.k");
// 3️⃣ Execute the full pipeline: lexer → parser → sema → evaluator
let result = run(&[entry], opts)?;
// 4️⃣ Serialize the evaluated configuration to JSON
let json = serde_json::to_string_pretty(&result.value)?;
println!("{}", json);
Ok(())
}
The run function handles all stages internally, returning a structured result containing the evaluated value and any compilation diagnostics.
Key Source Files
| Stage | File | Description |
|---|---|---|
| Lexing | crates/lexer/src/lib.rs |
Tokenization and lexical analysis |
| Parsing | crates/parser/src/lib.rs |
AST construction from token streams |
| Semantic Analysis | crates/sema/src/resolver/mod.rs |
Name resolution and type checking |
| Type System | crates/sema/src/ty/mod.rs |
Type definitions and inference logic |
| Evaluation | crates/evaluator/src/lib.rs |
Runtime execution and value generation |
| Driver | crates/driver/src/toolchain.rs |
Pipeline orchestration and public API |
These files collectively implement the KCL compiler pipeline, from raw source text to executable configuration output.
Summary
- The KCL compiler pipeline consists of four discrete stages: lexing, parsing, semantic analysis, and evaluation.
- Lexical analysis in
crates/lexerconverts source text into token streams viaparse_token_streams. - Parsing in
crates/parserbuilds an AST usingParser::newandparse_module. - Semantic analysis in
crates/semaresolves names and types throughResolver::resolve, producing a typedProgram. - Evaluation in
crates/evaluatorexecutes the resolved program viarun_program, generating concreteValueobjects. - The driver in
crates/drivercoordinates the entire flow throughkcl_driver::run, providing the primary API for CLI and programmatic usage.
Frequently Asked Questions
What is the entry point for the KCL compiler pipeline?
The primary entry point is kcl_driver::run located in crates/driver/src/toolchain.rs. This function accepts source file paths and driver options, then orchestrates the complete pipeline from lexing through evaluation, returning the final configuration value or compilation errors.
How does the KCL compiler handle type checking?
Type checking occurs during the semantic analysis phase in crates/sema/src/resolver/mod.rs. The Resolver traverses the AST to infer types using the type system defined in crates/sema/src/ty/mod.rs, unifying generic parameters and validating that all expressions conform to their declared schemas before evaluation begins.
What crate handles the final evaluation of KCL code?
The crates/evaluator crate handles final evaluation, with its main interface in crates/evaluator/src/lib.rs. It interprets the resolved semantic model to produce runtime values, executing schema definitions, applying defaults and overrides, and generating the final configuration output that can be serialized to JSON or YAML.
How can I invoke the KCL compiler pipeline programmatically?
You can invoke the pipeline using the driver API by calling kcl_driver::run with a list of entry file paths and DriverOptions. This function abstracts the internal stages—internally calling parse_file_with_session, Resolver::resolve, and evaluator::run_program—and returns a structured result containing the evaluated value and any diagnostics.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →