Module: Optimize::Demo::Claude::Validator

Defined in:
lib/optimize/demo/claude/validator.rb

Overview

Structural validator for IR::Function instruction streams coming back from the “gag pass” (LLM rewrite). Checks that every instruction has a known opcode and the arity matches the YARV operand schema.

Class Method Summary collapse

Class Method Details

.semantic(envelope, cases:) ⇒ Array<String>

Encode the envelope, load it as an iseq, run it (which defines any top-level methods), then evaluate each case in TOPLEVEL_BINDING and compare against the expected value with ==.

A rewrite must preserve behavior across every case, not just one —otherwise Claude happily table-looks-up a single expected value and calls it a day. Callers pass as many cases as are needed to catch that shortcut (multiple inputs covering the domain of interest).

Parameters:

  • envelope (IR::Function)

    a root-level function (as returned by Optimize::Codec.decode) with any mutations already spliced in.

  • cases (Array<Array(String, Object)>)

    one or more

    entry_source, expected

    pairs. ‘entry_source` is evaluated in

    TOPLEVEL_BINDING after the iseq is loaded.

Returns:

  • (Array<String>)

    empty on success; otherwise one error per failing case (plus at most one loader/runtime error if the iseq couldn’t be loaded at all).

Raises:

  • (ArgumentError)


81
82
83
84
85
# File 'lib/optimize/demo/claude/validator.rb', line 81

def semantic(envelope, cases:)
  raise ArgumentError, "cases must not be empty" if cases.empty?

  run_cases(envelope, cases)
end

.structural(function) ⇒ Array<String>

Returns one human-readable error per problematic instruction; empty when the stream is structurally valid.

Parameters:

Returns:

  • (Array<String>)

    one human-readable error per problematic instruction; empty when the stream is structurally valid.



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/optimize/demo/claude/validator.rb', line 18

def structural(function)
  errors = []
  function.instructions.each_with_index do |insn, idx|
    op_types = Serializer::OPCODE_OPERAND_TYPES[insn.opcode]
    if op_types.nil?
      errors << "instruction #{idx}: unknown opcode :#{insn.opcode}"
      next
    end
    expected = op_types.size
    actual = insn.operands.size
    if expected != actual
      errors << "instruction #{idx}: opcode :#{insn.opcode} expects #{expected} operand(s), got #{actual}"
    end
  end
  errors.concat(stack_discipline_errors(function)) if errors.empty?
  errors
end