idlc 0.1.6 → 0.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7afb7419f8d68fe843767795803581f71b8b82f4f160f12620240e26fd959eae
4
- data.tar.gz: 75017626ea863fc6d80db787eb829450ec1b0663520607b547bfa7c5c2be81c7
3
+ metadata.gz: 2fe70767fa4481a7e6085a724b275eb06c92629fdf4408ad2e0f0f815bfb65b1
4
+ data.tar.gz: 9d41295be8e44be071bcfef86af5e5995b596a464ce6c6c91d5510d7818940f4
5
5
  SHA512:
6
- metadata.gz: 718129ce9fca746406948debcf0563ae705f5e0f5e5e8e62bc129d75d2cb9352aa999cb1bb16f3d252d95398c7d2f4debe4af67e9b7d755f9ba9a21848fb977e
7
- data.tar.gz: a6595cf7d2e9ba63a02ae37fe690c8b06f12c7c45bb5badc221ff9e7ad3446caa1cffd0bc8354c4083b5e0ef95511fb11ad8cd71c146d36a63a76740094ea32e
6
+ metadata.gz: 1e291366c4dbfadcbfa2c7a4d3caff30fc3c71c93b1162ede1b2a2e8f1a652a4c17764eaf634434266ba092caef12c7012ffa1b139f85dd48fb10871da574025
7
+ data.tar.gz: a63b1fdc428d772f72d1377d36142afcebbcdd01bed484ffac8229d36072b78130fe14a907f657eff6145941adb3f6a7c21da773e0c899c20165a8d92eb85e75
data/lib/idlc/ast.rb CHANGED
@@ -2967,7 +2967,10 @@ module Idl
2967
2967
 
2968
2968
  value_result = value_try do
2969
2969
  idx_value = idx.value(symtab)
2970
- type_error "Array index (#{idx.text_value} = #{idx_value}) out of range (< #{lhs.type(symtab).width})" if idx_value >= lhs.type(symtab).width
2970
+ lhs_width = lhs.type(symtab).width
2971
+ if lhs_width != :unknown && idx_value >= lhs_width
2972
+ type_error "Array index (#{idx.text_value} = #{idx_value}) out of range (< #{lhs_width})"
2973
+ end
2971
2974
  end
2972
2975
  # OK, doesn't need to be known
2973
2976
 
@@ -4799,27 +4802,12 @@ module Idl
4799
4802
  # @return [Integer] the number of bits needed to represent value in two's complement
4800
4803
  def bits_needed(value, signed)
4801
4804
  if signed
4802
- case value
4803
- when 0
4804
- 1
4805
- when 1
4806
- 2
4807
- else
4808
- if value > 0
4809
- # need bit_legnth plus a sign bit
4810
- bits = value.bit_length + 1
4811
- else
4812
- # need bit_length plus a sign bit, unless value is a power of 2
4813
- if (value.abs & (value.abs - 1)) == 0
4814
- value.bit_length
4815
- else
4816
- value.bit_length + 1
4817
- end
4818
- end
4819
- end
4805
+ # add sign bit
4806
+ value.bit_length + 1
4820
4807
  else
4821
4808
  internal_error "unsigned value is negative" if value < 0
4822
4809
 
4810
+ # 0 needs a single bit; `0.bit_length` returns 0.
4823
4811
  value == 0 ? 1 : value.bit_length
4824
4812
  end
4825
4813
  end
@@ -9388,7 +9376,9 @@ module Idl
9388
9376
 
9389
9377
  sig { params(symtab: SymbolTable).returns(CsrField) }
9390
9378
  def field_def(symtab)
9391
- T.must(csr_obj(symtab).fields.find { |f| f.name == @field_name })
9379
+ field = csr_obj(symtab).fields.find { |f| f.name == @field_name }
9380
+ type_error "#{@field_name} is not a field of CSR[#{csr_name}]" if not field
9381
+ field
9392
9382
  end
