Class: Udb::NonIsaSpecification
- Inherits:
-
Object
- Object
- Udb::NonIsaSpecification
- Extended by:
- T::Sig
- Includes:
- Kernel
- Defined in:
- lib/udb/obj/non_isa_specification.rb
Overview
Clean non-ISA specification object that handles YAML-based specifications
Instance Attribute Summary collapse
- #data ⇒ Hash{String => T.untyped} readonly
- #name ⇒ String readonly
- #spec_data ⇒ Hash{String => T.untyped}? readonly
- #spec_path ⇒ Pathname? readonly
Instance Method Summary collapse
- #defined_by_condition ⇒ T.untyped
-
#exists_in_cfg?(cfg_arch) ⇒ Boolean
Configuration methods.
- #extract_prose_statements(include_sections: true) ⇒ Array<Hash{String, Symbol => T.untyped}>
- #initialize(name, data) constructor
-
#load_spec_data
Core spec data loading and validation.
- #long_name ⇒ String
- #optional_in_cfg?(cfg_arch) ⇒ Boolean
- #references ⇒ Array<Hash{String, Symbol => T.untyped}>
-
#render_for_cfg(cfg_arch, base_level: 3, normative: true, non_normative: true) ⇒ String
Rendering methods.
- #sections ⇒ Array<Hash{String, Symbol => T.untyped}>
- #spec_description ⇒ T.untyped
- #to_asciidoc(base_level: 3, normative: true, non_normative: true, when_callback: nil) ⇒ String
- #valid? ⇒ Boolean
-
#validate_prose_ids ⇒ Array<String>
Validation methods.
- #version ⇒ String?
Constructor Details
#initialize(name, data)
40 41 42 43 44 45 46 |
# File 'lib/udb/obj/non_isa_specification.rb', line 40 def initialize(name, data) @name = name @data = data.dup @spec_data = nil @spec_path = nil load_spec_data end |
Instance Attribute Details
#data ⇒ Hash{String => T.untyped} (readonly)
31 32 33 |
# File 'lib/udb/obj/non_isa_specification.rb', line 31 def data @data end |
#name ⇒ String (readonly)
28 29 30 |
# File 'lib/udb/obj/non_isa_specification.rb', line 28 def name @name end |
#spec_data ⇒ Hash{String => T.untyped}? (readonly)
37 38 39 |
# File 'lib/udb/obj/non_isa_specification.rb', line 37 def spec_data @spec_data end |
#spec_path ⇒ Pathname? (readonly)
34 35 36 |
# File 'lib/udb/obj/non_isa_specification.rb', line 34 def spec_path @spec_path end |
Instance Method Details
#defined_by_condition ⇒ T.untyped
136 137 138 139 140 141 142 143 144 |
# File 'lib/udb/obj/non_isa_specification.rb', line 136 def defined_by_condition when_condition = @data['when()'] || @spec_data&.dig('when()') return OpenStruct.new(to_asciidoc: "Always included") if when_condition.nil? # Convert condition to human-readable description OpenStruct.new( to_asciidoc: "When #{when_condition}" ) end |
#exists_in_cfg?(cfg_arch) ⇒ Boolean
Configuration methods
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/udb/obj/non_isa_specification.rb', line 109 def exists_in_cfg?(cfg_arch) return false unless valid? # Check configuration conditions if present when_condition = @data['when()'] || @spec_data&.dig('when()') return true if when_condition.nil? # Evaluate condition against cfg_arch # For now, simple string matching - could be enhanced with expression evaluation case when_condition when String # Basic string matching for now cfg_arch.param_values.any? { |k, v| when_condition.include?(k.to_s) } else true end end |
#extract_prose_statements(include_sections: true) ⇒ Array<Hash{String, Symbol => T.untyped}>
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 |
# File 'lib/udb/obj/non_isa_specification.rb', line 177 def extract_prose_statements(include_sections: true) statements = [] # Extract from description if spec_description.is_a?(Array) spec_description.each_with_index { |stmt, i| statements << stmt.merge(source: "description[#{i}]") if stmt.is_a?(Hash) } end # Extract from sections if include_sections sections.each_with_index do |section, section_idx| next unless section['content'].is_a?(Array) section['content'].each_with_index do |stmt, stmt_idx| statements << stmt.merge(source: "sections[#{section_idx}].content[#{stmt_idx}]") if stmt.is_a?(Hash) end end end statements end |
#load_spec_data
This method returns an undefined value.
Core spec data loading and validation
50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/udb/obj/non_isa_specification.rb', line 50 def load_spec_data base_path = Pathname.new(__dir__).parent.parent.parent.parent.parent.parent / "spec/custom/non_isa" @spec_path = base_path / "#{name}.yaml" return unless @spec_path.exist? begin @spec_data = YAML.safe_load_file(@spec_path, permitted_classes: []) rescue Psych::SyntaxError => e raise NonIsaSpecificationLoadError, "YAML syntax error in #{@spec_path}: #{e.}" rescue => e raise NonIsaSpecificationLoadError, "Failed to load #{@spec_path}: #{e.}" end end |
#long_name ⇒ String
75 76 77 78 79 80 |
# File 'lib/udb/obj/non_isa_specification.rb', line 75 def long_name return @data['long_name'] if @data['long_name'] return @spec_data['long_name'] if @spec_data&.dig('long_name') return @spec_data['name'] if @spec_data&.dig('name') name.split('_').map(&:capitalize).join(' ') end |
#optional_in_cfg?(cfg_arch) ⇒ Boolean
129 130 131 132 |
# File 'lib/udb/obj/non_isa_specification.rb', line 129 def optional_in_cfg?(cfg_arch) # Non-ISA specs are generally optional unless marked as mandatory !(@data['mandatory'] == true || @spec_data&.dig('mandatory') == true) end |
#references ⇒ Array<Hash{String, Symbol => T.untyped}>
102 103 104 |
# File 'lib/udb/obj/non_isa_specification.rb', line 102 def references @spec_data&.dig('references') || [] end |
#render_for_cfg(cfg_arch, base_level: 3, normative: true, non_normative: true) ⇒ String
Rendering methods
205 206 207 208 209 210 211 212 213 214 |
# File 'lib/udb/obj/non_isa_specification.rb', line 205 def render_for_cfg(cfg_arch, base_level: 3, normative: true, non_normative: true) return "" unless exists_in_cfg?(cfg_arch) to_asciidoc( base_level: base_level, normative: normative, non_normative: non_normative, when_callback: create_when_callback(cfg_arch) ) end |
#sections ⇒ Array<Hash{String, Symbol => T.untyped}>
96 97 98 |
# File 'lib/udb/obj/non_isa_specification.rb', line 96 def sections @spec_data&.dig('sections') || [] end |
#spec_description ⇒ T.untyped
90 91 92 |
# File 'lib/udb/obj/non_isa_specification.rb', line 90 def spec_description @spec_data&.dig('description') end |
#to_asciidoc(base_level: 3, normative: true, non_normative: true, when_callback: nil) ⇒ String
225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/udb/obj/non_isa_specification.rb', line 225 def to_asciidoc(base_level: 3, normative: true, non_normative: true, when_callback: nil) return create_fallback_content(base_level) unless valid? content = [] # Add main description prose desc_content = render_structured_prose(spec_description, normative: normative, non_normative: non_normative, when_callback: when_callback) content << desc_content if desc_content && !desc_content.empty? content << "" # Process all sections content.concat(render_sections(base_level, normative, non_normative, when_callback)) # Add references section if present content.concat(render_references(base_level)) unless references.empty? content.join("\n") end |
#valid? ⇒ Boolean
66 67 68 69 70 71 |
# File 'lib/udb/obj/non_isa_specification.rb', line 66 def valid? !@spec_data.nil? && @spec_data['kind'] == 'non-isa specification' && !@spec_data['name'].nil? && !@spec_data['description'].nil? end |
#validate_prose_ids ⇒ Array<String>
Validation methods
149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'lib/udb/obj/non_isa_specification.rb', line 149 def validate_prose_ids return [] unless valid? issues = [] statements = extract_prose_statements statements.each do |stmt| next unless stmt['id'] id = stmt['id'] source = stmt[:source] || 'unknown' # Check ID format according to prose-schema conventions unless valid_id_format?(id) issues << "Invalid ID format '#{id}' in #{source}: must be lowercase with underscores/hyphens only" end # Check for non-ISA specification naming convention unless valid_id_naming?(id) issues << "ID '#{id}' in #{source} should start with '#{name.downcase}-' for non-ISA specifications" end end # Check for duplicate IDs issues.concat(find_duplicate_ids(statements)) issues end |
#version ⇒ String?
84 85 86 |
# File 'lib/udb/obj/non_isa_specification.rb', line 84 def version @spec_data&.dig('version') end |