Class: Rucc::Type

Inherits:
Object
  • Object
show all
Extended by:
Check, Conv
Defined in:
lib/rucc/type.rb,
lib/rucc/type/conv.rb,
lib/rucc/type/check.rb

Defined Under Namespace

Modules: Check, Conv

Constant Summary collapse

VOID =

Objects representing basic types. All variables will be of one of these types or a derived type from one of them.

Type.new(Kind::VOID,    size: 0, align: 0, usig: false)
BOOL =
Type.new(Kind::BOOL,    size: 1, align: 1, usig: true)
CHAR =
Type.new(Kind::CHAR,    size: 1, align: 1, usig: false)
SHORT =
Type.new(Kind::SHORT,   size: 2, align: 2, usig: false)
INT =
Type.new(Kind::INT,     size: 4, align: 4, usig: false)
LONG =
Type.new(Kind::LONG,    size: 8, align: 8, usig: false)
LLONG =
Type.new(Kind::LLONG,   size: 8, align: 8, usig: false)
UCHAR =
Type.new(Kind::CHAR,    size: 1, align: 1, usig: true)
USHORT =
Type.new(Kind::SHORT,   size: 2, align: 2, usig: true)
UINT =
Type.new(Kind::INT,     size: 4, align: 4, usig: true)
ULONG =
Type.new(Kind::LONG,    size: 8, align: 8, usig: true)
ULLONG =
Type.new(Kind::LLONG,   size: 8, align: 8, usig: true)
FLOAT =
Type.new(Kind::FLOAT,   size: 4, align: 4, usig: false)
DOUBLE =
Type.new(Kind::DOUBLE,  size: 8, align: 8, usig: false)
LDOUBLE =
Type.new(Kind::LDOUBLE, size: 8, align: 8, usig: false)
ENUM =
Type.new(Kind::ENUM,    size: 4, align: 4, usig: false)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Check

is_arithtype, is_flotype, is_inttype, is_string

Methods included from Conv

usual_arith_conv

Constructor Details

#initialize(kind, size: nil, align: nil, usig: nil, isstatic: nil, ptr: nil, len: nil, fields: nil, offset: nil, is_struct: nil, bitoff: nil, bitsize: nil, rettype: nil, params: nil, hasva: nil, oldstyle: nil) ⇒ Type

Returns a new instance of Type.

Parameters:

  • kind (Kind)

    the kind of type

  • size (Integer) (defaults to: nil)
  • align (Integer) (defaults to: nil)
  • usig (Boolean) (defaults to: nil)

    true if unsigned

  • len (Integer) (defaults to: nil)

    array length



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/rucc/type.rb', line 15

def initialize(kind,
               size: nil, align: nil, usig: nil, isstatic: nil,
               ptr: nil,                                             # Pointer or Array
               len: nil,                                             # Array
               fields: nil, offset: nil,                             # Struct
               is_struct: nil,                                       # true if Struct, false if Union
               bitoff: nil, bitsize: nil,                            # Bitfield
               rettype: nil, params: nil, hasva: nil, oldstyle: nil  # Function
              )
  @kind = kind
  @size = size; @align = align; @usig = usig; @isstatic = isstatic
  @ptr = ptr                                                                  # Pointer or Array
  @len = len                                                                  # Array
  @fields = fields; @offset = offset                                          # Struct
  @is_struct = is_struct                                                      # true if Struct, false if Union
  @bitoff = bitoff; @bitsize = bitsize                                        # Bitfield
  @rettype = rettype; @params = params; @hasva = hasva; @oldstyle = oldstyle  # Function
end

Instance Attribute Details

#alignObject

Returns the value of attribute align.



33
34
35
# File 'lib/rucc/type.rb', line 33

def align
  @align
end

#bitoffObject

Returns the value of attribute bitoff.



33
34
35
# File 'lib/rucc/type.rb', line 33

def bitoff
  @bitoff
end

#bitsizeObject

Returns the value of attribute bitsize.



33
34
35
# File 'lib/rucc/type.rb', line 33

def bitsize
  @bitsize
end

#fieldsObject

Returns the value of attribute fields.



33
34
35
# File 'lib/rucc/type.rb', line 33

def fields
  @fields
end

#hasvaObject

Returns the value of attribute hasva.



33
34
35
# File 'lib/rucc/type.rb', line 33

def hasva
  @hasva
end

#is_structObject (readonly)

Returns the value of attribute is_struct.



33
34
35
# File 'lib/rucc/type.rb', line 33

def is_struct
  @is_struct
end

#isstaticObject

Returns the value of attribute isstatic.



