Skip to the content.

Home › Developer Docs › Aether Interpreter Documentation

Aether Interpreter Documentation

Overview

Tree-walking interpreter that executes AST nodes directly without compilation.

Location: src/interpreter/
Status: ✅ Complete (134 unit tests, ~559 integration tests passing)

Components

src/interpreter/
  mod.rs              public re-exports
  value.rs            Value enum (all runtime types)
  environment.rs      variable scoping + RuntimeError enum
  builtins.rs         built-in functions (print, len, http_get, )
  stdlib.rs           embedded stdlib loader
  io_pool.rs          I/O thread pool + HttpOptions
  event_loop.rs       EventLoopQueue for callback-based async
  evaluator/
    mod.rs            Evaluator struct, constructors, public API
    expressions.rs    eval_expr, eval_index, eval_slice, await_value
    statements.rs     exec_stmt_internal (all Stmt variants)
    functions.rs      eval_call, call_value, exec_async_body, try_submit_io_task
    members.rs        eval_member, eval_method_call (collections + structs)
    modules.rs        load_module, import resolution
    operators.rs      eval_unary, eval_binary, arithmetic, comparison

Value Types

pub enum Value {
    Int(i64),
    Float(f64),
    String(Rc<String>),     // Rc for cheap clone / GC
    Bool(bool),
    Null,
    Array(Rc<Vec<Value>>),  // Rc for cheap clone / GC
    Dict(Rc<Vec<(Value, Value)>>),  // insertion-ordered, key: string/int/bool
    Set(Rc<HashSet<Value>>),
    Function {
        params: Vec<String>,
        body: Rc<Stmt>,
        closure: Rc<Environment>,
    },
    AsyncFunction {
        params: Vec<String>,
        body: Rc<Stmt>,
        closure: Rc<Environment>,
    },
    BuiltinFn { name: String, arity: usize, func: BuiltinFn },
    Module { name: String, members: Rc<HashMap<String, Value>> },
    StructDef { name: String, fields: Vec<String>, methods: MethodMap },
    Instance {
        type_name: String,
        fields: Rc<RefCell<HashMap<String, Value>>>,
        methods: MethodMap,
    },
    Iterator(Rc<RefCell<IteratorState>>),
    Promise(Rc<RefCell<PromiseState>>),
    ErrorVal { message: String, stack_trace: String },
    FileLines(Rc<RefCell<FileIterState>>),
}

GC: Rc-based reference counting

See GC_DESIGN.md for details.

Evaluator Struct

pub struct Evaluator {
    pub environment: Environment,
    call_depth: usize,
    max_call_depth: usize,           // from AETHER_CALL_DEPTH (default 100)
    module_cache: HashMap<String, Environment>,
    loading_stack: Vec<String>,      // circular import detection
    pub current_file: Option<PathBuf>,
    pub(crate) io_pool: Option<Arc<IoPool>>,
    pub(crate) event_loop_queue: EventLoopQueue,
    pub(crate) event_loop_timeout: Option<f64>,  // from AETHER_EVENT_LOOP_TIMEOUT
    pub current_line: usize,
    pub(crate) call_stack: Vec<StackFrame>,      // for stack traces
}

Constructors

Constructor Use case
Evaluator::new() Full interpreter with stdlib
Evaluator::new_without_stdlib() Fast test initialization (~760× faster)

Main Methods

Environment

pub struct Environment {
    values: HashMap<String, Value>,
    parent: Option<Box<Environment>>,
}

Operations: define(name, value), get(name), set(name, value), with_parent(env)

Block-scoped with lexical scope chain. Function closures capture Rc<Environment>.

Runtime Errors

pub enum RuntimeError {
    UndefinedVariable(String),
    TypeError { expected: String, got: String },
    DivisionByZero,
    IndexOutOfBounds { index: i64, length: usize },
    InvalidOperation(String),
    ArityMismatch { expected: usize, got: usize },
    StackOverflow { depth: usize, limit: usize },
    Thrown(String),  // user throw — caught by TryCatch
}

Implemented Features

Expressions

Statements

Usage

use aether::interpreter::Evaluator;

let mut eval = Evaluator::new();
eval.execute_program(&program.statements)?;
eval.call_main()?;

For tests (no stdlib overhead):

let mut eval = Evaluator::new_without_stdlib();

Last Updated: 2026-04-29
Status: Complete


← Parser    Garbage Collection →