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 ⇒ Object
readonly
Returns the value of attribute data.
-
#name ⇒ Object
readonly
Returns the value of attribute name.
-
#spec_data ⇒ Object
readonly
Returns the value of attribute spec_data.
-
#spec_path ⇒ Object
readonly
Returns the value of attribute spec_path.
Instance Method Summary collapse
-
#defined_by_condition ⇒ Object
Return configuration conditions that enable this spec.
-
#exists_in_cfg?(cfg_arch) ⇒ Boolean
Check if this non-ISA spec should be included in the given configuration.
-
#extract_prose_statements(include_sections: true) ⇒ Object
Extract all prose statements from description and sections, tagging their source.
-
#initialize(name, data) ⇒ NonIsaSpecification
constructor
A new instance of NonIsaSpecification.
- #load_spec_data ⇒ Object
-
#long_name ⇒ Object
Get the long name for display.
-
#optional_in_cfg?(cfg_arch) ⇒ Boolean
Check if this spec is optional in the given configuration.
-
#references ⇒ Object
Get the array of reference hashes.
-
#render_for_cfg(cfg_arch, base_level: 3, normative: true, non_normative: true) ⇒ Object
Configuration-aware rendering.
-
#sections ⇒ Object
Get the array of section hashes.
-
#spec_description ⇒ Object
Get the main description prose array or string.
-
#to_asciidoc(base_level: 3, normative: true, non_normative: true, when_callback: nil) ⇒ Object
Render the full specification as AsciiDoc, including description, sections, and references.
-
#valid? ⇒ Boolean
Returns true if the spec is valid and has required fields.
-
#validate_prose_ids ⇒ Object
Validate all prose statement IDs and conventions for this spec.
-
#version ⇒ Object
Get the version if available.
Constructor Details
#initialize(name, data) ⇒ NonIsaSpecification
Returns a new instance of NonIsaSpecification.
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 ⇒ Object (readonly)
Returns the value of attribute data.
31 32 33 |
# File 'lib/udb/obj/non_isa_specification.rb', line 31 def data @data end |
#name ⇒ Object (readonly)
Returns the value of attribute name.
28 29 30 |
# File 'lib/udb/obj/non_isa_specification.rb', line 28 def name @name end |
#spec_data ⇒ Object (readonly)
Returns the value of attribute spec_data.
37 38 39 |
# File 'lib/udb/obj/non_isa_specification.rb', line 37 def spec_data @spec_data end |
#spec_path ⇒ Object (readonly)
Returns the value of attribute spec_path.
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 ⇒ Object
Return configuration conditions that enable this spec
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
Check if this non-ISA spec should be included in the given configuration
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) ⇒ Object
Extract all prose statements from description and sections, tagging their source.
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 ⇒ Object
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 ⇒ Object
Get the long name for display
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
Check if this spec is optional in the given configuration
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 ⇒ Object
Get the array of reference hashes.
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) ⇒ Object
Configuration-aware rendering
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 ⇒ Object
Get the array of section hashes.
96 97 98 |
# File 'lib/udb/obj/non_isa_specification.rb', line 96 def sections @spec_data&.dig('sections') || [] end |
#spec_description ⇒ Object
Get the main description prose array or string.
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) ⇒ Object
Render the full specification as AsciiDoc, including description, sections, and references.
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
Returns true if the spec is valid and has required fields.
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 ⇒ Object
Validate all prose statement IDs and conventions for this spec.
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 ⇒ Object
Get the version if available
84 85 86 |
# File 'lib/udb/obj/non_isa_specification.rb', line 84 def version @spec_data&.dig('version') end |