// src/lisp/vlm/MetacircularEval.ts
// THE METACIRCULAR EVALUATOR - A LISP interpreter written IN LISP
//
// This is the "brain" that travels with the message. It's ~80 lines of LISP
// that can evaluate any LISP expression using only bootstrap primitives.
//
// Environment representation: association list [["name", value], ...]
//
// The key insight: this code travels WITH every message. The bootstrap node
// only needs to know how to run letrec + the 7 primitives. Everything else
// (lambda semantics, let, etc.) is defined BY this traveling interpreter.

import type { SExpr } from '../SExpr';

export const METACIRCULAR_EVAL: SExpr = [
  'letrec', [
    // === ENVIRONMENT HELPERS ===

    // lookup: find a variable in the environment (association list)
    // Returns the value if found, or the name itself if not found (for primitives)
    ['lookup', ['lambda', ['name', 'env'],
      ['if', ['null?', 'env'],
        'name',  // Not found - return name itself (might be a primitive)
        ['if', ['eq?', ['car', ['car', 'env']], 'name'],
          ['cadr', ['car', 'env']],  // Found it
          ['lookup', 'name', ['cdr', 'env']]]]]],  // Keep looking

    // extend-env: add bindings to environment
    // params and vals are parallel lists
    ['extend-env', ['lambda', ['params', 'vals', 'env'],
      ['if', ['null?', 'params'],
        'env',
        ['cons',
          ['list', ['car', 'params'], ['car', 'vals']],
          ['extend-env', ['cdr', 'params'], ['cdr', 'vals'], 'env']]]]],

    // === LIST EVALUATION ===

    // evlis: evaluate a list of expressions
    ['evlis', ['lambda', ['exprs', 'env'],
      ['if', ['null?', 'exprs'],
        ['quote', []],
        ['cons',
          ['mceval', ['car', 'exprs'], 'env'],
          ['evlis', ['cdr', 'exprs'], 'env']]]]],

    // === FUNCTION APPLICATION ===

    // apply-fn: apply either a closure or a primitive
    ['apply-fn', ['lambda', ['fn', 'args'],
      ['if', ['and', ['pair?', 'fn'], ['eq?', ['car', 'fn'], ['quote', 'closure']]],
        // It's a closure - extend env and eval body
        ['mceval',
          ['caddr', 'fn'],   // body
          ['extend-env',
            ['cadr', 'fn'],  // params
            'args',
            ['cadddr', 'fn']]],  // captured env
        // It's a primitive - use bootstrap's apply
        ['apply', 'fn', 'args']]]],

    // === THE MAIN EVALUATOR ===

    ['mceval', ['lambda', ['e', 'env'],
      ['cond',
        // Self-evaluating: numbers
        [['number?', 'e'], 'e'],

        // Self-evaluating: booleans
        [['boolean?', 'e'], 'e'],

        // Self-evaluating: null
        [['null?', 'e'], 'e'],

        // Variable lookup: strings -> check environment
        [['string?', 'e'],
          ['lookup', 'e', 'env']],

        // Not a list? Return as-is (atoms)
        [['atom?', 'e'], 'e'],

        // QUOTE - return unevaluated
        [['eq?', ['car', 'e'], ['quote', 'quote']],
          ['cadr', 'e']],

        // IF - conditional
        [['eq?', ['car', 'e'], ['quote', 'if']],
          ['if', ['mceval', ['cadr', 'e'], 'env'],
            ['mceval', ['caddr', 'e'], 'env'],
            ['mceval', ['cadddr', 'e'], 'env']]],

        // LAMBDA - create closure: [closure, params, body, env]
        [['eq?', ['car', 'e'], ['quote', 'lambda']],
          ['list',
            ['quote', 'closure'],
            ['cadr', 'e'],   // params
            ['caddr', 'e'],  // body
            'env']],         // capture environment

        // Function/Primitive application
        ['else',
          ['apply-fn',
            ['mceval', ['car', 'e'], 'env'],
            ['evlis', ['cdr', 'e'], 'env']]]]]]
  ],

  // Entry point: evaluate expression with empty environment
  ['mceval', 'e', ['quote', []]]
];

/**
 * Get the metacircular evaluator as a callable expression
 * Wraps it to take expression as input 'e'
 */
export function getMetacircularEval(): SExpr {
  return METACIRCULAR_EVAL;
}
