Class: Idl::IntLiteralAst
- Includes:
- Rvalue
- Defined in:
- lib/idl/ast.rb
Overview
represents an integer literal
Instance Method Summary collapse
- #freeze_tree(global_symtab) ⇒ Object
-
#initialize(input, interval) ⇒ IntLiteralAst
constructor
A new instance of IntLiteralAst.
-
#to_idl ⇒ String
Return valid IDL representation of the node (and its subtree).
-
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
-
#type_check(symtab) ⇒ void
type check this node and all children.
-
#unsigned_value ⇒ Integer
The unsigned value of this literal (i.e., treating it as unsigned even if the signed specifier is present).
-
#value(symtab) ⇒ Object
Return the compile-time-known value of the node.
-
#values(symtab) ⇒ Array<Integer>, ...
included
from Rvalue
Return a complete list of possible compile-time-known values of the node, or raise a ValueError if the full list cannot be determined.
- #width(symtab) ⇒ Object
Constructor Details
#initialize(input, interval) ⇒ IntLiteralAst
Returns a new instance of IntLiteralAst.
4321 4322 4323 |
# File 'lib/idl/ast.rb', line 4321 def initialize(input, interval) super(input, interval, EMPTY_ARRAY) end |
Instance Method Details
#freeze_tree(global_symtab) ⇒ Object
4325 4326 4327 4328 4329 4330 4331 4332 |
# File 'lib/idl/ast.rb', line 4325 def freeze_tree(global_symtab) return if frozen? # initialize the cached objects type(global_symtab) value(global_symtab) freeze end |
#to_idl ⇒ String
Return valid IDL representation of the node (and its subtree)
4518 |
# File 'lib/idl/ast.rb', line 4518 def to_idl = text_value |
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
Should not be called until #type_check is called with the same arguments
4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 |
# File 'lib/idl/ast.rb', line 4351 def type(symtab) return @type unless @type.nil? case text_value.delete("_") when /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/ # verilog-style literal signed = ::Regexp.last_match(4) width = width(symtab) unless width == :unknown type_error("integer width must be positive (is #{width})") unless width.is_a?(Integer) && width.positive? end qualifiers = signed == "s" ? [:signed, :const] : [:const] @type = Type.new(:bits, width:, qualifiers:) when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/ # C++-style literal signed = ::Regexp.last_match(3) qualifiers = signed == "s" ? [:signed, :const] : [:const] @type = Type.new(:bits, width: width(symtab), qualifiers:) when /^([0-9]*)(s?)$/ # basic decimal signed = ::Regexp.last_match(2) qualifiers = signed == "s" ? [:signed, :const] : [:const] @type = Type.new(:bits, width: width(symtab), qualifiers:) else internal_error "Unhandled int value" end end |
#type_check(symtab) ⇒ void
4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 |
# File 'lib/idl/ast.rb', line 4335 def type_check(symtab) if text_value.delete("_") =~ /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/ # verilog-style literal width = ::Regexp.last_match(1) value_text = ::Regexp.last_match(6) if width.nil? || width == "XLEN" width = symtab.mxlen.nil? ? 32 : symtab.mxlen # 32 is the min width, which is what we care about here end # ensure we actually have enough bits to represent the value type_error("#{value_text} cannot be represented in #{width} bits") if unsigned_value.bit_length > width.to_i end end |
#unsigned_value ⇒ Integer
Returns the unsigned value of this literal (i.e., treating it as unsigned even if the signed specifier is present).
4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 |
# File 'lib/idl/ast.rb', line 4465 def unsigned_value return @unsigned_value unless @unsigned_value.nil? @unsigned_value = case text_value.delete("_") when /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/ # verilog-style literal radix_id = ::Regexp.last_match(5) value = ::Regexp.last_match(6) radix_id = "d" if radix_id.empty? case radix_id when "b" value.to_i(2) when "o" value.to_i(8) when "d" value.to_i(10) when "h" value.to_i(16) end when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/ # C++-style literal radix_id = ::Regexp.last_match(1) value = ::Regexp.last_match(2) radix_id = "o" if radix_id.empty? # @unsigned_value = case radix_id when "b" value.to_i(2) when "o" value.to_i(8) when "d" value.to_i(10) when "x" value.to_i(16) end when /^([0-9]*)(s?)$/ # basic decimal value = ::Regexp.last_match(1) # @unsigned_value = value.to_i(10) value.to_i(10) else internal_error "Unhandled int value '#{text_value}'" end end |
#value(symtab) ⇒ Object
Return the compile-time-known value of the node
4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 |
# File 'lib/idl/ast.rb', line 4418 def value(symtab) return @value unless @value.nil? if text_value.delete("_") =~ /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/ # verilog-style literal signed = ::Regexp.last_match(4) width = width(symtab) v = if width == :unknown if !signed.empty? if unsigned_value > 0x7fff_ffff value_error("Don't know if value will be negative") else if unsigned_value > 0xffff_ffff value_error("Don't know if value will fit in literal") end unsigned_value end else if unsigned_value > 0xffff_ffff value_error("Don't know if value will fit in literal") end unsigned_value end else if unsigned_value.bit_length > width value_error("Value does not fit in literal") end if !signed.empty? && ((unsigned_value >> (width - 1)) == 1) if unsigned_value.bit_length > (width - 1) value_error("Value does not fit in literal") end -(2**width.to_i - unsigned_value) else unsigned_value end end @value = v else @value = unsigned_value end end |
#values(symtab) ⇒ Array<Integer>, ... Originally defined in module Rvalue
Return a complete list of possible compile-time-known values of the node, or raise a ValueError if the full list cannot be determined
For most AstNodes, this will just be a single-entry array
#width(symtab) ⇒ Object
4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 |
# File 'lib/idl/ast.rb', line 4383 def width(symtab) return @width unless @width.nil? text_value_no_underscores = text_value.delete("_") case text_value_no_underscores when /^((XLEN)|([0-9]+))?'(s?)([bodh]?)(.*)$/ # verilog-style literal width = ::Regexp.last_match(1) if width.nil? || width == "XLEN" width = symtab.mxlen.nil? ? :unknown : symtab.mxlen else width = width.to_i end @width = width when /^0([bdx]?)([0-9a-fA-F]*)(s?)$/ signed = ::Regexp.last_match(3) width = signed == "s" ? value(symtab).bit_length + 1 : value(symtab).bit_length width = 1 if width.zero? # happens when the literal is '0' @width = width when /^([0-9]*)(s?)$/ signed = ::Regexp.last_match(3) width = signed == "s" ? value(symtab).bit_length + 1 : value(symtab).bit_length width = 1 if width.zero? # happens when the literal is '0' @width = width else internal_error "No match on int literal" end end |