idlc 0.1.1 → 0.1.2

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: 4562703a6d610aa163c7ed288acc6ceb5b3f1a58198b0989b077e18956058af7
4
- data.tar.gz: 7172094fef52add65e52f13beb00cb7ccca624af104e785296578d4506c48f4c
3
+ metadata.gz: eef72fdf692691fc5fc0d5d25692cebbfc832fb8517108cfde54954b265a8bd1
4
+ data.tar.gz: 6d54d42e8301d4db0b2be560713314b2e60dda0c615531fd39fbeacc68bec1c7
5
5
  SHA512:
6
- metadata.gz: bc2d2eaacc3da4b47dca354364927ae43463dff4d8a47e635932d36f6b2e09cac4b7be28bfa98131a06e8b89e969e8c8abb9eea9af0eb862e07e3516988c5b39
7
- data.tar.gz: adfd751e70c16cae7ae4ee364af403adf38cfd3eddf7b17287b5819402f96452584d362ee75b88323cd06eebbd3889ca1f1394d7d5134fdf9cecb840b5aea810
6
+ metadata.gz: 0ebc4d54d6bbbd90cd7b3f2001d4e58e46b765893fd63d6058ef8537e2f8fbc5cec65e87a4bf181273d2ac9af49aefa7b951480adef6f286c3b1db76886139ca
7
+ data.tar.gz: 0b21382974ac68f7e3de24e0114a4d8613375d6cacbcac24bb8e60a0fe46058b1a03aa0615e93026591ca1a2298c924a34e79e506b8434a11cb0d2b71b154575
data/lib/idlc/ast.rb CHANGED
@@ -461,9 +461,6 @@ module Idl
461
461
  # This is also an opportunity to pre-calculate anything that only needs global symbols
462
462
  #
463
463
  # @param global_symtab [SymbolTable] Symbol table with global scope populated
464
-
465
-
466
- # @!macro freeze_tree
467
464
  sig { params(global_symtab: SymbolTable).returns(AstNode) }
468
465
  def freeze_tree(global_symtab)
469
466
  return self if frozen?
@@ -508,9 +505,6 @@ module Idl
508
505
  sig { abstract.returns(String) }
509
506
  def to_idl; end
510
507
 
511
- sig { overridable.returns(String) }
512
- def to_idl_verbose = to_idl
513
-
514
508
  # return yaml to indicate where the node comes from
515
509
  # the retrun value will be:
516
510
  # file: <path to input file (or nil if input was given as a string)>
@@ -2184,49 +2178,50 @@ module Idl
2184
2178
  class BitfieldDefinitionAst < AstNode
2185
2179
  include Declaration
2186
2180
 
2181
+ class Memo < T::Struct
2182
+ prop :type, T.nilable(Type)
2183
+ prop :element_names, T.nilable(T::Array[String])
2184
+ prop :element_ranges, T.nilable(T::Hash[SymbolTable, T::Array[T::Range[Integer]]]), default: {}
2185
+ end
2186
+
2187
2187
  sig { override.params(symtab: SymbolTable).returns(T::Boolean) }
2188
2188
  def const_eval?(symtab) = true
2189
2189
 
2190
+ sig { params(input: T.nilable(String), interval: T.nilable(T::Range[Integer]), name: T.any(BuiltinTypeNameAst, UserTypeNameAst), size: IntLiteralAst, fields: T::Array[BitfieldFieldDefinitionAst]).void }
2190
2191
  def initialize(input, interval, name, size, fields)
2191
2192
  super(input, interval, [name, size] + fields)
2192
2193
 
2193
2194
  @name = name
2194
2195
  @size = size
2195
2196
  @fields = fields
2197
+ @memo = Memo.new
2196
2198
  end
2197
2199
 
2198
- # @!macro freeze_tree
2199
- def freeze_tree(global_symtab)
2200
- return if frozen?
2201
-
2202
- type(global_symtab)
2203
-
2204
- @children.each { |child| child.freeze_tree(global_symtab) }
2205
-
2206
- freeze
2207
- end
2208
-
2209
- # @return [Integer] The number of bits in the Bitfield
2200
+ # @return The number of bits in the Bitfield
2201
+ sig { params(symtab: SymbolTable).returns(Integer) }
2210
2202
  def size(symtab)
