Class: Ikra::Types::ZipStructType

Inherits:
StructType show all
Defined in:
lib/types/types/struct_type.rb,
lib/translator/struct_type.rb

Overview

This type represents the type of an array that is the result of zipping two arrays. [ZipStructType] is similar to [StructType] but can be accessed via indices.

Defined Under Namespace

Modules: ZipStruct

Instance Attribute Summary

Attributes inherited from StructType

#fields

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from StructType

#==, identifier_from_hash, #initialize, #to_c_type, #to_ffi_type

Methods included from RubyType

#class_id, #eql?, #hash, #inspect, #is_primitive?, #is_union_type?, #should_generate_self_arg?, #to_array_type, #to_c_type, #to_str, #to_union_type

Constructor Details

This class inherits a constructor from Ikra::Types::StructType

Class Method Details

.new(*types) ⇒ Object



76
77
78
79
80
81
82
# File 'lib/types/types/struct_type.rb', line 76

def new(*types)
    identifiers = Array.new(types.size) do |index|
        :"field_#{index}"
    end

    super(Hash[identifiers.zip(types)])
end

Instance Method Details

#[](index) ⇒ Object

Returns the type of the element at [index].



121
122
123
# File 'lib/types/types/struct_type.rb', line 121

def [](index)
    return @fields[:"field_#{index}"]
end

#generate_definitionObject



17
18
19
20
21
22
23
24
25
26
27
# File 'lib/translator/struct_type.rb', line 17

def generate_definition
    fields_def = @fields.map do |field_name, type|
        "#{type.to_c_type} #{field_name};"
    end

    all_fields = fields_def.join("\n")

    return Translator.read_file(file_name: "struct_definition.cpp", replacements: {
        "name" => to_c_type,
        "fields" => all_fields})
end

#generate_inline_initialization(*input) ⇒ Object

Generates a source code expression that creates and initializes an instance of this struct.



12
13
14
15
# File 'lib/translator/struct_type.rb', line 12

def generate_inline_initialization(*input)
    field_init = input.join(", ")
    return "((#{to_c_type}) {#{field_init}})"
end

#generate_non_constant_read(receiver, selector, index_expression_identifier) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/translator/struct_type.rb', line 37

def generate_non_constant_read(receiver, selector, index_expression_identifier)
    expression = ""

    for index in 0...@fields.size
        expression = expression + "(#{index_expression_identifier} == #{index} ? #{receiver}.field_#{index} : "
    end

    # Out of bounds case should throw and exception
    expression = expression + "NULL"

    for index in 0...@fields.size
        expression = expression + ")"
    end

    return expression
end

#generate_read(receiver, selector, index) ⇒ Object

Generates a source code expression that reads a fields of this struct by index.



30
31
32
33
34
35
# File 'lib/translator/struct_type.rb', line 30

def generate_read(receiver, selector, index)
    # Type inference already ensured that there is exactly one parameter which is
    # an IntLiteral.

    return "#{receiver}.field_#{index}"
end

#get_return_type(selector, *arg_nodes) ⇒ Object

Performs type inference for the result of accessing this Zip “Array” by index.



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/types/types/struct_type.rb', line 86

def get_return_type(selector, *arg_nodes)
    # TODO: Can only handle single cases at the moment. This should eventually forward
    # to Array integration code.

    if selector != :"[]"
        raise AssertionError.new(
            "Selector not supported for ZipStructType: #{selector}")
    end

    if arg_nodes.size != 1
        raise AssertionError.new("Expected exactly one argument")
    end

    if arg_nodes.first.class == AST::IntLiteralNode
        if arg_nodes.first.value >= @fields.size
            raise AssertionError.new(
                "ZipStruct index out of bounds: #{arg_nodes.first.value}")
        end

        return self[arg_nodes.first.value]
    else
        return get_return_type_non_constant(selector)
    end
end

#get_return_type_non_constant(selector) ⇒ Object

Performs type inference for the result of accessing this Zip “Array” by index.



112
113
114
115
116
117
118
# File 'lib/types/types/struct_type.rb', line 112

def get_return_type_non_constant(selector)
    # TODO: Can only handle single cases at the moment. This should eventually forward
    # to Array integration code.

    # TODO: This code assumes that the all struct elements have the same type
    return self[0]
end

#to_ruby_typeObject



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/types/types/struct_type.rb', line 155

def to_ruby_type
    # Cache struct types
    if @struct_type == nil
        # Create class
        @struct_type = Class.new(FFI::Struct)
        @struct_type.include(ZipStruct)

        # Define layout of struct
        var_names = Array.new(@fields.size) do |index|
            :"field_#{index}"
        end

        var_types = var_names.map do |name|
            @fields[name].to_ffi_type
        end

        layout = var_names.zip(var_types).flatten
        @struct_type.layout(*layout)
    end

    return @struct_type
end