9393
9383
 
9394
9384
  sig { params(symtab: SymbolTable).returns(String) }
@@ -20,8 +20,18 @@ module Idl
20
20
  width = forced_type ? forced_type.width : value.bit_length
21
21
  raise "pruning error: attempting to prune an integer with unknown width" unless width.is_a?(Integer)
22
22
  width = 1 if width == 0
23
- v = value <= 512 ? value.to_s : "h#{value.to_s(16)}"
24
- str = "#{width}'#{v}"
23
+
24
+ # negative values must keep an explicit sign marker and their native decimal
25
+ # text; the literal grammar already parses signed negative decimals correctly,
26
+ # while re-encoding as an unsigned magnitude (with no sign marker) silently
27
+ # drops the sign once rendered to C++ (see IntLiteralAst#gen_cpp)
28
+ str =
29
+ if value.is_a?(Integer) && value.negative?
30
+ "#{width}'sd#{value}"
31
+ else
32
+ v = value <= 512 ? value.to_s : "h#{value.to_s(16)}"
33
+ "#{width}'#{v}"
34
+ end
25
35
  Idl::IntLiteralAst.new(str, 0...str.size, str)
26
36
  end
27
37
 
@@ -694,7 +704,10 @@ module Idl
694
704
  def prune(symtab, forced_type: nil)
695
705
  if forced_type
696
706
  raise "pruning error: attempt to force bitwidth when width is unknown" if forced_type.width.nil? || forced_type.width == :unknown
697
- s = "#{forced_type.width}'d#{value(symtab)}"
707
+ v = value(symtab)
708
+ # negative values need an explicit sign marker; without it, the literal
709
+ # re-parses as unsigned and loses its sign once rendered to C++
710
+ s = v.negative? ? "#{forced_type.width}'sd#{v}" : "#{forced_type.width}'d#{v}"
698
711
  IntLiteralAst.new(s, 0...s.size, s)
699
712
  else
700
713
  dup
data/lib/idlc/type.rb CHANGED
@@ -464,6 +464,14 @@ module Idl
464
464
  self
465
465
  end
466
466
 
467
+ sig { params(value: Integer).returns(Integer) }
468
+ def self.unsigned_bits_needed(value)
469
+ raise "unsigned JSON schema integer cannot be negative" if value.negative?
470
+
471
+ value.zero? ? 1 : value.bit_length
472
+ end
473
+ private_class_method :unsigned_bits_needed
474
+
467
475
  # @return [Idl::Type] Type of a scalar
468
476
  # @param schema [Hash] JSON Schema description of a scalar
469
477
  sig { params(schema: T::Hash[String, T.untyped]).returns(T.nilable(Type)) }
@@ -474,9 +482,9 @@ module Idl
474
482
  Type.new(:boolean)
475
483
  when "integer"
476
484
  if schema.key?("enum")
477
- Type.new(:bits, width: schema["enum"].max.bit_length)
485
+ Type.new(:bits, width: schema["enum"].map { |e| unsigned_bits_needed(e) }.max)
478
486
  elsif schema.key?("maximum")
479
- Type.new(:bits, width: schema["maximum"].bit_length)
487
+ Type.new(:bits, width: unsigned_bits_needed(schema["maximum"]))
480
488
  else
481
489
  Type.new(:bits, width: 128)
482
490
  end
@@ -494,7 +502,7 @@ module Idl
494
502
  when TrueClass, FalseClass
495
503
  Type.new(:boolean)
496
504
  when Integer
497
- Type.new(:bits, width: schema["const"].bit_length)
505
+ Type.new(:bits, width: unsigned_bits_needed(schema["const"]))
498
506
  when String
499
507
  Type.new(:string, width: schema["const"].length)
500
508
  else
@@ -507,7 +515,7 @@ module Idl
507
515
  when TrueClass, FalseClass
508
516
  Type.new(:boolean)
509
517
  when Integer
