Class: Yadriggy::C::ClangTypeChecker

Inherits:
RubyTypeInferer show all
Includes:
CType
Defined in:
lib/yadriggy/c/ctypecheck.rb

Direct Known Subclasses

OclTypeChecker

Constant Summary

Constants included from CType

Yadriggy::C::CType::Float32Array, Yadriggy::C::CType::Float32Type, Yadriggy::C::CType::FloatArray, Yadriggy::C::CType::Int, Yadriggy::C::CType::IntArray, Yadriggy::C::CType::Void

Constants included from Yadriggy

DynType, Undef, VERSION, Void

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from CType

#arrayof, #typedecl

Methods inherited from RubyTypeInferer

#binary_type, #bind_local_var, #get_instance_variable_type, #get_return_type, #is_attr_accessor?, #to_non_instance_type

Methods inherited from RubyTypeChecker

#bind_local_var, #clear_references, #get_call_expr_type, #get_name_type, #get_return_type, #lookup_builtin, #lookup_ruby_classes, #references, #type_assert_params, #type_assert_subsume, #type_parameters

Methods inherited from TypeChecker

#add_typedef, #check, #error_group, #make_base_env, #type, #type_as, #type_assert, #type_assert_false, #type_assert_later, #type_env, #typecheck, #typedef

Methods inherited from Yadriggy::Checker

all_rules, #apply_typing_rule, #ast, #ast_env, #check, #check_all, check_init_class, #check_later, #error, #error_found!, #error_group, find_rule_entry, #make_base_env, #proceed, rule

Methods included from Yadriggy

debug, debug=, define_syntax, reify

Constructor Details

#initialize(syntax = nil) ⇒ ClangTypeChecker

Returns a new instance of ClangTypeChecker.



59
60
61
62
63
# File 'lib/yadriggy/c/ctypecheck.rb', line 59

def initialize(syntax=nil)
  super(syntax || C::syntax)
  @local_vars_table = {}
  @instance_variables = Set.new
end

Instance Attribute Details

#instance_variablesSet<IvarObj> (readonly)

Returns accessed instance variables.

Returns:

  • (Set<IvarObj>)

    accessed instance variables.



57
58
59
# File 'lib/yadriggy/c/ctypecheck.rb', line 57

def instance_variables
  @instance_variables
end

#local_vars_tableHash<Def,Hash<Symbol,Type>> (readonly)

Returns a map from functions to their local variables.

Returns:

  • (Hash<Def,Hash<Symbol,Type>>)

    a map from functions to their local variables.



54
55
56
# File 'lib/yadriggy/c/ctypecheck.rb', line 54

def local_vars_table
  @local_vars_table
end

Instance Method Details

#binary_cexpr_type(op, t1, t2) ⇒ Object



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/yadriggy/c/ctypecheck.rb', line 208

def binary_cexpr_type(op, t1, t2)
  case op
  when :+, :-, :*, :/
    if t1 <= RubyClass::Float || t2 <= RubyClass::Float
      return RubyClass::Float
    elsif t1 <= Float32Type || t2 <= Float32Type
      return Float32Type
    else
      return RubyClass::Integer
    end
  when :%
    type_assert(t1 <= RubyClass::Integer &&
                t2 <= RubyClass::Integer, 'bad operand type')
    return RubyClass::Integer
  when :<, :>, :<=, :>=, :==, :'&&', :'||'
    return RubyClass::Boolean
  else
    type_assert(false, "bad operator: #{ast.op}")
  end
end

#check_duplicate(name, t) ⇒ Object



139
140
141
142
143
# File 'lib/yadriggy/c/ctypecheck.rb', line 139

def check_duplicate(name, t)
  old_type = type_env.bound_name?(name)
  type_assert(old_type.nil? || old_type == t,
              "incompatible or duplicate declaration: #{name}")
end

#declare_type(name, name_ast, t) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/yadriggy/c/ctypecheck.rb', line 120

def declare_type(name, name_ast, t)
  if name == 'return' || name == 'foreign'
    type_assert(valid_type?(t) || t == Void,
                "bad return type: #{t.name}")
    check_duplicate(name, t)
    type_env.bind_name(name.to_sym, t)
  elsif name == 'native'
    type_assert(t.is_a?(String), 'bad native argument. not String.')
    type_assert(type_env.bound_name?(:native).nil?,
                'duplicate declaration: native')
    type_env.bind_name(:native, InstanceType.new(t))
  else
    type_assert(valid_type?(t), "bad parameter type: #{name}")
    check_duplicate(name, t)
    bind_local_var(type_env, name_ast, t, false)
  end
end

#is_subsumed_by?(sub_type, super_type) ⇒ Boolean

Returns:

  • (Boolean)


78
79
80
81
# File 'lib/yadriggy/c/ctypecheck.rb', line 78

def is_subsumed_by?(sub_type, super_type)
  (valid_var_type?(sub_type) && valid_var_type?(super_type)) ||
    sub_type <= super_type
end

#method_with_block?(name) ⇒ Boolean

Specifies the names of methods with a block.

Parameters:

  • name (String)

    a method name.

Returns:

  • (Boolean)

See Also:

  • Yadriggy::C::ClangTypeChecker.{CodeGen{CodeGen#call_with_block}
  • Yadriggy::C::ClangTypeChecker.{{#typecheck_call_with_block}


321
322
323
# File 'lib/yadriggy/c/ctypecheck.rb', line 321

def method_with_block?(name)
  name == 'times'
end

#typecheck_call_with_block(call_ast) ⇒ Object



325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/yadriggy/c/ctypecheck.rb', line 325

def typecheck_call_with_block(call_ast)
  type_assert(ast.name.name == 'times',
              "no such method: #{ast.name.name}")
  type_assert(type(ast.receiver) == RubyClass::Integer,
              'the receiver must be an integer')
  type_assert(ast.block.params.size == 1,
              "wrong number of block parameters")
  type_as(ast.block.params[0], RubyClass::Integer)
  tenv = type_env.new_tenv
  tenv.bind_name(ast.block.params[0], RubyClass::Integer)
  tenv.bind_name(:return, Void)
  type(ast.block, tenv)
  Void
end

#typedecl_type(type_expr) ⇒ Object

Parameters:



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/yadriggy/c/ctypecheck.rb', line 101

def typedecl_type(type_expr)
  if type_expr.is_a?(Call)
    type_assert(type_expr.args.size == 1, 'bad array type')
    etype = RubyClass[type_expr.args[0].value]
    type_assert(etype != Undef, 'cannot resolve a type name')
    type_assert(valid_var_type?(etype), "bad array type: #{etype}")
    ArrayType.new(etype)
  else
    rt = type_expr.value
    type_assert(rt != Undef, 'cannot resolve a type name')
    if rt.is_a?(Module) && rt <= FFIArray
      ArrayType.new(RubyClass[rt.element_type])
    else
      RubyClass[rt]
    end
  end
end

#valid_type?(t) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
# File 'lib/yadriggy/c/ctypecheck.rb', line 74

def valid_type?(t)
  valid_var_type?(t) || ArrayType.role(t)
end

#valid_var_type?(t) ⇒ Boolean

Returns:

  • (Boolean)


65
66
67
68
69
70
71
72
# File 'lib/yadriggy/c/ctypecheck.rb', line 65

def valid_var_type?(t)
  if t.is_a?(Type)
    et = t.exact_type
    et == Integer || et == Float || et == String || et == Float32
  else
    false
  end
end