Class: TypeProf::Core::GlobalEnv

Inherits:
Object
  • Object
show all
Defined in:
lib/typeprof/core/env.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeGlobalEnv

Returns a new instance of GlobalEnv.



3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/typeprof/core/env.rb', line 3

def initialize
  @type_table = {}

  @static_eval_queue = []

  @run_queue = []
  @run_queue_set = Set.empty

  @pending_diagnostic_paths = Set.empty

  @mod_object = ModuleEntity.new([])
  @mod_object.inner_modules[:Object] = @mod_object

  @mod_basic_object = resolve_cpath([:BasicObject])
  @mod_class = resolve_cpath([:Class])
  @mod_module = resolve_cpath([:Module])

  @gvars = {}
  @mod_ary = resolve_cpath([:Array])
  @mod_hash = resolve_cpath([:Hash])
  @mod_range = resolve_cpath([:Range])
  @mod_str = resolve_cpath([:String])

  @cls_type = Type::Instance.new(self, @mod_class, [])
  @mod_type = Type::Instance.new(self, @mod_module, [])
  @obj_type = Type::Instance.new(self, resolve_cpath([:Object]), [])
  @nil_type = Type::Instance.new(self, resolve_cpath([:NilClass]), [])
  @true_type = Type::Instance.new(self, resolve_cpath([:TrueClass]), [])
  @false_type = Type::Instance.new(self, resolve_cpath([:FalseClass]), [])
  @str_type = Type::Instance.new(self, resolve_cpath([:String]), [])
  @int_type = Type::Instance.new(self, resolve_cpath([:Integer]), [])
  @float_type = Type::Instance.new(self, resolve_cpath([:Float]), [])
  @rational_type = Type::Instance.new(self, resolve_cpath([:Rational]), [])
  @complex_type = Type::Instance.new(self, resolve_cpath([:Complex]), [])
  @proc_type = Type::Instance.new(self, resolve_cpath([:Proc]), [])
  @symbol_type = Type::Instance.new(self, resolve_cpath([:Symbol]), [])
  @method_type = Type::Instance.new(self, resolve_cpath([:Method]), [])
  @set_type = Type::Instance.new(self, resolve_cpath([:Set]), [])
  @regexp_type = Type::Instance.new(self, resolve_cpath([:Regexp]), [])

  @bot_type = Type::Bot.new(self)

  @run_count = 0
end

Instance Attribute Details

#bot_typeObject (readonly)

Returns the value of attribute bot_type.



55
56
57
# File 'lib/typeprof/core/env.rb', line 55

def bot_type
  @bot_type
end

#cls_typeObject (readonly)

Returns the value of attribute cls_type.



51
52
53
# File 'lib/typeprof/core/env.rb', line 51

def cls_type
  @cls_type
end

#complex_typeObject (readonly)

Returns the value of attribute complex_type.



53
54
55
# File 'lib/typeprof/core/env.rb', line 53

def complex_type
  @complex_type
end

#false_typeObject (readonly)

Returns the value of attribute false_type.



52
53
54
# File 'lib/typeprof/core/env.rb', line 52

def false_type
  @false_type
end

#float_typeObject (readonly)

Returns the value of attribute float_type.



53
54
55
# File 'lib/typeprof/core/env.rb', line 53

def float_type
  @float_type
end

#int_typeObject (readonly)

Returns the value of attribute int_type.



53
54
55
# File 'lib/typeprof/core/env.rb', line 53

def int_type
  @int_type
end

#method_typeObject (readonly)

Returns the value of attribute method_type.



54
55
56
# File 'lib/typeprof/core/env.rb', line 54

def method_type
  @method_type
end

#mod_aryObject (readonly)

Returns the value of attribute mod_ary.



50
51
52
# File 'lib/typeprof/core/env.rb', line 50

def mod_ary
  @mod_ary
end

#mod_classObject (readonly)

Returns the value of attribute mod_class.



50
51
52
# File 'lib/typeprof/core/env.rb', line 50

def mod_class
  @mod_class
end

#mod_hashObject (readonly)

Returns the value of attribute mod_hash.



50
51
52
# File 'lib/typeprof/core/env.rb', line 50

def mod_hash
  @mod_hash
end

#mod_objectObject (readonly)

Returns the value of attribute mod_object.



50
51
52
# File 'lib/typeprof/core/env.rb', line 50

def mod_object
  @mod_object
end

#mod_rangeObject (readonly)

Returns the value of attribute mod_range.