510
- Type.new(:bits, width: schema["enum"].map { |e| e.bit_length }.max)
518
+ Type.new(:bits, width: schema["enum"].map { |e| unsigned_bits_needed(e) }.max)
511
519
  when String
512
520
  Type.new(:string, width: schema["enum"].map { |e| e.length }.max)
513
521
  else
@@ -551,6 +559,27 @@ module Idl
551
559
  end
552
560
  private_class_method :from_json_schema_scalar_type
553
561
 
562
+ sig { params(types: T::Array[Type]).returns(Type) }
563
+ def self.merge_json_schema_scalar_types(types)
564
+ raise "No scalar types" if types.empty?
565
+
566
+ first = types.fetch(0)
567
+ kind = first.kind
568
+ raise "Schema error: Array elements must be the same type" unless types.all? { |t| t.kind == kind }
569
+
570
+ if kind == :bits
571
+ unknown_width_type = types.find { |t| t.width == :unknown }
572
+ return unknown_width_type unless unknown_width_type.nil?
573
+
574
+ Type.new(:bits, width: T.must(types.map(&:width).max))
575
+ else
576
+ raise "Schema error: Array elements must be the same type" unless types.all? { |t| first.equal_to?(t) }
577
+
578
+ first
579
+ end
580
+ end
581
+ private_class_method :merge_json_schema_scalar_types
582
+
554
583
  # @return [Idl::Type] Type of array
555
584
  # @param schema [Hash] JSON Schema description of an array
556
585
  sig { params(schema: T::Hash[String, T.untyped]).returns(Type) }
@@ -566,25 +595,9 @@ module Idl
566
595
  raise "unexpected #{schema}" unless schema["items"].is_a?(Array)
567
596
 
568
597
  # this ia an array with each element specified
569
- sub_type = T.let(nil, T.nilable(Type))
570
- schema["items"].each do |item_schema|
571
- if sub_type.nil?
572
- sub_type = from_json_schema_scalar_type(item_schema)
573
- else
574
- unless sub_type.equal_to?(from_json_schema_scalar_type(item_schema))
575
- raise "Schema error: Array elements must be the same type (#{sub_type} #{from_json_schema_scalar_type(item_schema)}) \n#{schema["items"]}"
576
- end
577
- end
578
- end
579
- if schema.key?("additionalItems")
580
- if sub_type.nil?
581
- sub_type = from_json_schema_scalar_type(schema["additionalItems"])
582
- else
583
- unless sub_type.equal_to?(from_json_schema_scalar_type(schema["additionalItems"]))
584
- raise "Schema error: Array elements must be the same type"
585
- end
586
- end
587
- end
598
+ item_types = schema["items"].map { |item_schema| from_json_schema_scalar_type(item_schema) }
599
+ item_types << from_json_schema_scalar_type(schema["additionalItems"]) if schema.key?("additionalItems")
600
+ sub_type = merge_json_schema_scalar_types(item_types.compact)
588
601
  Type.new(:array, width:, sub_type:)
589
602
  end
590
603
  end
data/lib/idlc/version.rb CHANGED
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Idl
7
7
  class Compiler
8
- def self.version = "0.1.6"
8
+ def self.version = "0.1.8"
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idlc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.6
4
+ version: 0.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Hower
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-08-02 00:00:00.000000000 Z
10
+ date: 2026-09-28 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: activesupport
@@ -369,7 +369,7 @@ licenses:
369
369
  - BSD-3-Clause-Clear
370
370
  metadata:
371
371
  homepage_uri: https://github.com/riscv/riscv-unified-db
372
- mailing_list_uri: https://lists.riscv.org/g/tech-unifieddb
372
+ mailing_list_uri: https://lists.riscv.org/g/sig-unifieddb
373
373
  bug_tracker_uri: https://github.com/riscv/riscv-unified-db/issues
374
374
  rdoc_options: []
375
375
  require_paths: