Stream < EmptyObject {

Patterns < EmptyObject {
  Base < Common::Patterns::Base { }

  End  < Base {
    construct: Constructions::End.new
  }
  Item < Base { var checks
    construct: Constructions::Item.new(checks: checks)
  }
}

Constructions < EmptyObject {
  Base < Common::Constructions::Base { }

  End  < Base { }
  Item < Base { var checks }
}

Constructions << {
  End << { bytecode: |g| {
    # Just verify the index is NOT within range
    g.push_subject; g.send(:size, 0)
      g.push_idx
    g.send(:">", 1)
    g.goto_if_true(g.overall_fail)
  }}

  Item << { bytecode: |g| {
    many_checks = checks.size > 1
    local_fail  = g.overall_fail
    if(many_checks) { local_fail = g.new_label }

    # First, verify the index is within range
    g.push_subject; g.send(:size, 0)
      g.push_idx
    g.send(:">", 1)
    g.goto_if_false(g.overall_fail)

    checks.empty? || (
      # Retrieve the item
      g.push_subject_at_idx

      # Try each check on the item until one fails
      checks.each |method, args, result| {
        if(many_checks) { g.dup_top }

        # Run the given method (or other check) with the given args (if applicable) 
        :self.equal?(method) &? (
          # Do nothing; let the self pass through to result checking.
        ) ?? (method.is_a?(Symbol) &? (
          args.each |arg| { g.push_literal_or_array(arg) }
          g.send(method, args.size)
        ) ?? (method.is_a?(Proc) &? (
          code = method.block.compiled_code
          g.push_literal(code) # TODO: add a move_up instruction and avoid all of these swap_stacks
            g.swap_stack; g.push_literal(code.name)             # name
            g.swap_stack; g.push_cpath_top; g.find_const(:Myco) # module
            g.swap_stack                                        # receiver (the item)
            g.push_literal_array(args)                          # args
            g.push_nil                                          # block
          g.send(:invoke, 5)
        ) ?? (
          raise("Unknown type of check method: "method"")
        )))

        # Compare the result of the check with the given expected result 
        null.equal?(result) &? (
          g.goto_if_not_nil(local_fail)
        ) ?? ((false.equal?(result) || true.equal?(result) ||
               result.is_a?(Symbol) || result.is_a?(Fixnum)) &? (
          g.push_literal(result)
          g.goto_if_not_equal(local_fail)
        ) ?? (
          g.push_literal_or_array(result)
          g.send(:"==", 1)
          g.goto_if_false(local_fail)
        ))
      }

      if(many_checks) {
        local_done = g.new_label
        g.pop # The dup'd subject_at_idx
        g.goto(local_done)

        local_fail.set!
        g.pop # The dup'd subject_at_idx
        g.goto(g.overall_fail)

        local_done.set!
      }
    )

    g.meta_push_1
    g.increment_idx
  }}
}

}