50
51
52
# File 'lib/typeprof/core/env.rb', line 50

def mod_range
  @mod_range
end

#mod_strObject (readonly)

Returns the value of attribute mod_str.



50
51
52
# File 'lib/typeprof/core/env.rb', line 50

def mod_str
  @mod_str
end

#mod_typeObject (readonly)

Returns the value of attribute mod_type.



51
52
53
# File 'lib/typeprof/core/env.rb', line 51

def mod_type
  @mod_type
end

#nil_typeObject (readonly)

Returns the value of attribute nil_type.



52
53
54
# File 'lib/typeprof/core/env.rb', line 52

def nil_type
  @nil_type
end

#obj_typeObject (readonly)

Returns the value of attribute obj_type.



52
53
54
# File 'lib/typeprof/core/env.rb', line 52

def obj_type
  @obj_type
end

#proc_typeObject (readonly)

Returns the value of attribute proc_type.



54
55
56
# File 'lib/typeprof/core/env.rb', line 54

def proc_type
  @proc_type
end

#rational_typeObject (readonly)

Returns the value of attribute rational_type.



53
54
55
# File 'lib/typeprof/core/env.rb', line 53

def rational_type
  @rational_type
end

#regexp_typeObject (readonly)

Returns the value of attribute regexp_type.



54
55
56
# File 'lib/typeprof/core/env.rb', line 54

def regexp_type
  @regexp_type
end

#run_countObject

Returns the value of attribute run_count.



69
70
71
# File 'lib/typeprof/core/env.rb', line 69

def run_count
  @run_count
end

#set_typeObject (readonly)

Returns the value of attribute set_type.



54
55
56
# File 'lib/typeprof/core/env.rb', line 54

def set_type
  @set_type
end

#str_typeObject (readonly)

Returns the value of attribute str_type.



52
53
54
# File 'lib/typeprof/core/env.rb', line 52

def str_type
  @str_type
end

#symbol_typeObject (readonly)

Returns the value of attribute symbol_type.



54
55
56
# File 'lib/typeprof/core/env.rb', line 54

def symbol_type
  @symbol_type
end

#true_typeObject (readonly)

Returns the value of attribute true_type.



52
53
54
# File 'lib/typeprof/core/env.rb', line 52

def true_type
  @true_type
end

#type_tableObject (readonly)

Returns the value of attribute type_table.



48
49
50
# File 'lib/typeprof/core/env.rb', line 48

def type_table
  @type_table
end

Instance Method Details

#add_diagnostic_path(path) ⇒ Object



217
218
219
# File 'lib/typeprof/core/env.rb', line 217

def add_diagnostic_path(path)
  @pending_diagnostic_paths << path unless @pending_diagnostic_paths.include?(path)
end

#add_run(obj) ⇒ Object



188
189
190
191
192
193
# File 'lib/typeprof/core/env.rb', line 188

def add_run(obj)
  unless @run_queue_set.include?(obj)
    @run_queue << obj
    @run_queue_set << obj
  end
end

#add_static_eval_queue(change_type, arg) ⇒ Object



161
162
163
# File 'lib/typeprof/core/env.rb', line 161

def add_static_eval_queue(change_type, arg)
  @static_eval_queue << [change_type, arg]
end

#define_allObject



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/typeprof/core/env.rb', line 165

def define_all
  until @static_eval_queue.empty?
    change_type, arg = @static_eval_queue.shift
    case change_type
    when :inner_modules_changed
      arg[0].on_inner_modules_changed(self, arg[1])
    when :static_read_changed
      case arg
      when BaseStaticRead
        arg.on_scope_updated(self)
      when ScopedStaticRead
        arg.on_cbase_updated(self)
      else
        raise
      end
    when :parent_modules_changed
      arg.on_parent_modules_changed(self)
    else
      raise change_type.to_s
    end
  end
end

#each_direct_superclass(mod, singleton) ⇒ Object



71
72
73
74
75
76
# File 'lib/typeprof/core/env.rb', line 71

def each_direct_superclass(mod, singleton)
  while mod
    yield mod, singleton
    singleton, mod = get_superclass(singleton, mod)
  end
end

#each_extended_module(mod, &blk) ⇒ Object



98
99
100
101
102
103
104
105
# File 'lib/typeprof/core/env.rb', line 98

def each_extended_module(mod, &blk)
  # An extended module contributes its instance methods (singleton = false)
  # as the receiver's singleton methods.
  mod.extended_modules.each do |_ext_decl, ext_mod|
    yield ext_mod, false
    each_included_module(ext_mod, &blk)
  end
