//! Bytecode compiler: lowers `crate::ast::Program` into a `Chunk` of
//! instructions plus the supporting compile-time tables (slot maps, format
//! templates, schema cache).
//!
//! All compile-time-only helpers live here too: `is_pure_expr` /
//! `contains_type_literal` (used to decide whether an expression can be
//! evaluated without entering the VM) and the `fold_type` /
//! `interned_scalar_schema` machinery (used to
//! convert `TypeExpr` AST nodes into JSON-Schema-shaped `Value` literals
//! at compile time).

use std::cell::RefCell;
use std::rc::Rc;
use std::sync::{Arc, OnceLock};

use rustc_hash::FxHashMap;
use smallvec::SmallVec;

use crate::artifact::CompiledModuleContext;
use crate::ast::{
    AssignPathStep, AssignTarget, BinaryOp, Expr, LabelMetadata, ProcessStartExpr, Program,
    TypeExpr, UnaryOp,
};
use crate::lexer::Span;
use crate::tracking::{LashlangAstPath, LashlangExecutionContext, LashlangExecutionSite};

use super::record::{Symbol, intern_symbol, lookup_symbol, record_with_capacity, symbol_name};
use super::schema::{ValidationPlan, compile_schema_value};
use super::{
    Chunk, CompileStats, CompiledAggregateAwaitShape, CompiledAssignPath, CompiledAssignPathStep,
    CompiledFormatTemplate, CompiledResourceOperationBatch, CompiledResourceOperationBatchLeaf,
    Instruction, IntrinsicOp, LASH_HOST_REQUIREMENTS_REF_KEY, LASH_MODULE_REF_KEY,
    LASH_PROCESS_NAME_KEY, LASH_PROCESS_REF_KEY, LASH_PROCESS_VALUE_KEY, LASH_TYPE_KEY, Name,
    Value, as_number, compile_format_template, eval_binary_values, execute_integer_div_builtin,
    execute_len_direct, execute_range_builtin, is_comparison_binary_op, is_numeric_binary_op,
    is_truthy, read_field_direct, read_index_direct, transient_name, unwrap_type_value,
};

pub(crate) struct Compiler {
    module_context: Option<CompiledModuleContext>,
    lashlang_execution: Option<LashlangExecutionCompileContext>,
    code: Vec<Instruction>,
    spans: Vec<Option<Span>>,
    constants: Vec<Value>,
    names: Vec<Name>,
    name_lookup: FxHashMap<Symbol, usize>,
    slots: Rc<RefCell<SlotTable>>,
    key_lists: Vec<Box<[usize]>>,
    format_templates: Vec<CompiledFormatTemplate>,
    compiled_schemas: Vec<ValidationPlan>,
    assign_paths: Vec<CompiledAssignPath>,
    resource_operation_batches: Vec<CompiledResourceOperationBatch>,
    compile_stats: Rc<RefCell<CompileStats>>,
    const_slots: Vec<Option<Value>>,
    loop_contexts: Vec<LoopContext>,
}

struct LashlangExecutionCompileContext {
    context: LashlangExecutionContext,
    paths: FxHashMap<usize, LashlangAstPath>,
    sites: Vec<Option<LashlangExecutionSite>>,
}

struct LoopContext {
    continue_target: usize,
    break_jumps: SmallVec<[usize; 4]>,
}

#[derive(Default)]
struct SlotTable {
    names: Vec<Name>,
    lookup: FxHashMap<Symbol, usize>,
}

include!("compiler/entry.rs");
include!("compiler/expr.rs");
include!("compiler/effects.rs");
include!("compiler/helpers.rs");
