Class: RBS::Substitution

Inherits:
Object
  • Object
show all
Defined in:
sig/substitution.rbs,
lib/rbs/substitution.rb

Overview

Substitution from type variables to types.

The substitution construction is in destructive manner.

sub = Substitution.new
sub.add(from: :A, to: type1)
sub.add(from: :B, to: type2)
sub.instance_type = type3

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSubstitution

Returns a new instance of Substitution.



12
13
14
# File 'lib/rbs/substitution.rb', line 12

def initialize()
  @mapping = {}
end

Instance Attribute Details

#instance_typeTypes::t?

The result of applying this substitution to instance type. nil maps to instance type itself.

Returns:

  • (Types::t, nil)


17
18
19
# File 'sig/substitution.rbs', line 17

def instance_type
  @instance_type
end

#mappingHash[Symbol, Types::t] (readonly)

A hash containing mapping from type variable name to type.

Returns:

  • (Hash[Symbol, Types::t])


13
14
15
# File 'sig/substitution.rbs', line 13

def mapping
  @mapping
end

Class Method Details

.build(variables, types, instance_type: nil, &block) ⇒ void

This method returns an undefined value.

Utility method to construct a substitution. Raises an error when variables.size != types.size. instance_type defaults to nil.

Yields types in types and the block value is used if block is given.

Parameters:

  • variables (Array[Symbol])
  • types (Array[Types::t])
  • instance_type: (Types::t, nil) (defaults to: nil)


31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'sig/substitution.rbs', line 31

def self.build(variables, types, instance_type: nil, &block)
  unless variables.size == types.size
    raise "Broken substitution: variables=#{variables}, types=#{types}"
  end

  mapping = variables.zip(types).to_h

  self.new.tap do |subst|
    mapping.each do |v, t|
      type = block_given? ? yield(t) : t
      subst.add(from: v, to: type)
    end

    subst.instance_type = instance_type
  end
end

Instance Method Details

#+(other) ⇒ Substitution

(s1 + s2)[t] == s2[s1[t]]

Parameters:

Returns:



46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'sig/substitution.rbs', line 46

def +(other)
  return self if other.empty?
  return other if self.empty?

  Substitution.new.tap do |subst|
    subst.mapping.merge!(mapping)

    other.mapping.each do |var, type|
      if mapping.key?(var)
        subst.add(from: var, to: self[type])
      else
        subst.add(from: var, to: type)
      end
    end
  end
end

#add(from:, to:) ⇒ void

This method returns an undefined value.

Add mapping to this substitution. Overwrites the previous mapping if same from is given.

Parameters:

  • from: (Symbol)
  • to: (Types::t)


23
24
25
# File 'sig/substitution.rbs', line 23

def add(from:, to:)
  mapping[from] = to
end

#apply(ty) ⇒ Types::t Also known as: []

Applies the substitution to given type.

Parameters:

  • (Types::t)

Returns:

  • (Types::t)


34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'sig/substitution.rbs', line 34

def apply(ty)
  case ty
  when Types::Variable
    # @type var ty: Types::Variable
    mapping[ty.name] || ty
  when Types::Bases::Instance
    if t = instance_type
      t
    else
      ty
    end
  else
    ty
  end
end

#empty?Boolean

Returns true if given substitution is identity.

Returns:

  • (Boolean)


40
41
42
# File 'sig/substitution.rbs', line 40

def empty?
  mapping.empty? && instance_type.nil?
end

#without(*vars) ⇒ Substitution

Returns a substitution without variables given in vars.

Parameters:

  • vars (Symbol)

Returns:



37
38
39
40
41
42
43
44
45
46
# File 'sig/substitution.rbs', line 37

def without(*vars)
  Substitution.new.tap do |subst|
    subst.mapping.merge!(mapping)
    vars.each do |var|
      subst.mapping.delete(var)
    end

    subst.instance_type = self.instance_type
  end
end