end

#each_included_module(mod, &blk) ⇒ Object



91
92
93
94
95
96
# File 'lib/typeprof/core/env.rb', line 91

def each_included_module(mod, &blk)
  mod.included_modules.each do |_inc_decl, inc_mod|
    yield inc_mod, false
    each_included_module(inc_mod, &blk)
  end
end

#each_superclass(mod, singleton, &blk) ⇒ Object



78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/typeprof/core/env.rb', line 78

def each_superclass(mod, singleton, &blk)
  while mod
    # TODO: prepended modules
    yield mod, singleton
    if singleton
      each_extended_module(mod, &blk)
    else
      each_included_module(mod, &blk)
    end
    singleton, mod = get_superclass(singleton, mod)
  end
end

#follow_alias(mod) ⇒ Object



241
242
243
244
245
246
247
248
249
250
# File 'lib/typeprof/core/env.rb', line 241

def follow_alias(mod)
  visited = nil
  while mod.alias_target
    visited ||= Set.empty
    break if visited.include?(mod) # cycle
    visited << mod
    mod = mod.alias_target
  end
  mod
end

#gen_ary_type(elem_vtx) ⇒ Object



57
58
59
# File 'lib/typeprof/core/env.rb', line 57

def gen_ary_type(elem_vtx)
  Type::Instance.new(self, @mod_ary, [elem_vtx])
end

#gen_hash_type(key_vtx, val_vtx) ⇒ Object



61
62
63
# File 'lib/typeprof/core/env.rb', line 61

def gen_hash_type(key_vtx, val_vtx)
  Type::Instance.new(self, @mod_hash, [key_vtx, val_vtx])
end

#gen_range_type(elem_vtx) ⇒ Object



65
66
67
# File 'lib/typeprof/core/env.rb', line 65

def gen_range_type(elem_vtx)
  Type::Instance.new(self, @mod_range, [elem_vtx])
end

#get_instance_type(mod, type_args, changes, base_ty_env, base_ty) ⇒ Object



129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/typeprof/core/env.rb', line 129

def get_instance_type(mod, type_args, changes, base_ty_env, base_ty)
  ty_env = base_ty_env.dup
  if base_ty.is_a?(Type::Instance)
    base_ty.mod.type_params.zip(base_ty.args) do |(param, default_ty), arg|
      ty_env[param] = arg || (default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new)
    end
  elsif base_ty.is_a?(Type::Singleton)
    base_ty.mod.type_params&.each do |(param, default_ty)|
      ty_env[param] = default_ty ? default_ty.covariant_vertex(self, changes, ty_env) : Source.new
    end
  end
  args = mod.type_params.zip(type_args).map do |(param, default_ty), arg|
    if changes
      (arg || default_ty)&.covariant_vertex(self, changes, ty_env) || Source.new
    else
      Source.new
    end
  end
  Type::Instance.new(self, mod, args)
end

#get_superclass(singleton, mod) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/typeprof/core/env.rb', line 107

def get_superclass(singleton, mod)
  super_mod = mod.superclass
  if super_mod
    return [singleton, super_mod]
  else
    if mod == @mod_basic_object
      if singleton
        return [false, @mod_class]
      else
        return nil
      end
    elsif mod == @mod_object
      # Unresolved while loading the core RBS; the Module fallback below would cycle
      return [singleton, @mod_basic_object]
    elsif mod == @mod_module && !singleton
      return nil
    else
      return [false, @mod_module]
    end
  end
end

#get_superclass_type(ty, changes, base_ty_env) ⇒ Object



150
151
152
153
154
155
156
157
158
159
# File 'lib/typeprof/core/env.rb', line 150

def get_superclass_type(ty, changes, base_ty_env)
  singleton, super_mod = get_superclass(ty.is_a?(Type::Singleton), ty.mod)
  return unless super_mod

  if singleton
    Type::Singleton.new(self, super_mod)
  else
    get_instance_type(super_mod, ty.mod.superclass_type_args || [], changes, base_ty_env, ty)
  end
end

#get_vertexes(vtxs) ⇒ Object

just for validation



222
223
224
225
226
227
# File 'lib/typeprof/core/env.rb', line 222

def get_vertexes(vtxs)
  @mod_object.get_vertexes(vtxs)
  @gvars.each_value do |gvar_entity|
    vtxs << gvar_entity.vtx
  end
end

#load_core_rbs(raw_decls, position_encoding) ⇒ Object



