class Ikra::Translator::ASTTranslator

Attributes

expression_translator[R]
statement_translator[R]

Public Class Methods

new() click to toggle source
# File lib/translator/ast_translator.rb, line 464
def initialize
    @expression_translator = ExpressionTranslator.new(self)
    @statement_translator = StatementTranslator.new(self)
end
translate_block(block_def_node) click to toggle source
# 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) click to toggle source
# File lib/translator/ast_translator.rb, line 528
def self.translate_method(method_def_node)
    return self.new.translate_method(method_def_node)
end

Public Instance Methods

define_assign_variable(name, node) click to toggle source

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

# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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_id() click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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) click to toggle source
# 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