Class: Idl::ConcatenationExpressionAst
- Includes:
- Rvalue
- Defined in:
- lib/idlc/ast.rb,
lib/idlc/passes/prune.rb,
lib/idlc/passes/gen_adoc.rb
Overview
represents a concatenation expression
for example:
{1'b0, 5'd3}
Constant Summary
Constants inherited from AstNode
AstNode::Bits1Type, AstNode::Bits32Type, AstNode::Bits64Type, AstNode::BoolType, AstNode::ConstBoolType, AstNode::PossiblyUnknownBits1Type, AstNode::PossiblyUnknownBits32Type, AstNode::PossiblyUnknownBits64Type, AstNode::ReachableFunctionCacheType, AstNode::StringType, AstNode::VoidType
Instance Attribute Summary
Attributes inherited from AstNode
#children, #input, #interval, #parent
Class Method Summary collapse
Instance Method Summary collapse
- #const_eval?(symtab) ⇒ Boolean
- #expressions ⇒ Object
- #gen_adoc(indent, indent_spaces: 2) ⇒ Object
- #prune(symtab, forced_type: nil) ⇒ Object
- #to_h ⇒ Object
- #to_idl ⇒ Object
-
#type(symtab) ⇒ Type
Given a specific symbol table, return the type of this node.
-
#type_check(symtab, strict:) ⇒ void
type check this node and all children.
-
#value(symtab) ⇒ Object
Return the compile-time-known value of the node.
Methods included from Rvalue
#max_value, #min_value, #truncate, #values
Methods inherited from AstNode
#always_terminates?, #declaration?, #executable?, extract_base_var_name, #find_ancestor, #find_dst_registers, #find_referenced_csrs, #find_src_registers, #freeze_tree, #gen_option_adoc, #initialize, #input_file, input_from_source_yaml, #inspect, #internal_error, interval_from_source_yaml, #lineno, #lines_around, #nullify_assignments, #pass_find_return_values, #path, #print_ast, #reachable_exceptions, #reachable_functions, #set_input_file, #set_input_file_unless_already_set, #source_line_file_offsets, #source_starting_offset, #source_yaml, #starting_line, #text_value, #truncation_warn, #type_error, #unindent, value_else, #value_else, value_error, #value_error, value_try, #value_try, write_back_nested
Constructor Details
This class inherits a constructor from Idl::AstNode
Class Method Details
.from_h(yaml, source_mapper) ⇒ Object
5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 |
# File 'lib/idlc/ast.rb', line 5543 def self.from_h(yaml, source_mapper) raise "Bad YAML" unless yaml.key?("kind") && yaml.fetch("kind") == "concat_expr" input = input_from_source_yaml(yaml.fetch("source"), source_mapper) interval = interval_from_source_yaml(yaml.fetch("source")) ConcatenationExpressionAst.new( input, interval, yaml.fetch("exprs").map { |v| AstNode.from_h(v, source_mapper) } ) end |
Instance Method Details
#const_eval?(symtab) ⇒ Boolean
5464 |
# File 'lib/idlc/ast.rb', line 5464 def const_eval?(symtab) = expressions.all? { |e| e.const_eval?(symtab) } |
#expressions ⇒ Object
5466 |
# File 'lib/idlc/ast.rb', line 5466 def expressions = @children |
#gen_adoc(indent, indent_spaces: 2) ⇒ Object
102 103 104 |
# File 'lib/idlc/passes/gen_adoc.rb', line 102 def gen_adoc(indent, indent_spaces: 2) "#{' ' * indent}{#{expressions.map { |e| e.gen_adoc(0, indent_spaces:) }.join(', ')}}" end |
#prune(symtab, forced_type: nil) ⇒ Object
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 |
# File 'lib/idlc/passes/prune.rb', line 640 def prune(symtab, forced_type: nil) value_result = value_try do v = value(symtab) return PruneHelpers.create_int_literal(v, forced_type: forced_type || type(symtab)) end value_else(value_result) do c = ConcatenationExpressionAst.new( input, interval, @children.map { |c| c.prune(symtab) } ) if forced_type if forced_type.width < type(symtab).width c = AryRangeAccessAst.new( input, interval, c, PruneHelpers.create_int_literal(forced_type.width - 1), create_int_literal(0) ) elsif forced_type.width > type(symtab).width extra = forced_type.width - type(symtab).width mock_type = Struct.new(:width) c = ConcatenationExpressionAst.new( input, interval, [PruneHelpers.create_int_literal(0, forced_type: mock_type.new(extra))] + @children.map { |c| c.prune(symtab) } ) end end c end end |
#to_h ⇒ Object
5536 5537 5538 5539 5540 |
# File 'lib/idlc/ast.rb', line 5536 def to_h = { "kind" => "concat_expr", "exprs" => expressions.map(&:to_h), "source" => source_yaml } |
#to_idl ⇒ Object
5533 |
# File 'lib/idlc/ast.rb', line 5533 def to_idl = "{#{expressions.map { |exp| exp.to_idl }.join(',')}}" |
#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
5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 |
# File 'lib/idlc/ast.rb', line 5482 def type(symtab) all_known_values = T.let(true, T::Boolean) width_known = T.let(true, T::Boolean) is_const = T.let(true, T::Boolean) total_width = expressions.reduce(0) do |sum, exp| e_type = exp.type(symtab) if e_type.width == :unknown width_known = false elsif width_known sum = sum + e_type.width end all_known_values &= e_type.known? sum end qualifiers = is_const ? [:const] : [] if all_known_values qualifiers << :known if width_known Type.new(:bits, width: total_width, qualifiers:) else Type.new(:bits, width: :unknown, qualifiers:) end else if width_known Type.new(:bits, width: total_width, qualifiers:) else Type.new(:bits, width: :unknown, qualifiers:) end end end |
#type_check(symtab, strict:) ⇒ void
5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 |
# File 'lib/idlc/ast.rb', line 5469 def type_check(symtab, strict:) type_error "Must concatenate at least two objects" if expressions.size < 2 expressions.each do |exp| exp.type_check(symtab, strict:) e_type = exp.type(symtab) type_error "Concatenation only supports Bits<> types" unless e_type.kind == :bits internal_error "Negative width for element #{exp.text_value}" if (e_type.width != :unknown) && (e_type.width <= 0) end end |
#value(symtab) ⇒ Object
Return the compile-time-known value of the node
5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 |
# File 'lib/idlc/ast.rb', line 5517 def value(symtab) result = T.let(UnknownLiteral.new(0, 0), T.any(Integer, UnknownLiteral)) total_width = 0 expressions.reverse_each do |exp| result |= (exp.value(symtab) << total_width) total_width += exp.type(symtab).width end if result.is_a?(UnknownLiteral) result.unknown_mask.zero? ? result.known_value : result else result end end |