2211
2203
  @size.value(symtab)
2212
2204
  end
2213
2205
 
2214
- # @return [Array<String>] Array of all element names, in the same order as those from {#element_ranges}
2206
+ # @return Array of all element names, in the same order as those from {#element_ranges}
2207
+ sig { returns(T::Array[String]) }
2215
2208
  def element_names
2216
- return @element_names unless @element_names.nil?
2209
+ return @memo.element_names unless @memo.element_names.nil?
2217
2210
 
2218
- @element_names = @fields.map(&:name)
2211
+ @memo.element_names = @fields.map(&:name)
2219
2212
  end
2220
2213
 
2221
2214
  # @return [Array<Range>]
2222
2215
  # Array of all element ranges, in the same order as those from {#element_names}.
2216
+ sig { params(symtab: SymbolTable).returns(T::Array[T::Range[Integer]]) }
2223
2217
  def element_ranges(symtab)
2224
- return @element_ranges unless @element_ranges.nil?
2218
+ return @memo.element_ranges[symtab] unless @memo.element_ranges[symtab].nil?
2225
2219
 
2226
- @element_ranges = @fields.map { |f| f.range(symtab) }
2220
+ @memo.element_ranges[symtab] = @fields.map { |f| f.range(symtab) }
2227
2221
  end
2228
2222
 
2229
2223
  # @!macro type_check
2224
+ sig { override.params(symtab: SymbolTable, strict: T::Boolean).void }
2230
2225
  def type_check(symtab, strict:)
2231
2226
  type_error "Cannot use reserved word '#{name}' as user-defined type name" if ReservedWords::RESERVED.include?(name)
2232
2227
 
@@ -2242,20 +2237,21 @@ module Idl
2242
2237
  end
2243
2238
 
2244
2239
  # @!macro add_symbol
2240
+ sig { override.params(symtab: SymbolTable).void }
2245
2241
  def add_symbol(symtab)
2246
2242
  internal_error "All Bitfields should be declared at global scope" unless symtab.levels == 1
2247
2243
 
2248
2244
  t = type(symtab)
2249
- internal_error "Type is nil" if t.nil?
2250
2245
 
2251
2246
  symtab.add!(name, t)
2252
2247
  end
2253
2248
 
2254
2249
  # @!macro type_no_args
2250
+ sig { params(symtab: SymbolTable).returns(Type) }
2255
2251
  def type(symtab)
2256
- return @type unless @type.nil?
2252
+ return @memo.type unless @memo.type.nil?
2257
2253
 
