Class: Ibex::Diff
- Inherits:
-
Object
- Object
- Ibex::Diff
- Defined in:
- lib/ibex/diff.rb,
sig/ibex/diff.rbs
Overview
Deterministic grammar and automaton change classification.
Instance Method Summary collapse
- #change(before, after) ⇒ Hash[Symbol, Integer]
- #classify(before, after) ⇒ Hash[Symbol, Object?]
- #conflict_identity(grammar, conflict) ⇒ String
- #conflict_records(automaton) ⇒ Hash[String, Object?]
-
#initialize(before, after) ⇒ Diff
constructor
A new instance of Diff.
- #numeric_metrics ⇒ Hash[Symbol, Hash[Symbol, Integer]]
- #production_record(grammar, production) ⇒ Hash[Symbol, Object?]
- #production_shape(grammar, id) ⇒ String
- #rule_records(grammar) ⇒ Hash[String, Object?]
- #symbol_name(grammar, id) ⇒ String
- #symbol_records(grammar) ⇒ Hash[String, Object?]
- #to_h ⇒ Hash[Symbol, Object?]
- #warning_records(grammar) ⇒ Hash[String, Object?]
Constructor Details
#initialize(before, after) ⇒ Diff
Returns a new instance of Diff.
8 9 10 11 |
# File 'lib/ibex/diff.rb', line 8 def initialize(before, after) @before = before @after = after end |
Instance Method Details
#change(before, after) ⇒ Hash[Symbol, Integer]
136 137 138 |
# File 'lib/ibex/diff.rb', line 136 def change(before, after) { before: before, after: after, delta: after - before } end |
#classify(before, after) ⇒ Hash[Symbol, Object?]
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/ibex/diff.rb', line 28 def classify(before, after) common = before.keys & after.keys { added: (after.keys - before.keys).sort.map { |key| { id: key, value: after.fetch(key) } }, removed: (before.keys - after.keys).sort.map { |key| { id: key, value: before.fetch(key) } }, changed: common.sort.filter_map do |key| next if before.fetch(key) == after.fetch(key) { id: key, before: before.fetch(key), after: after.fetch(key) } end } end |
#conflict_identity(grammar, conflict) ⇒ String
88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ibex/diff.rb', line 88 def conflict_identity(grammar, conflict) if conflict.fetch(:type).to_sym == :shift_reduce shift_reduce = conflict #: IR::shift_reduce_conflict reduction = production_shape(grammar, shift_reduce.fetch(:reduce)) "shift_reduce:#{shift_reduce.fetch(:symbol)}:#{reduction}" else reduce_reduce = conflict #: IR::reduce_reduce_conflict reductions = reduce_reduce.fetch(:reductions).map { |id| production_shape(grammar, id) }.sort "reduce_reduce:#{reduce_reduce.fetch(:symbol)}:#{reductions.join('|')}" end end |
#conflict_records(automaton) ⇒ Hash[String, Object?]
76 77 78 79 80 81 82 83 84 85 |
# File 'lib/ibex/diff.rb', line 76 def conflict_records(automaton) grouped = Hash.new { |hash, key| hash[key] = [] } #: Hash[String, Array[Object?]] automaton.states.each do |state| state.conflicts.each do |conflict| identity = conflict_identity(automaton.grammar, conflict) grouped[identity] << conflict.fetch(:resolution) end end grouped.transform_values { |resolutions| resolutions.sort_by(&:inspect) } end |
#numeric_metrics ⇒ Hash[Symbol, Hash[Symbol, Integer]]
125 126 127 128 129 130 131 132 133 |
# File 'lib/ibex/diff.rb', line 125 def numeric_metrics { states: change(@before.states.length, @after.states.length), productions: change(@before.grammar.productions.length, @after.grammar.productions.length), warnings: change(@before.grammar.warnings.length, @after.grammar.warnings.length), shift_reduce: change(@before.conflict_summary.fetch(:sr), @after.conflict_summary.fetch(:sr)), reduce_reduce: change(@before.conflict_summary.fetch(:rr), @after.conflict_summary.fetch(:rr)) } end |
#production_record(grammar, production) ⇒ Hash[Symbol, Object?]
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/ibex/diff.rb', line 64 def production_record(grammar, production) precedence = production.precedence_override { rhs: production.rhs.map { |id| symbol_name(grammar, id) }, precedence: precedence && symbol_name(grammar, precedence), node: production.node && { name: production.node.fetch(:name), fields: production.node.fetch(:fields) } } end |
#production_shape(grammar, id) ⇒ String
101 102 103 104 105 106 |
# File 'lib/ibex/diff.rb', line 101 def production_shape(grammar, id) production = grammar.productions.fetch(id) lhs = symbol_name(grammar, production.lhs) rhs = production.rhs.map { |symbol| symbol_name(grammar, symbol) } "#{lhs}->#{rhs.join(' ')}" end |
#rule_records(grammar) ⇒ Hash[String, Object?]
55 56 57 58 59 60 61 |
# File 'lib/ibex/diff.rb', line 55 def rule_records(grammar) grammar.productions.group_by(&:lhs).to_h do |lhs, productions| name = grammar.symbol_by_id(lhs)&.name || lhs.to_s alternatives = productions.map { |production| production_record(grammar, production) } [name, alternatives] end end |
#symbol_name(grammar, id) ⇒ String
109 110 111 |
# File 'lib/ibex/diff.rb', line 109 def symbol_name(grammar, id) grammar.symbol_by_id(id)&.name || id.to_s end |
#symbol_records(grammar) ⇒ Hash[String, Object?]
42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/ibex/diff.rb', line 42 def symbol_records(grammar) grammar.symbols.to_h do |symbol| [ symbol.name, { kind: symbol.kind, reserved: symbol.reserved, display_name: symbol.display_name, semantic_type: symbol.semantic_type, precedence: symbol.precedence } ] end end |
#to_h ⇒ Hash[Symbol, Object?]
14 15 16 17 18 19 20 21 22 23 |
# File 'lib/ibex/diff.rb', line 14 def to_h { ibex_report: "diff", schema_version: 1, symbols: classify(symbol_records(@before.grammar), symbol_records(@after.grammar)), rules: classify(rule_records(@before.grammar), rule_records(@after.grammar)), conflicts: classify(conflict_records(@before), conflict_records(@after)), warnings: classify(warning_records(@before.grammar), warning_records(@after.grammar)), metrics: numeric_metrics } end |
#warning_records(grammar) ⇒ Hash[String, Object?]
114 115 116 117 118 119 120 121 122 |
# File 'lib/ibex/diff.rb', line 114 def warning_records(grammar) grouped = Hash.new { |hash, key| hash[key] = [] } #: Hash[String, Array[Object?]] grammar.warnings.each do |warning| value = warning.except(:loc) identity = [warning.fetch(:type), value.except(:message).inspect].join(":") grouped[identity] << value end grouped.transform_values { |values| values.sort_by(&:inspect) } end |