# Key Differences Between KCL's AST Evaluator and Fast Evaluator

> Explore the key differences between KCL's AST evaluator and fast evaluator. Understand their distinct approaches to compilation and interpretation for speed and feature completeness.

- Repository: [The KCL Programming Language/kcl](https://github.com/kcl-lang/kcl)
- Tags: internals
- Published: 2026-03-05

---

**The AST evaluator executes a complete compilation pipeline including type checking and schema validation, while the fast evaluator interprets the AST directly to prioritize speed over language feature completeness.**

The KCL programming language (kcl-lang/kcl) provides two distinct execution engines for running configuration code. Understanding the key differences between KCL's AST evaluator and its fast evaluator is essential for choosing the right approach for production deployments versus rapid prototyping scenarios.

## Architectural Overview

KCL implements two fundamentally different execution strategies within its Rust codebase. The **AST evaluator** (`kcl_evaluator::Evaluator`) located in [`crates/evaluator/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/evaluator/src/lib.rs) processes code through a comprehensive compilation pipeline. In contrast, the **fast evaluator** (`FastRunner`) defined in [`crates/runner/src/runner.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/runner/src/runner.rs) provides a lightweight interpretation path controlled by the `fast_eval` boolean flag in `ExecProgramArgs`.

## The AST Evaluator: Full Compilation Pipeline

The AST evaluator represents KCL's production-grade execution engine. Defined at lines 55-68 of [`crates/evaluator/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/evaluator/src/lib.rs), the `Evaluator` struct performs comprehensive semantic analysis before producing results.

The core structure initializes with a reference to the parsed program:

```rust
pub struct Evaluator<'ctx> {
    pub program: &'ctx ast::Program,
    // runtime, scopes, lazy evaluation, schema & rule stacks, etc.
}

```

The execution flow follows a strict pipeline via the `run` method (lines 62-68):

```rust
let modules = self.program.get_modules_for_pkg(kcl_ast::MAIN_PKG);
self.init_scope(kcl_ast::MAIN_PKG);
self.compile_ast_modules(&modules);
Ok(self.plan_globals_to_string())

```

This path executes **parsing → type-checking → schema resolution → rule execution → runtime evaluation**. According to the source code, the evaluator resolves imports, validates schemas, applies constraints, and generates both JSON and YAML results while handling hidden attributes, schema-type paths, and configuration overrides.

## The Fast Evaluator: Direct AST Interpretation

The fast evaluator bypasses the compilation stage entirely. Located in [`crates/runner/src/runner.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/runner/src/runner.rs) at lines 258-262, the `FastRunner` struct interprets the AST directly without semantic analysis.

The mode is controlled by the `fast_eval` boolean field (lines 68-71):

```rust
/// fast_eval denotes directly executing at the AST level to obtain
/// the result without any form of compilation.
#[serde(skip)]
pub fast_eval: bool,

```

When `fast_eval` is set to `true`, the `Runner::run` method instantiates `FastRunner` instead of the full `Evaluator`. The `FastRunner` walks the AST and evaluates expressions immediately, skipping type inference, schema merging, default value filling, and constraint validation.

## Feature Support and Performance Comparison

The key differences between KCL's AST evaluator and its fast evaluator manifest in three critical areas:

**Performance Characteristics**
- **AST Evaluator**: Slower execution due to comprehensive analysis, but guarantees correctness and complete error diagnostics with source-level information
- **Fast Evaluator**: Much faster for simple scripts due to zero compilation overhead, limited to runtime panic reporting only

**Language Feature Support**
- **AST Evaluator**: Full support for schemas, rules, constraints, imports, and complex configuration merging
- **Fast Evaluator**: Limited to basic expressions and statements; ignores schemas, constraints, and import resolution

**Execution Model**
- **AST Evaluator**: Creates a full evaluation context with scopes, lazy evaluation, and schema stacks
- **Fast Evaluator**: Direct interpretation without compilation-stage work or validation

## Practical Usage Examples

### Full Evaluation with the AST Evaluator

Use `Evaluator::new()` for production scenarios requiring complete language semantics:

```rust
use kcl_evaluator::Evaluator;
use kcl_ast::ast::Program;

// Assume `program` is a parsed KCL AST.
let evaluator = Evaluator::new(&program);
let (json, yaml) = evaluator.run().expect("evaluation failed");
println!("JSON:\n{}", json);
println!("YAML:\n{}", yaml);

```

This approach validates all constraints and provides precise error locations referencing exact source positions when validation fails.

### Fast Evaluation via API

Enable fast evaluation by setting `fast_eval: true` in `ExecProgramArgs`:

```rust
use kcl_runner::ExecProgramArgs;

let mut args = ExecProgramArgs::default();
args.k_filename_list = vec!["example.k".into()];
args.fast_eval = true;   // Enable fast path

let result = kcl_runner::run_program(args).map_err_to_result().unwrap();
println!("JSON (fast): {}", result.json_result);

```

### Direct FastRunner Usage

For embedded scenarios, instantiate `FastRunner` directly:

```rust
use kcl_runner::{FastRunner, RunnerOptions};

let options = RunnerOptions {
    fast_eval: true,
    ..Default::default()
};
let fast_runner = FastRunner::new(Some(options));
let result = fast_runner.run().expect("fast run failed");
println!("Result: {}", result.json_result);

```

When using the fast evaluator, scripts containing schema definitions or import statements may produce different output compared to the full evaluator, as these features are not processed.

## Summary

- The **AST evaluator** in [`crates/evaluator/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/evaluator/src/lib.rs) provides production-grade execution with full semantic analysis, type checking, and schema validation through the `Evaluator` struct and its `run` method.
- The **fast evaluator** in [`crates/runner/src/runner.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/runner/src/runner.rs) offers lightweight AST interpretation via `FastRunner` when the `fast_eval` flag is enabled, prioritizing execution speed over feature completeness.
- Use the AST evaluator for production deployments requiring constraint validation, import resolution, and precise error diagnostics pointing to specific source locations.
- Use the fast evaluator for rapid prototyping, REPL-like interactions, or simple scripts where execution speed outweighs the need for schema validation and type checking.
- The execution mode is controlled through the `fast_eval` field in `ExecProgramArgs` (lines 68-71) or by directly instantiating the respective runner struct.

## Frequently Asked Questions

### When should I use the AST evaluator versus the fast evaluator?

Use the **AST evaluator** when running production configuration pipelines that require schema validation, constraint checking, import resolution, and detailed error reporting with source-level diagnostics. Use the **fast evaluator** for development workflows, quick syntax verification, or simple scripts where you prioritize execution speed over strict validation of KCL's advanced features like schemas and rules.

### What features are unavailable in the fast evaluator?

According to the implementation in [`crates/runner/src/runner.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/runner/src/runner.rs), the fast evaluator does not perform type checking, schema default value filling, constraint validation, or import resolution. It evaluates basic expressions and statements only, meaning schemas, rules, and complex configuration merging defined in [`crates/evaluator/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/evaluator/src/lib.rs) are ignored during execution.

### How do I enable fast evaluation in KCL?

You can enable fast evaluation by setting `fast_eval: true` in the `ExecProgramArgs` struct when calling `kcl_runner::run_program()`, or by using the `--fast_eval` (`-K`) CLI flag which propagates through [`crates/cmd/src/lib.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/cmd/src/lib.rs) to the runner configuration. Developers can also instantiate `FastRunner` directly from [`crates/runner/src/runner.rs`](https://github.com/kcl-lang/kcl/blob/main/crates/runner/src/runner.rs) for embedded use cases requiring minimal overhead.

### Does the fast evaluator produce the same output as the AST evaluator?

No. While both return JSON results through `ExecProgramResult`, the fast evaluator produces different output for scripts using schemas, constraints, or imports because it skips the validation and merging stages that occur in the full compilation pipeline. For simple scripts without schema definitions, the output may be identical, but production configurations should always use the AST evaluator to ensure complete semantic correctness.