33
34
35
# File 'lib/rucc/type.rb', line 33

def isstatic
  @isstatic
end

#kindObject (readonly)

Returns the value of attribute kind.



33
34
35
# File 'lib/rucc/type.rb', line 33

def kind
  @kind
end

#lenObject

Returns the value of attribute len.



33
34
35
# File 'lib/rucc/type.rb', line 33

def len
  @len
end

#offsetObject

Returns the value of attribute offset.



33
34
35
# File 'lib/rucc/type.rb', line 33

def offset
  @offset
end

#oldstyleObject (readonly)

Returns the value of attribute oldstyle.



33
34
35
# File 'lib/rucc/type.rb', line 33

def oldstyle
  @oldstyle
end

#paramsObject

Returns the value of attribute params.



33
34
35
# File 'lib/rucc/type.rb', line 33

def params
  @params
end

#ptrObject

Returns the value of attribute ptr.



33
34
35
# File 'lib/rucc/type.rb', line 33

def ptr
  @ptr
end

#rettypeObject (readonly)

Returns the value of attribute rettype.



33
34
35
# File 'lib/rucc/type.rb', line 33

def rettype
  @rettype
end

#sizeObject

Returns the value of attribute size.



33
34
35
# File 'lib/rucc/type.rb', line 33

def size
  @size
end

#usigObject

Returns the value of attribute usig.



33
34
35
# File 'lib/rucc/type.rb', line 33

def usig
  @usig
end

Class Method Details

.char_type(enc) ⇒ Type

Parameters:

Returns:



192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/rucc/type.rb', line 192

def char_type(enc)
  case enc
  when ENC::NONE, ENC::WCHAR
    return Type::INT
  when ENC::CHAR16
    return Type::USHORT
  when ENC::CHAR32
    return Type::UINT
  else
    raise "internal error"
  end
end

.copy_incomplete_type(ty) ⇒ Type, NilClass

Parameters:

  • ty (Type, NilClass)

Returns:



279
280
281
282
# File 'lib/rucc/type.rb', line 279

def copy_incomplete_type(ty)
  return nil if ty.nil?
  (ty.len == -1) ? ty.dup : ty
end

.ensure_assignable!(totype, fromtype) ⇒ Object

Parameters:



214
215
216
217
218
219
220
221
222
223
# File 'lib/rucc/type.rb', line 214

def ensure_assignable!(totype, fromtype)
  if (Type.is_arithtype(totype) || (totype.kind == Kind::PTR)) &&
      (Type.is_arithtype(fromtype) || (fromtype.kind == Kind::PTR))
    return
  end
  if is_same_struct?(totype, fromtype)
    return
  end
  raise "incompatible kind: <#{totype}> <#{fromtype}>"
end

.is_same_struct?(a, b) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/rucc/type.rb', line 228

def is_same_struct?(a, b)
  if a.kind != b.kind
    return false
  end

  case a.kind
  when Kind::ARRAY
    return a.len == b.len && is_same_struct?(a.ptr, b.ptr)
  when Kind::PTR
    return is_same_struct?(a.ptr, b.ptr)
  when Kind::STRUCT
    if a.is_struct != b.is_struct
      return false
    end
    ka = a.fields.values
    kb = b.fields.values
    if ka.size != kb.size
      return false
    end
    ka.zip(kb).each do |(x, y)|
      if !is_same_struct?(x, y)
        return false
      end
    end
    return true
  else
    return true
  end
end

.make_array_type(ty, len) ⇒ Type

Parameters:

  • ty (Type)
  • len (Integer)

Returns:



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/rucc/type.rb', line 131

def make_array_type(ty, len)
  if len < 0
    size = -1
  else
    size = ty.size * len
  end
  Type.new(Kind::ARRAY,
           ptr:   ty,
           size:  size,
           len:   len,
           align: ty.align)
end

.make_func_type(rettype, paramtypes, has_varargs, oldstyle) ⇒ Type

Parameters:

  • rettype (Type)
  • paramtypes (Array)
  • has_varargs (Boolean)
  • oldstyle (Boolean)

Returns:



149
150
151
152
153
154
155
# File 'lib/rucc/type.rb', line 149

def make_func_type(rettype, paramtypes, has_varargs, oldstyle)
  Type.new(Kind::FUNC,
           rettype:  rettype,
           params:   paramtypes,
           hasva:    has_varargs,
           oldstyle: oldstyle)
end

.make_numtype(kind, usig) ⇒ Type

Parameters:

  • kind (Kind)
  • usig (Boolean)

Returns:



160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/rucc/type.rb', line 160

