Class: Steep::TypeInference::TypeEnv
- Inherits:
-
Object
- Object
- Steep::TypeInference::TypeEnv
- Defined in:
- lib/steep/type_inference/type_env.rb
Instance Attribute Summary collapse
-
#const_env ⇒ Object
readonly
Returns the value of attribute const_env.
-
#const_types ⇒ Object
readonly
Returns the value of attribute const_types.
-
#gvar_types ⇒ Object
readonly
Returns the value of attribute gvar_types.
-
#ivar_types ⇒ Object
readonly
Returns the value of attribute ivar_types.
-
#lvar_types ⇒ Object
readonly
Returns the value of attribute lvar_types.
-
#subtyping ⇒ Object
readonly
Returns the value of attribute subtyping.
Class Method Summary collapse
Instance Method Summary collapse
- #assert_annotation(name, annotated_type:, original_type:) ⇒ Object
- #assert_assign(var_type:, lhs_type:) ⇒ Object
- #assign(lvar: nil, const: nil, gvar: nil, ivar: nil, type:, &block) ⇒ Object
- #get(lvar: nil, const: nil, gvar: nil, ivar: nil) ⇒ Object
-
#initialize(subtyping:, const_env:) ⇒ TypeEnv
constructor
A new instance of TypeEnv.
- #initialize_copy(other) ⇒ Object
- #join!(envs) ⇒ Object
- #lookup_dictionary(ivar:, gvar:) ⇒ Object
- #lvar_name(lvar) ⇒ Object
- #merge!(original_env:, override_env:, &block) ⇒ Object
- #set(lvar: nil, const: nil, gvar: nil, ivar: nil, type:) ⇒ Object
- #with_annotations(lvar_types: {}, ivar_types: {}, const_types: {}, gvar_types: {}, &block) ⇒ Object
Constructor Details
#initialize(subtyping:, const_env:) ⇒ TypeEnv
Returns a new instance of TypeEnv.
11 12 13 14 15 16 17 18 |
# File 'lib/steep/type_inference/type_env.rb', line 11 def initialize(subtyping:, const_env:) @subtyping = subtyping @lvar_types = {} @const_types = {} @gvar_types = {} @ivar_types = {} @const_env = const_env end |
Instance Attribute Details
#const_env ⇒ Object (readonly)
Returns the value of attribute const_env.
9 10 11 |
# File 'lib/steep/type_inference/type_env.rb', line 9 def const_env @const_env end |
#const_types ⇒ Object (readonly)
Returns the value of attribute const_types.
6 7 8 |
# File 'lib/steep/type_inference/type_env.rb', line 6 def const_types @const_types end |
#gvar_types ⇒ Object (readonly)
Returns the value of attribute gvar_types.
7 8 9 |
# File 'lib/steep/type_inference/type_env.rb', line 7 def gvar_types @gvar_types end |
#ivar_types ⇒ Object (readonly)
Returns the value of attribute ivar_types.
8 9 10 |
# File 'lib/steep/type_inference/type_env.rb', line 8 def ivar_types @ivar_types end |
#lvar_types ⇒ Object (readonly)
Returns the value of attribute lvar_types.
5 6 7 |
# File 'lib/steep/type_inference/type_env.rb', line 5 def lvar_types @lvar_types end |
#subtyping ⇒ Object (readonly)
Returns the value of attribute subtyping.
4 5 6 |
# File 'lib/steep/type_inference/type_env.rb', line 4 def subtyping @subtyping end |
Class Method Details
.build(annotations:, signatures:, subtyping:, const_env:) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/steep/type_inference/type_env.rb', line 29 def self.build(annotations:, signatures:, subtyping:, const_env:) new(subtyping: subtyping, const_env: const_env).tap do |env| annotations.lvar_types.each do |name, type| env.set(lvar: name, type: type) end annotations.ivar_types.each do |name, type| env.set(ivar: name, type: type) end annotations.const_types.each do |name, type| env.set(const: name, type: type) end signatures.globals.each do |name, annot| type = subtyping.builder.absolute_type(annot.type, current: AST::Namespace.root) env.set(gvar: name, type: type) end end end |
Instance Method Details
#assert_annotation(name, annotated_type:, original_type:) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 |
# File 'lib/steep/type_inference/type_env.rb', line 217 def assert_annotation(name, annotated_type:, original_type:) annotated_type = subtyping.(annotated_type) original_type = subtyping.(original_type) relation = Subtyping::Relation.new(sub_type: annotated_type, super_type: original_type) constraints = Subtyping::Constraints.new(unknowns: Set.new) subtyping.check(relation, constraints: constraints).else do |result| yield name, relation, result end annotated_type end |
#assert_assign(var_type:, lhs_type:) ⇒ Object
197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/steep/type_inference/type_env.rb', line 197 def assert_assign(var_type:, lhs_type:) var_type = subtyping.(var_type) lhs_type = subtyping.(lhs_type) relation = Subtyping::Relation.new(sub_type: lhs_type, super_type: var_type) constraints = Subtyping::Constraints.new(unknowns: Set.new) subtyping.check(relation, constraints: constraints).else do |result| yield result end var_type end |
#assign(lvar: nil, const: nil, gvar: nil, ivar: nil, type:, &block) ⇒ Object
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
# File 'lib/steep/type_inference/type_env.rb', line 145 def assign(lvar: nil, const: nil, gvar: nil, ivar: nil, type:, &block) case when lvar yield_self do name = lvar_name(lvar) var_type = lvar_types[name] if var_type assert_assign(var_type: var_type, lhs_type: type, &block) else lvar_types[name] = type end end when const yield_self do const_type = const_types[const] || const_env.lookup(const) if const_type assert_assign(var_type: const_type, lhs_type: type, &block) else yield nil AST::Types::Any.new end end else lookup_dictionary(ivar: ivar, gvar: gvar) do |var_name, dictionary| if dictionary.key?(var_name) assert_assign(var_type: dictionary[var_name], lhs_type: type, &block) else yield nil AST::Types::Any.new end end end end |
#get(lvar: nil, const: nil, gvar: nil, ivar: nil) ⇒ Object
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/steep/type_inference/type_env.rb', line 90 def get(lvar: nil, const: nil, gvar: nil, ivar: nil) case when lvar lvar_name(lvar).yield_self do |name| if lvar_types.key?(name) lvar_types[name] else ty = yield lvar_types[name] = ty || AST::Types::Any.new end end when const if const_types.key?(const) const_types[const] else const_env.lookup(const).yield_self do |type| if type type else yield AST::Types::Any.new end end end else lookup_dictionary(ivar: ivar, gvar: gvar) do |var_name, dictionary| if dictionary.key?(var_name) dictionary[var_name] else yield AST::Types::Any.new end end end end |
#initialize_copy(other) ⇒ Object
20 21 22 23 24 25 26 27 |
# File 'lib/steep/type_inference/type_env.rb', line 20 def initialize_copy(other) @subtyping = other.subtyping @lvar_types = other.lvar_types.dup @const_types = other.const_types.dup @gvar_types = other.gvar_types.dup @ivar_types = other.ivar_types.dup @const_env = other.const_env end |
#join!(envs) ⇒ Object
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/steep/type_inference/type_env.rb', line 63 def join!(envs) lvars = {} common_vars = envs.map {|env| Set.new(env.lvar_types.keys) }.inject {|a, b| a & b } envs.each do |env| env.lvar_types.each do |name, type| unless lvar_types.key?(name) lvars[name] = [] unless lvars[name] lvars[name] << type end end end lvars.each do |name, types| if lvar_types.key?(name) || common_vars.member?(name) set(lvar: name, type: AST::Types::Union.build(types: types)) else set(lvar: name, type: AST::Types::Union.build(types: types + [AST::Types::Nil.new])) end end end |
#lookup_dictionary(ivar:, gvar:) ⇒ Object
179 180 181 182 183 184 185 186 |
# File 'lib/steep/type_inference/type_env.rb', line 179 def lookup_dictionary(ivar:, gvar:) case when ivar yield ivar, ivar_types when gvar yield gvar, gvar_types end end |
#lvar_name(lvar) ⇒ Object
188 189 190 191 192 193 194 195 |
# File 'lib/steep/type_inference/type_env.rb', line 188 def lvar_name(lvar) case lvar when Symbol lvar when ASTUtils::Labeling::LabeledName lvar.name end end |
#merge!(original_env:, override_env:, &block) ⇒ Object
211 212 213 214 215 |
# File 'lib/steep/type_inference/type_env.rb', line 211 def merge!(original_env:, override_env:, &block) original_env.merge!(override_env) do |name, original_type, override_type| assert_annotation name, annotated_type: override_type, original_type: original_type, &block end end |
#set(lvar: nil, const: nil, gvar: nil, ivar: nil, type:) ⇒ Object
126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/steep/type_inference/type_env.rb', line 126 def set(lvar: nil, const: nil, gvar: nil, ivar: nil, type:) case when lvar lvar_name(lvar).yield_self do |name| lvar_types[name] = type end when const const_types[const] = type else lookup_dictionary(ivar: ivar, gvar: gvar) do |var_name, dictionary| dictionary[var_name] = type end end end |
#with_annotations(lvar_types: {}, ivar_types: {}, const_types: {}, gvar_types: {}, &block) ⇒ Object
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/steep/type_inference/type_env.rb', line 47 def with_annotations(lvar_types: {}, ivar_types: {}, const_types: {}, gvar_types: {}, &block) dup.tap do |env| merge!(original_env: env.lvar_types, override_env: lvar_types, &block) merge!(original_env: env.ivar_types, override_env: ivar_types, &block) merge!(original_env: env.gvar_types, override_env: gvar_types, &block) const_types.each do |name, annotated_type| original_type = self.const_types[name] || const_env.lookup(name) if original_type assert_annotation name, original_type: original_type, annotated_type: annotated_type, &block end env.const_types[name] = annotated_type end end end |