Class: RDL::Typecheck::Env
Overview
Local variable environment tracks the types of local variables, and whether they’re “fixed,” i.e., whether they should be treated flow-insensitively
Instance Attribute Summary collapse
-
#env ⇒ Object
Returns the value of attribute env.
Class Method Summary collapse
-
.join(e, *envs) ⇒ Object
- + envs +
-
is Array<Env> any elts of envs that are nil are discarded returns new Env where every key is mapped to the union of its bindings in the envs any fixed binding in any env must be fixed in all envs and at the same type.
Instance Method Summary collapse
- #==(other) ⇒ Object
-
#[](var) ⇒ Object
- + var +
-
is a Symbol.
-
#bind(var, typ, force: false) ⇒ Object
force should only be used with care! currently only used when type is being refined to a subtype in a lexical scope.
- #fix(var, typ) ⇒ Object
- #fixed?(var) ⇒ Boolean
- #has_key?(var) ⇒ Boolean
-
#initialize(params = nil) ⇒ Env
constructor
- + params +
-
is a map from Symbols to Types.
-
#merge(other) ⇒ Object
merges bindings in self with bindings in other, preferring bindings in other if there is a common key.
Constructor Details
#initialize(params = nil) ⇒ Env
- + params +
-
is a map from Symbols to Types. This initial variable mapping
is added to the Env, and these initial mappings are fixed. If params is nil, initial Env is empty.
54 55 56 57 58 59 60 61 |
# File 'lib/rdl/typecheck.rb', line 54 def initialize(params = nil) @env = Hash.new unless params.nil? params.each_pair { |var, typ| @env[var] = {type: typ, fixed: true} } end end |
Instance Attribute Details
#env ⇒ Object
Returns the value of attribute env.
49 50 51 |
# File 'lib/rdl/typecheck.rb', line 49 def env @env end |
Class Method Details
.join(e, *envs) ⇒ Object
- + envs +
-
is Array<Env>
any elts of envs that are nil are discarded returns new Env where every key is mapped to the union of its bindings in the envs any fixed binding in any env must be fixed in all envs and at the same type
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/rdl/typecheck.rb', line 107 def self.join(e, *envs) raise RuntimeError, "Expecting AST, got #{e.class}" unless e.is_a? AST::Node env = Env.new envs.delete(nil) return env if envs.empty? return envs[0] if envs.size == 1 first = envs[0] rest = envs[1..-1] first.env.each_pair { |var, h| first_typ = h[:type] if h[:fixed] error :inconsistent_var_type, [var.to_s], e unless rest.all? { |other| (other.fixed? var) || (not (other.has_key? var)) } neq = [] rest.each { |other| other_typ = other[var] neq << other_typ unless first_typ == other_typ } error :inconsistent_var_type_type, [var.to_s, (first_typ + neq).map { |t| t.to_s }.join(' and ')], e unless neq.empty? env.env[var] = {type: h[:type], fixed: true} else typ = RDL::Type::UnionType.new(first_typ, *rest.map { |other| ((other.has_key? var) && other[var]) || $__rdl_nil_type }) typ = typ.canonical env.env[var] = {type: typ, fixed: false} end } return env end |
Instance Method Details
#==(other) ⇒ Object
91 92 93 94 |
# File 'lib/rdl/typecheck.rb', line 91 def ==(other) return false unless other.is_a? Env return @env == other.env end |
#[](var) ⇒ Object
- + var +
-
is a Symbol
64 65 66 |
# File 'lib/rdl/typecheck.rb', line 64 def [](var) return @env[var][:type] end |
#bind(var, typ, force: false) ⇒ Object
force should only be used with care! currently only used when type is being refined to a subtype in a lexical scope
69 70 71 72 73 74 |
# File 'lib/rdl/typecheck.rb', line 69 def bind(var, typ, force: false) raise RuntimeError, "Can't update variable with fixed type" if !force && @env[var] && @env[var][:fixed] result = Env.new result.env = @env.merge(var => {type: typ, fixed: false}) return result end |
#fix(var, typ) ⇒ Object
80 81 82 83 84 85 |
# File 'lib/rdl/typecheck.rb', line 80 def fix(var, typ) raise RuntimeError, "Can't fix type of already-bound variable" if @env[var] result = Env.new result.env = @env.merge(var => {type: typ, fixed: true}) return result end |
#fixed?(var) ⇒ Boolean
87 88 89 |
# File 'lib/rdl/typecheck.rb', line 87 def fixed?(var) return @env[var] && @env[var][:fixed] end |
#has_key?(var) ⇒ Boolean
76 77 78 |
# File 'lib/rdl/typecheck.rb', line 76 def has_key?(var) return @env.has_key?(var) end |
#merge(other) ⇒ Object
merges bindings in self with bindings in other, preferring bindings in other if there is a common key
97 98 99 100 101 |
# File 'lib/rdl/typecheck.rb', line 97 def merge(other) result = Env.new result.env = @env.merge(other.env) return result end |