286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
# File 'lib/typeprof/core/env.rb', line 286

def load_core_rbs(raw_decls, position_encoding)
  file_context = FileContext.new(nil, position_encoding)
  lenv = LocalEnv.new(file_context, CRef::Toplevel, {}, [])
  decls = raw_decls.map do |raw_decl|
    AST.create_rbs_decl(raw_decl, lenv)
  end.compact

  decls += AST.parse_rbs("typeprof-rbs-shim.rbs", <<-RBS, position_encoding)
    class Exception
      include _Exception
    end
    class String
      include _ToS
      include _ToStr
    end
    class Array[Elem]
      include _ToAry[Elem]
      include _Each[Elem]
    end
    class Hash[K, V]
      include _Each[[K, V]]
    end
    class Object
      include Hash::_Key
    end
  RBS

  # Loading frequently used modules first will reduces constant resolution
  # which makes loading faster :-)
  critical_modules = [
    decls.find {|decl| decl.cpath == [:Object] },
    decls.find {|decl| decl.cpath == [:Module] },
    decls.find {|decl| decl.cpath == [:Numeric] },
    decls.find {|decl| decl.cpath == [:Integer] },
    decls.find {|decl| decl.cpath == [:String] },
    decls.find {|decl| decl.cpath == [:Array] },
    decls.find {|decl| decl.cpath == [:Hash] },
    decls.find {|decl| decl.cpath == [:Enumerator] },
  ]
  decls = critical_modules + (decls - critical_modules)

  decls.each {|decl| decl.define(self) }
  define_all
  decls.each {|decl| decl.install(self) }
  run_all
end

#process_diagnostic_pathsObject



208
209
210
211
212
213
214
215
# File 'lib/typeprof/core/env.rb', line 208

def process_diagnostic_paths
  processed_paths = []
  @pending_diagnostic_paths.each do |path|
    processed = yield path
    processed_paths << path if processed
  end
  processed_paths.each {|path| @pending_diagnostic_paths.delete(path) }
end

#resolve_const(cpath) ⇒ Object

constants



254
255
256
257
# File 'lib/typeprof/core/env.rb', line 254

def resolve_const(cpath)
  mod = resolve_cpath(cpath[0..-2])
  mod.get_const(cpath[-1])
end

#resolve_cpath(cpath) ⇒ Object

classes and modules



231
232
233
234
235
236
237
238
239
# File 'lib/typeprof/core/env.rb', line 231

def resolve_cpath(cpath)
  mod = @mod_object
  raise unless cpath # annotation
  cpath.each do |cname|
    mod = mod.inner_modules[cname] ||= ModuleEntity.new(mod.cpath + [cname], mod)
    mod = follow_alias(mod)
  end
  mod
end

#resolve_cvar(cpath, name) ⇒ Object



274
275
276
277
278
# File 'lib/typeprof/core/env.rb', line 274

def resolve_cvar(cpath, name)
  # TODO: include はあとで考える
  mod = resolve_cpath(cpath)
  mod.get_cvar(name)
end

#resolve_gvar(name) ⇒ Object



264
265
266
# File 'lib/typeprof/core/env.rb', line 264

def resolve_gvar(name)
  @gvars[name] ||= ValueEntity.new
end

#resolve_ivar(cpath, singleton, name) ⇒ Object



268
269
270
271
272
# File 'lib/typeprof/core/env.rb', line 268

def resolve_ivar(cpath, singleton, name)
  # TODO: include はあとで考える
  mod = resolve_cpath(cpath)
  mod.get_ivar(singleton, name)
end

#resolve_method(cpath, singleton, mid) ⇒ Object



259
260
261
262
# File 'lib/typeprof/core/env.rb', line 259

def resolve_method(cpath, singleton, mid)
  mod = resolve_cpath(cpath)
  mod.get_method(singleton, mid)
end

#resolve_type_alias(cpath, name) ⇒ Object



280
281
282
283
284
# File 'lib/typeprof/core/env.rb', line 280

def resolve_type_alias(cpath, name)
  # TODO: include はあとで考える
  mod = resolve_cpath(cpath)
  mod.get_type_alias(name)
end

#run_allObject



195
196
197
198
199
200
201
202
203
204
205
206
# File 'lib/typeprof/core/env.rb', line 195

def run_all
  run_count = 0
  until @run_queue.empty?
    obj = @run_queue.shift
    @run_queue_set.delete(obj)
    unless obj.destroyed
      run_count += 1
      obj.run(self)
    end
  end
  @run_count += run_count
end