2258
- @type = BitfieldType.new(
2254
+ @memo.type = BitfieldType.new(
2259
2255
  name,
2260
2256
  @size.value(symtab),
2261
2257
  element_names,
@@ -2264,9 +2260,11 @@ module Idl
2264
2260
  end
2265
2261
 
2266
2262
  # @return [String] bitfield name
2263
+ sig { returns(String) }
2267
2264
  def name = @name.text_value
2268
2265
 
2269
2266
  # @!macro value_no_args
2267
+ sig { params(_symtab: SymbolTable).returns(ValueRbType) }
2270
2268
  def value(_symtab) = raise AstNode::InternalError, "Bitfield definitions have no value"
2271
2269
 
2272
2270
  # @!macro to_idl
@@ -2289,7 +2287,7 @@ module Idl
2289
2287
  "source" => source_yaml
2290
2288
  }
2291
2289
 
2292
- sig { params(yaml: T::Hash[String, T.untyped], source_mapper: T::Hash[String, String]).returns(AstNode) }
2290
+ sig { override.params(yaml: T::Hash[String, T.untyped], source_mapper: T::Hash[String, String]).returns(AstNode) }
2293
2291
  def self.from_h(yaml, source_mapper)
2294
2292
  raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "bitfield_decl"
2295
2293
 
@@ -2297,8 +2295,8 @@ module Idl
2297
2295
  interval = interval_from_source_yaml(yaml.fetch("source"))
2298
2296
  BitfieldDefinitionAst.new(
2299
2297
  input, interval,
2300
- AstNode.from_h(yaml.fetch("name"), source_mapper),
2301
- AstNode.from_h(yaml.fetch("size"), source_mapper),
2298
+ T.cast(AstNode.from_h(yaml.fetch("name"), source_mapper), T.any(BuiltinTypeNameAst, UserTypeNameAst)),
2299
+ T.cast(AstNode.from_h(yaml.fetch("size"), source_mapper), IntLiteralAst),
2302
2300
  yaml.fetch("fields").map { |f| AstNode.from_h(f, source_mapper) }
2303
2301
  )
2304
2302
  end
@@ -6938,6 +6936,10 @@ module Idl
6938
6936
  # * U64 (Bits<64>)
6939
6937
  class BuiltinTypeNameAst < AstNode
6940
6938
 
6939
+ class Memo < T::Struct
6940
+ prop :bits_type, T::Hash[SymbolTable, T.nilable(Type)], default: {}
6941
+ end
6942
+
6941
6943
  sig { override.params(symtab: SymbolTable).returns(T::Boolean) }
6942
6944
  def const_eval?(symtab) = (@type_name == "bits") ? bits_expression.const_eval?(symtab) : true
6943
6945
 
@@ -6950,6 +6952,7 @@ module Idl
6950
6952
  super(input, interval, [bits_expression])
6951
6953
  end
6952
6954
  @type_name = type_name
6955
+ @memo = Memo.new
6953
6956
  end
6954
6957
 
6955
6958
  # @!macro type_check
@@ -6970,21 +6973,19 @@ module Idl
6970
6973
  end
6971
6974
  end
6972
6975
 
6973
- def freeze_tree(symtab)
6974
- return if frozen?
6975
-
6976
- if @type_name == "Bits"
6977
- # precalculate size if possible
6976
+ sig { params(symtab: SymbolTable).returns(Type) }
6977
+ def bits_type(symtab)
6978
+ @memo.bits_type[symtab] ||=
6978
6979
  begin
6979
- value_try do
6980
- @bits_type = Type.new(:bits, width: bits_expression.value(symtab))
6980
+ t = T.let(nil, T.nilable(Type))
6981
+ value_result = value_try do
6982
+ t = Type.new(:bits, width: bits_expression.value(symtab))
6983
+ end
6984
+ value_else(value_result) do
6985
+ t = Type.new(:bits, width: :unknown, width_ast: bits_expression)
6981
6986
  end
6982
- rescue TypeError
6983
- # ok, probably using a parameter
6987
+ T.must(t)
6984
6988
  end
6985
- bits_expression&.freeze_tree(symtab)
6986
- end
6987
- freeze
6988
6989
  end
6989
6990
 
6990
6991
  # @!macro type
@@ -7008,14 +7009,7 @@ module Idl
7008
7009
  when "String"
7009
7010
  StringType
7010
7011
  when "Bits"
7011
- return @bits_type unless @bits_type.nil?
7012
-
7013
- value_result = value_try do
7014
- return Type.new(:bits, width: bits_expression.value(symtab))
7015
- end
7016
- value_else(value_result) do
7017
- return Type.new(:bits, width: :unknown, width_ast: bits_expression)
7018
- end
7012
+ bits_type(symtab)
7019
7013
  else
7020
7014
  internal_error "TODO: #{text_value}"
7021
7015
  end
@@ -7241,6 +7235,13 @@ module Idl
7241
7235
  class IntLiteralAst < AstNode
7242
7236
  include Rvalue
7243
7237
 
7238
+ class Memo < T::Struct
7239
+ prop :type, T.nilable(Type)
7240
+ prop :width, T.nilable(T.any(Integer, Symbol))
7241
+ prop :value, T.nilable(T.any(Integer, UnknownLiteral))
7242
+ prop :unsigned_value, T.nilable(T.any(Integer, UnknownLiteral))
7243
+ end
7244
+
7244
7245
  sig { override.params(symtab: SymbolTable).returns(T::Boolean) }
7245
7246
  def const_eval?(symtab) = true
7246
7247
 
@@ -7248,19 +7249,11 @@ module Idl
7248
7249
  def initialize(input, interval, text)
7249
7250
  @text = text
7250
7251
  super(input, interval, EMPTY_ARRAY)
7252
+ @memo = Memo.new
7251
7253
  end
7252
7254
 
7253
7255
  def text_value = @text
7254
7256
 
7255
- def freeze_tree(global_symtab)
7256
- return if frozen?
7257
-
7258
- # initialize the cached objects
7259
- type(global_symtab)
7260
- value(global_symtab)
7261
- freeze
7262
- end
7263
-
7264
7257
  # @!macro type_check
7265
7258
  def type_check(symtab, strict:)
7266
7259
  if text_value.delete("_") =~ /^((MXLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
@@ -7279,7 +7272,7 @@ module Idl
7279
7272
 
7280
7273
  # @!macro type
7281
7274
  def type(symtab)
7282
- return @type unless @type.nil?
7275
+ return @memo.type unless @memo.type.nil?
7283
7276
 
7284
7277
  case text_value.delete("_")
7285
7278
  when /^((MXLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
@@ -7295,7 +7288,7 @@ module Idl
7295
7288
 
7296
7289
  qualifiers = signed == "s" ? [:signed, :const] : [:const]
7297
7290
  qualifiers << :known unless T.must(value).include?("x")
7298
- @type =
7291
+ @memo.type =
7299
7292
  if width == :unknown
7300
7293
  Type.new(:bits, width:, max_width: 64, qualifiers:)
7301
7294
  else
@@ -7306,20 +7299,20 @@ module Idl
7306
7299
  signed = ::Regexp.last_match(3)
7307
7300
 
7308
7301
  qualifiers = signed == "s" ? [:signed, :const, :known] : [:const, :known]
7309
- @type = Type.new(:bits, width: width(symtab), qualifiers:)
7302
+ @memo.type = Type.new(:bits, width: width(symtab), qualifiers:)
7310
7303
  when /^([0-9]*)(s?)$/
7311
7304
  # basic decimal
7312
7305
  signed = ::Regexp.last_match(2)
7313
7306
 
7314
7307
  qualifiers = signed == "s" ? [:signed, :const, :known] : [:const, :known]
7315
- @type = Type.new(:bits, width: width(symtab), qualifiers:)
7308
+ @memo.type = Type.new(:bits, width: width(symtab), qualifiers:)
7316
7309
  else
7317
7310
  internal_error "Unhandled int value '#{text_value}'"
7318
7311
  end
7319
7312
  end
7320
7313
 
7321
7314
  def width(symtab)
7322
- return @width unless @width.nil?
7315
+ return @memo.width unless @memo.width.nil?
7323
7316
 
7324
7317
  text_value_no_underscores = text_value.delete("_")
7325
7318
 
@@ -7336,21 +7329,21 @@ module Idl
7336
7329
  else
7337
7330
  width = width.to_i
7338
7331
  end
7339
- @width = width
7332
+ @memo.width = width
7340
7333
  when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/
7341
7334
  signed = ::Regexp.last_match(3)
7342
7335
 
7343
7336
  width = signed == "s" ? value(symtab).bit_length + 1 : value(symtab).bit_length
7344
7337
  width = 1 if width.zero? # happens when the literal is '0'
7345
7338
 
7346
- @width = width
7339
+ @memo.width = width
7347
7340
  when /^([0-9]*)(s?)$/
7348
7341
  signed = ::Regexp.last_match(3)
7349
7342
 
7350
7343
  width = signed == "s" ? value(symtab).bit_length + 1 : value(symtab).bit_length
7351
7344
  width = 1 if width.zero? # happens when the literal is '0'
7352
7345
 
7353
- @width = width
7346
+ @memo.width = width
7354
7347
  else
7355
7348
  internal_error "No match on int literal"
7356
7349
  end
@@ -7358,7 +7351,7 @@ module Idl
7358
7351
 
7359
7352
  # @!macro value
7360
7353
  def value(symtab)
7361
- return @value unless @value.nil?
7354
+ return @memo.value unless @memo.value.nil?
7362
7355
 
7363
7356
  if text_value.delete("_") =~ /^((MXLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
7364
7357
  # verilog-style literal
@@ -7396,18 +7389,18 @@ module Idl
7396
7389
  end
7397
7390
  end
7398
7391
 
7399
- @value = v
7392
+ @memo.value = v
7400
7393
  else
7401
- @value = unsigned_value
7394
+ @memo.value = unsigned_value
7402
7395
  end
7403
7396
  end
7404
7397
 
7405
7398
 
7406
7399
  # @return [Integer] the unsigned value of this literal (i.e., treating it as unsigned even if the signed specifier is present)
7407
7400
  def unsigned_value
7408
- return @unsigned_value unless @unsigned_value.nil?
7401
+ return @memo.unsigned_value unless @memo.unsigned_value.nil?
7409
7402
 
7410
- @unsigned_value =
7403
+ @memo.unsigned_value =
7411
7404
  case text_value.delete("_")
7412
7405
  when /^((MXLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/
7413
7406
  # verilog-style literal
@@ -7487,15 +7480,6 @@ module Idl
7487
7480
  sig { override.returns(String) }
7488
7481
  def to_idl = text_value
7489
7482
 
7490
- sig { override.returns(String) }
7491
- def to_idl_verbose
7492
- if @width == :unknown
7493
- "MXLEN'#{@type.signed? ? 's' : ''}d#{unsigned_value}"
7494
- else
7495
- "#{@width}'#{@type.signed? ? 's' : ''}d#{unsigned_value}"
7496
- end
7497
- end
7498
-
7499
7483
  sig { returns(T::Boolean) }
7500
7484
  def signed?
7501
7485
  case text_value.delete("_")
@@ -9284,15 +9268,6 @@ module Idl
9284
9268
  @memo = Memo.new
9285
9269
  end
9286
9270
 
9287
- def freeze_tree(symtab)
9288
- return if frozen?
9289
-
9290
- type_error "CSR '#{@csr_name}' is not defined" unless symtab.csr?(@csr_name)
9291
-
9292
- @children.each { |child| child.freeze_tree(symtab) }
9293
- freeze
9294
- end
9295
-
9296
9271
  # @!macro type
9297
9272
  def type(symtab) = @memo.type ||= CsrType.new(csr_def(symtab))
9298
9273
 
@@ -265,6 +265,9 @@ module Idl
265
265
  symtab.restore_values(snapshot)
266
266
  symtab.pop
267
267
  end
268
+ # Nullify any outer-scope variable assigned in the loop body, since we
269
+ # don't know how many iterations ran (or if any ran at all)
270
+ stmts.each { |stmt| stmt.nullify_assignments(symtab) }
268
271
  new_loop
269
272
  end
270
273
  end
@@ -357,7 +360,7 @@ module Idl
357
360
  pruned_action = action.prune(symtab)
358
361
 
359
362
  new_stmt = StatementAst.new(input, interval, pruned_action)
360
- pruned_action.freeze_tree(symtab) unless pruned_action.frozen?
363
+ # pruned_action.freeze_tree(symtab) unless pruned_action.frozen?
361
364
 
362
365
  pruned_action.add_symbol(symtab) if pruned_action.is_a?(Declaration)
363
366
  # action#prune already handles symtab update (execute)
data/lib/idlc/type.rb CHANGED
@@ -65,7 +65,7 @@ module Idl
65
65
  if @kind == :array
66
66
  T.must(@sub_type).runtime?
67
67
  else
68
- @kind == :bits && @width == :unknown
68
+ @kind == :bits && !@width.is_a?(Integer)
69
69
  end
70
70
  end
71
71
 
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.1"
8
+ def self.version = "0.1.2"
9
9
  end
10
10
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: idlc
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Derek Hower
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-17 00:00:00.000000000 Z
11
+ date: 2026-03-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport