Class: Ikra::Symbolic::ArrayStencilCommand::FlattenIndexNodeVisitor

Inherits:
AST::Visitor show all
Defined in:
lib/symbolic/symbolic.rb

Overview

This visitor executes the check_parents_index function on every local variable If the local variable is the “stencil array” then its indices will get modified/corrected for the 1D array access

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from AST::Visitor

#visit_array_node, #visit_begin_node, #visit_block_def_node, #visit_bool_node, #visit_break_node, #visit_class_def_node, #visit_const_node, #visit_float_node, #visit_for_node, #visit_hash_node, #visit_if_node, #visit_int_node, #visit_ivar_read_node, #visit_meth_def_node, #visit_nil_node, #visit_node, #visit_program_node, #visit_return_node, #visit_root_node, #visit_send_node, #visit_source_code_expr_node, #visit_string_node, #visit_symbol_node, #visit_ternary_node, #visit_until_node, #visit_until_post_node, #visit_var_def_node, #visit_while_node, #visit_while_post_node

Constructor Details

#initialize(name, offsets, command) ⇒ FlattenIndexNodeVisitor

Returns a new instance of FlattenIndexNodeVisitor.



549
550
551
552
553
# File 'lib/symbolic/symbolic.rb', line 549

def initialize(name, offsets, command)
    @name = name
    @offsets = offsets
    @command = command
end

Instance Attribute Details

#commandObject (readonly)

Returns the value of attribute command.



547
548
549
# File 'lib/symbolic/symbolic.rb', line 547

def command
  @command
end

#nameObject (readonly)

Returns the value of attribute name.



546
547
548
# File 'lib/symbolic/symbolic.rb', line 546

def name
  @name
end

#offsetsObject (readonly)

Returns the value of attribute offsets.



545
546
547
# File 'lib/symbolic/symbolic.rb', line 545

def offsets
  @offsets
end

Instance Method Details

#check_index(name, offsets, node) ⇒ Object



566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
# File 'lib/symbolic/symbolic.rb', line 566

def check_index(name, offsets, node)
    if node.identifier == name
        # This is the array-variable used in the stencil

        send_node = node
        index_combination = []
        is_literal = true

        # Build the index off this access in index_combination
        for i in 0..command.dimensions.size-1
            send_node = send_node.parent
            if not (send_node.is_a?(AST::SendNode) && send_node.selector == :[])
                raise AssertionError.new(
                    "This has to be a SendNode and Array-selector")
            end
            index_combination[i] = send_node.arguments.first
            if not index_combination[i].is_a?(AST::IntLiteralNode)
                is_literal = false
            end
        end

        if is_literal
            # The index consists of only literals so we can translate it easily by mapping the index onto the offsets

            index_combination = index_combination.map do |x|
                x.value
            end

            replacement = AST::IntLiteralNode.new(
                value: offsets[index_combination])
        else
            # This handles the case where non-literals have to be translated with the Ternary Node

            offset_arr = offsets.to_a
            replacement = AST::IntLiteralNode.new(value: offset_arr[0][1])
            for i in 1..offset_arr.size-1
                # Build combination of ternary nodes

                ternary_build = AST::SendNode.new(receiver: AST::IntLiteralNode.new(value: offset_arr[i][0][0]), selector: :==, arguments: [index_combination[0]])
                for j in 1..index_combination.size-1

                    next_eq = AST::SendNode.new(receiver: AST::IntLiteralNode.new(value: offset_arr[i][0][j]), selector: :==, arguments: [index_combination[j]])
                    ternary_build = AST::SendNode.new(receiver: next_eq, selector: :"&&", arguments: [ternary_build])
                end
                replacement = AST::TernaryNode.new(condition: ternary_build, true_val: AST::IntLiteralNode.new(value: offset_arr[i][1]), false_val: replacement)
            end
        end

        #Replace outer array access with new 1D array access

        send_node.replace(AST::SendNode.new(receiver: node, selector: :[], arguments: [replacement]))
    end
end

#visit_lvar_read_node(node) ⇒ Object



555
556
557
558
# File 'lib/symbolic/symbolic.rb', line 555

def visit_lvar_read_node(node)
    super(node)
    check_index(name, offsets, node)
end

#visit_lvar_write_node(node) ⇒ Object



560
561
562
563
# File 'lib/symbolic/symbolic.rb', line 560

def visit_lvar_write_node(node)
    super(node)
    check_index(name, offsets, node)
end