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
5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 |
# File 'lib/idlc/ast.rb', line 5558 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
5479 |
# File 'lib/idlc/ast.rb', line 5479 def const_eval?(symtab) = expressions.all? { |e| e.const_eval?(symtab) } |
#expressions ⇒ Object
5481 |
# File 'lib/idlc/ast.rb', line 5481 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
5551 5552 5553 5554 5555 |
# File 'lib/idlc/ast.rb', line 5551 def to_h = { "kind" => "concat_expr", "exprs" => expressions.map(&:to_h), "source" => source_yaml } |
#to_idl ⇒ Object
5548 |
# File 'lib/idlc/ast.rb', line 5548 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
5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 |
# File 'lib/idlc/ast.rb', line 5497 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
5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 |
# File 'lib/idlc/ast.rb', line 5484 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
5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 |
# File 'lib/idlc/ast.rb', line 5532 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 |