def make_numtype(kind, usig)
  size = align =
    case kind
    when Kind::VOID    then 0
    when Kind::BOOL    then 1
    when Kind::CHAR    then 1
    when Kind::SHORT   then 2
    when Kind::INT     then 4
    when Kind::LONG    then 8
    when Kind::LLONG   then 8
    when Kind::FLOAT   then 4
    when Kind::DOUBLE  then 8
    when Kind::LDOUBLE then 8
    else
      raise "internal error"
    end
  Type.new(kind, size: size, align: align, usig: usig)
end

.make_ptr_type(ty) ⇒ Type

Parameters:

Returns:



121
122
123
124
125
126
# File 'lib/rucc/type.rb', line 121

def make_ptr_type(ty)
  Type.new(Kind::PTR,
           ptr:   ty,
           size:  8,
           align: 8)
end

.make_rectype(is_struct) ⇒ Type

Parameters:

  • is_struct (Boolean)

Returns:



186
187
188
# File 'lib/rucc/type.rb', line 186

def make_rectype(is_struct)
  Type.new(Kind::STRUCT, is_struct: is_struct)
end

.make_stub_typeType

Returns:



180
181
182
# File 'lib/rucc/type.rb', line 180

def make_stub_type
  Type.new(Kind::STUB, size: 0)
end

.same_arith_type(t, u) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


208
209
210
# File 'lib/rucc/type.rb', line 208

def same_arith_type(t, u)
  t.kind == u.kind && t.usig == u.usig
end

.type_compatible?(a, b) ⇒ Boolean

Parameters:

Returns:

  • (Boolean)


261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
# File 'lib/rucc/type.rb', line 261

def type_compatible?(a, b)
  if a.kind == Kind::STRUCT
    return is_same_struct?(a, b)
  end
  if a.kind != b.kind
    return false
  end
  if a.ptr && b.ptr
    return type_compatible?(a.ptr, b.ptr)
  end
  if is_arithtype(a) && is_arithtype(b)
    return same_arith_type(a, b)
  end
  true
end

Instance Method Details

#decorate_int(name) ⇒ String

Parameters:

  • name (String)

Returns:

  • (String)


103
104
105
106
107
108
109
# File 'lib/rucc/type.rb', line 103

def decorate_int(name)
  u = usig ? "u" : ""
  if bitsize && bitsize > 0
    return "#{u}#{name}:#{bitoff}:#{bitoff + bitsize}"
  end
  "#{u}#{name}"
end

#replace_by!(tmpl) ⇒ Object

Parameters:



112
113
114
115
116
# File 'lib/rucc/type.rb', line 112

def replace_by!(tmpl)
  tmpl.instance_variables.each do |ivar|
    self.instance_variable_set(ivar, tmpl.instance_variable_get(ivar))
  end
end

#to_sString

Returns:

  • (String)


49
50
51
# File 'lib/rucc/type.rb', line 49

def to_s
  to_s_impl({})
end

#to_s_impl(dict) ⇒ String

Parameters:

  • dict (Hash)

Returns:

  • (String)


55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/rucc/type.rb', line 55

def to_s_impl(dict)
  # TODO(south37) Consider nil case
  # if (!ty)
  #     return "(nil)";
  case kind
  when Kind::VOID    then return "void"
  when Kind::BOOL    then return "_Bool"
  when Kind::CHAR    then return decorate_int("char")
  when Kind::SHORT   then return decorate_int("short")
  when Kind::INT     then return decorate_int("int")
  when Kind::LONG    then return decorate_int("long")
  when Kind::LLONG   then return decorate_int("llong")
  when Kind::FLOAT   then return "float"
  when Kind::DOUBLE  then return "double"
  when Kind::LDOUBLE then return "long double"
  when Kind::PTR
    return "*#{ptr.to_s_impl(dict)}"
  when Kind::ARRAY
    return "[#{len}]#{ptr.to_s_impl(dict)}"
  when Kind::STRUCT
    k = is_struct ? "struct" : "union"
    if !dict[self.object_id].nil?
      return "(#{k})"
    end
    dict[self.object_id] = true
    if fields
      s = "(#{k}"
      fields.each do |_, fieldtype|
        s << " (#{fieldtype.to_s_impl(dict)})"
      end
      s << ")"
      return s
    end
    raise "Must not reach here"  # TODO(south37) Confirm occurance
  when Kind::FUNC
    s = "("
    if params
      s << params.map { |param| param.to_s_impl(dict) }.join(",")
    end
    s << ")=>#{rettype.to_s_impl(dict)}"
    return s
  else
    return "(Unknown ty: #{kind})"
  end
end