Class: Ikra::Translator::ASTTranslator

Inherits:
Object
  • Object
show all
Defined in:
lib/translator/ast_translator.rb

Direct Known Subclasses

HostSectionASTTranslator

Defined Under Namespace

Classes: ExpressionTranslator, StatementTranslator

Constant Summary collapse

@@next_temp_identifier_id =
0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeASTTranslator

Returns a new instance of ASTTranslator.



464
465
466
467
# File 'lib/translator/ast_translator.rb', line 464

def initialize
    @expression_translator = ExpressionTranslator.new(self)
    @statement_translator = StatementTranslator.new(self)
end

Instance Attribute Details

#expression_translatorObject (readonly)

Returns the value of attribute expression_translator.



460
461
462
# File 'lib/translator/ast_translator.rb', line 460

def expression_translator
  @expression_translator
end

#statement_translatorObject (readonly)

Returns the value of attribute statement_translator.



462
463
464
# File 'lib/translator/ast_translator.rb', line 462

def statement_translator
  @statement_translator
end

Class Method Details

.translate_block(block_def_node) ⇒ Object



520
521
522
# File 'lib/translator/ast_translator.rb', line 520

def self.translate_block(block_def_node)
    return self.new.translate_block(block_def_node)
end

.translate_method(method_def_node) ⇒ Object



528
529
530
# File 'lib/translator/ast_translator.rb', line 528

def self.translate_method(method_def_node)
    return self.new.translate_method(method_def_node)
end

Instance Method Details

#define_assign_variable(name, node) ⇒ Object

Generates code that assigns the value of a node to a newly-defined variable.



494
495
496
497
# File 'lib/translator/ast_translator.rb', line 494

def define_assign_variable(name, node)
    type = node.get_type.to_c_type
    return "#{type} #{name} = #{node.accept(expression_translator)};"
end

#generate_method_signature(meth_def_node) ⇒ Object



532
533
534
535
536
537
538
539
540
541
542
543
# File 'lib/translator/ast_translator.rb', line 532

def generate_method_signature(meth_def_node)
    method_params = ([
        "environment_t * #{Constants::ENV_IDENTIFIER}", 
        "#{meth_def_node.parent.get_type.to_c_type} #{Constants::SELF_IDENTIFIER}"] + 
            meth_def_node.parameters_names_and_types.map do |name, type|
                "#{type.singleton_type.to_c_type} #{name}"
            end).join(", ")

    signature = "__device__ #{meth_def_node.get_type.singleton_type.to_c_type} #{meth_def_node.parent.get_type.mangled_method_name(meth_def_node.name)}(#{method_params})"

    return signature
end

#indent_block(str) ⇒ Object



473
474
475
# File 'lib/translator/ast_translator.rb', line 473

def indent_block(str)
    return str.split("\n").map do |line| "    " + line end.join("\n")
end

#statements_as_expression(str) ⇒ Object



469
470
471
# File 'lib/translator/ast_translator.rb', line 469

def statements_as_expression(str)
    return "[&]#{wrap_in_c_block(str, omit_newl: true)}()"
end

#temp_identifier_idObject



488
489
490
491
# File 'lib/translator/ast_translator.rb', line 488

def temp_identifier_id
    @@next_temp_identifier_id += 1
    @@next_temp_identifier_id
end

#translate_block(block_def_node) ⇒ Object



524
525
526
# File 'lib/translator/ast_translator.rb', line 524

def translate_block(block_def_node)
    return block_def_node.body.accept(statement_translator)
end

#translate_method(meth_def_node) ⇒ Object



549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
# File 'lib/translator/ast_translator.rb', line 549

def translate_method(meth_def_node)
    # TODO: merge with BlockTranslator
    # TODO: load environment variables

    # Declare local variables
    local_variables_def = ""
    meth_def_node.local_variables_names_and_types.each do |name, type|
        local_variables_def += "#{type.to_c_type} #{name};\n"
    end

    # TODO: There should be a better way to ensure that we don't generate methods
    # multiple times.
    mangled_name = meth_def_node.parent.get_type.mangled_method_name(meth_def_node.name)
    def_label = "def_label_#{mangled_name}"

    return "#ifndef #{def_label}\n#define #{def_label}\n" +
        generate_method_signature(meth_def_node) + 
        "\n" + 
        wrap_in_c_block(local_variables_def + meth_def_node.body.accept(statement_translator)) +
        "#endif"
end

#translate_method_predecl(meth_def_node) ⇒ Object



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

def translate_method_predecl(meth_def_node)
    return generate_method_signature(meth_def_node) + ";"
end

#wrap_in_c_block(str, omit_newl: false) ⇒ Object



477
478
479
480
481
482
483
484
485
# File 'lib/translator/ast_translator.rb', line 477

def wrap_in_c_block(str, omit_newl: false)
    result = "{\n" + indent_block(str) + "\n}"

    if omit_newl
        return result
    else
        return result + "\n"
    end
end

#wrap_in_union_type(str, type) ⇒ Object



499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
# File 'lib/translator/ast_translator.rb', line 499

def wrap_in_union_type(str, type)
    if type == Types::PrimitiveType::Int
        return "union_t(#{type.class_id}, union_v_t::from_int(#{str}))"
    elsif type == Types::PrimitiveType::Float
        return "union_t(#{type.class_id}, union_v_t::from_float(#{str}))"
    elsif type == Types::PrimitiveType::Bool
        return "union_t(#{type.class_id}, union_v_t::from_bool(#{str}))"
    elsif type == Types::PrimitiveType::Nil
        return "union_t(#{type.class_id}, union_v_t::from_int(#{str}))"
    elsif type.is_a?(Symbolic::ArrayCommand)
        return "union_t(#{type.class_id}, union_v_t::from_pointer((void *) #{str}))"
    elsif type.is_a?(Types::LocationAwareArrayType)
        # TODO: Should not use variable_size_array for fixed size arrays
        return "union_t(#{type.class_id}, union_v_t::from_variable_size_array_t(#{str}))"
    elsif !type.is_a?(Types::UnionType)
        return "union_t(#{type.class_id}, union_v_t::from_object_id(#{str}))"
    else
        raise AssertionError.new("UnionType found but singleton type expected")
    end
end