Class: Ibex::Fix

Inherits:
Object
  • Object
show all
Defined in:
lib/ibex/fix.rb

Overview

Bounded conflict-repair candidate generation and safety evaluation. rubocop:disable Metrics/ClassLength -- candidate generation and its three safety gates share one target identity.

Defined Under Namespace

Classes: BudgetExceeded

Constant Summary collapse

SCHEMA_VERSION =

@rbs! type candidate = { category: String, description: String, source: String?, algorithm: Symbol }

3
CATEGORIES =

: Integer

%w[
  precedence_declaration precedence_override algorithm_change
  mechanical_rewrite
].freeze
ADVICE_CATEGORIES =

: Array

%w[expectation_declaration recovery_quality].freeze
ADVICE_STATEMENT =

: Array

"Advice does not eliminate the selected conflict and is not a verified repair."

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(source, file:, grammar:, automaton:, algorithm:, mode:, state: nil, conflict_index: nil, max_candidates: 32, max_builds: 32, equiv_max_tokens: 8, equiv_max_configurations: 50_000, equiv_samples: 100, verify_max_states: 100_000, verify_max_items: 1_000_000, messages: nil, message_file: nil) ⇒ Fix

rubocop:disable Metrics/ParameterLists



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ibex/fix.rb', line 41

def initialize(source, file:, grammar:, automaton:, algorithm:, mode:, state: nil, conflict_index: nil,
               max_candidates: 32, max_builds: 32, equiv_max_tokens: 8,
               equiv_max_configurations: 50_000, equiv_samples: 100,
               verify_max_states: 100_000, verify_max_items: 1_000_000,
               messages: nil, message_file: nil)
  { max_candidates: max_candidates, max_builds: max_builds, equiv_max_tokens: equiv_max_tokens,
    equiv_max_configurations: equiv_max_configurations, equiv_samples: equiv_samples,
    verify_max_states: verify_max_states, verify_max_items: verify_max_items }.each do |name, value|
    raise ArgumentError, "#{name} must be positive" unless value.positive?
  end

  @source = source
  if source.match?(/^# #{Regexp.escape(BisonImport::STRUCTURAL_STATUS_MARKER)}: incomplete$/)
    raise Ibex::Error,
          "(fix):1:1: cannot propose repairs for a structurally incomplete Bison import"
  end
  @file = file
  @grammar = grammar
  @automaton = automaton
  @algorithm = algorithm
  @mode = mode
  @requested_state = state
  @requested_conflict_index = conflict_index
  @max_candidates = max_candidates
  @max_builds = max_builds
  @equiv_max_tokens = equiv_max_tokens
  @equiv_max_configurations = equiv_max_configurations
  @equiv_samples = equiv_samples
  @verify_max_states = verify_max_states
  @verify_max_items = verify_max_items
  @messages = messages
  @message_file = message_file
  @sources = {}
  @builds = 0
end

Instance Attribute Details

#sourcesObject (readonly)

: Hash[String, String]



33
34
35
# File 'lib/ibex/fix.rb', line 33

def sources
  @sources
end

Instance Method Details

#runObject

Raises:



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/ibex/fix.rb', line 79

def run
  state, index, conflict = select_target
  candidates = candidate_space(conflict)
  advice = advice_space(conflict)
  if candidates.length > @max_candidates
    details = {
      result: "budget_exhausted", phase: "candidate_enumeration",
      bounds: bounds, enumerated_candidates: candidates.length
    }
    raise BudgetExceeded, details
  end

  proposals = [] #: Array[Hash[Symbol, Object?]]
  rejections = [] #: Array[Hash[Symbol, Object?]]
  incomplete = false
  candidates.each do |candidate|
    outcome = evaluate_candidate(candidate, conflict)
    outcome_status = outcome.fetch(:status) #: String
    if outcome_status == "safe"
      proposals << proposal(candidate, outcome, conflict, proposals.length + 1)
    else
      outcome_reason = outcome.fetch(:reason) #: String
      incomplete ||= %w[equivalence_budget_exhausted verification_budget_exhausted]
                     .include?(outcome_reason)
      rejections << rejection(candidate, outcome)
    end
  end
  report = report_for(state, index, conflict, candidates, proposals, rejections, advice)
  raise BudgetExceeded, report.merge(result: "budget_exhausted", phase: "candidate_evaluation") if incomplete

  report
end