Class: Wrapture::TypeSpec

Inherits:
Object
  • Object
show all
Defined in:
lib/wrapture/type_spec.rb

Overview

A description of a type used in a specification.

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(spec = 'void') ⇒ TypeSpec

Creates a parameter specification based on the provided hash spec. spec can be a string instead of a hash, in which case it will be used as the name of the type.

Type specs must have a ‘name’ key with either the type itself (for example ‘const char *’) or a keyword specifying some other type (for example ‘equivalent-struct’). The only exception is for function pointers, which instead use a ‘function’ key that contains a FunctionSpec specification. This specification does not need to be definable, it only needs to have a parameter list and return type for the signature to be clear.



47
48
49
50
51
52
53
54
55
# File 'lib/wrapture/type_spec.rb', line 47

def initialize(spec = 'void')
  actual_spec = if spec.is_a?(String)
                  { 'name' => spec }
                else
                  spec
                end

  @spec = TypeSpec.normalize_spec_hash(actual_spec)
end

Class Method Details

.normalize_spec_hash(spec) ⇒ Object

Returns a normalized copy of the hash specification of a type in spec. See normalize_spec_hash! for details.



26
27
28
# File 'lib/wrapture/type_spec.rb', line 26

def self.normalize_spec_hash(spec)
  normalize_spec_hash!(Marshal.load(Marshal.dump(spec)))
end

.normalize_spec_hash!(spec) ⇒ Object

Normalizes the hash specification of a type in spec in place. This will normalize the include list.



32
33
34
35
# File 'lib/wrapture/type_spec.rb', line 32

def self.normalize_spec_hash!(spec)
  spec['includes'] = Wrapture.normalize_includes(spec['includes'])
  spec
end

Instance Method Details

#==(other) ⇒ Object

Compares this TypeSpec with other. Comparison happens by converting each object to a string using to_s and comparing.

Added in release 0.4.2.



61
62
63
# File 'lib/wrapture/type_spec.rb', line 61

def ==(other)
  to_s == other.to_s
end

#baseObject

The name of this type with all special characters removed.



66
67
68
# File 'lib/wrapture/type_spec.rb', line 66

def base
  name.delete('*&').strip
end

#cast_expression(expression) ⇒ Object

An expression casting the result of a given expression into this type.

Added in release 0.4.2.



73
74
75
# File 'lib/wrapture/type_spec.rb', line 73

def cast_expression(expression)
  "( #{variable} )( #{expression} )"
end

#equivalent_pointer?Boolean

True if this type is an equivalent struct pointer reference.

Returns:

  • (Boolean)


78
79
80
# File 'lib/wrapture/type_spec.rb', line 78

def equivalent_pointer?
  name == EQUIVALENT_POINTER_KEYWORD
end

#equivalent_struct?Boolean

True if this type is an equivalent struct reference.

Returns:

  • (Boolean)


83
84
85
# File 'lib/wrapture/type_spec.rb', line 83

def equivalent_struct?
  name == EQUIVALENT_STRUCT_KEYWORD
end

#function?Boolean

True if this type is a function.

Returns:

  • (Boolean)


88
89
90
# File 'lib/wrapture/type_spec.rb', line 88

def function?
  @spec.key?('function')
end

#includesObject

A list of includes needed for this type.



93
94
95
96
97
98
99
100
101
102
# File 'lib/wrapture/type_spec.rb', line 93

def includes
  includes = @spec['includes'].dup

  if function?
    func = FunctionSpec.new(@spec['function'])
    includes.concat(func.declaration_includes)
  end

  includes.uniq
end

#nameObject

The name of the type.



105
106
107
# File 'lib/wrapture/type_spec.rb', line 105

def name
  @spec['name']
end

#pointer?Boolean

True if this type is a pointer.

Returns:

  • (Boolean)


110
111
112
# File 'lib/wrapture/type_spec.rb', line 110

def pointer?
  name.end_with?('*')
end

#resolve(owner) ⇒ Object

Creates a new TypeSpec within the scope of owner that will be directly usable. This will replace equivalent structs, pointers, and self references with a usable type name.



117
118
119
# File 'lib/wrapture/type_spec.rb', line 117

def resolve(owner)
  owner.resolve_type(self)
end

#return_expression(func, func_name: func.name) ⇒ Object

A string with a declaration of FunctionSpec func with this type as the return value. func_name can be provided to override the function name, for example if a class name needs to be included.



124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/wrapture/type_spec.rb', line 124

def return_expression(func, func_name: func.name)
  name_part = String.new(func_name || '')
  param_part = String.new
  ret_part = name

  current_spec = @spec
  while current_spec.is_a?(Hash) && current_spec.key?('function')
    name_part.prepend('( *')

    current_func = FunctionSpec.new(current_spec['function'])
    param_part.concat(" )( #{current_func.param_list} )")

    current_spec = current_spec.dig('function', 'return', 'type')
    ret_part = current_spec
  end

  ret_part << ' ' unless ret_part.end_with?('*')

  "#{ret_part}#{name_part}( #{func.param_list} )#{param_part}"
end

#self?Boolean

True if this type is a reference to a class instance.

Returns:

  • (Boolean)


146
147
148
# File 'lib/wrapture/type_spec.rb', line 146

def self?
  name == SELF_REFERENCE_KEYWORD
end

#to_sObject

Gives a string representation of this type (its name).

Added in release 0.4.2.



153
154
155
# File 'lib/wrapture/type_spec.rb', line 153

def to_s
  name
end

#variable(var_name = nil) ⇒ Object

A string with a declaration of a variable named var_name of this type. If var_name is nil then this will simply be a type declaration.



159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/wrapture/type_spec.rb', line 159

def variable(var_name = nil)
  if variadic?
    '...'
  elsif function?
    func = FunctionSpec.new(@spec['function'])
    func_name = "( *#{var_name} )" || '(*)'
    func.return_expression(func_name: func_name)
  elsif var_name.nil?
    name
  else
    "#{name}#{' ' unless name.end_with?('*')}#{var_name}"
  end
end

#variadic?Boolean

True if this type is a variadic parameter type (name is equal to ...).

Returns:

  • (Boolean)


174
175
176
# File 'lib/wrapture/type_spec.rb', line 174

def variadic?
  name == '...'
end