Class: Carbon::Concrete::Type::Generic

Inherits:
Object
  • Object
show all
Defined in:
lib/carbon/concrete/type/generic.rb

Overview

Note:

This class is frozen upon initialization. This means that any attempt to modify it will result in an error. In most cases, the attributes on this class will also be frozen, as well.

A generic part of a type. This is normally the T in Carbon::Pointer<T>. Generic portions can also have traits that the generic type must implement; this keeps track of that too. A complete example, containing traits, would look like this: Carbon::Pointer<T: Carbon::Sized + Carbon::Numeric>. The actual pointer type may not use those traits.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, implements, location: nil) ⇒ Generic

Initialize the generic part of the type.

Parameters:

  • name (Type)

    The name of the generic.

  • implements (Set<Type>)

    The traits the generic must implement, if any.

See Also:



58
59
60
61
62
63
# File 'lib/carbon/concrete/type/generic.rb', line 58

def initialize(name, implements, location: nil)
  @location = location
  @name = name
  @implements = Set.new(implements)
  deep_freeze!
end

Instance Attribute Details

#implementsSet<Type> (readonly)

The implements of the generic. These are the traits that the generic parameter has to implement; this allows the generic code to make assumptions about the generic type (such as behavior or size) that would otherwise be impossible to make.

Examples:

name = "Carbon::Pointer<T: Carbon::Sized>"
type = Carbon::Type(name)
type.generics.first.implements
  # => Set[#<Carbon::Concrete::Type Carbon::Sized>]

Returns:

  • (Set<Type>)

    The traits the generic has to implement.



42
43
44
# File 'lib/carbon/concrete/type/generic.rb', line 42

def implements
  @implements
end

#locationObject (readonly)

The location of the type. This is used for interfacing with other programs that require a location of some sort.

Returns:

  • (Object)


49
50
51
# File 'lib/carbon/concrete/type/generic.rb', line 49

def location
  @location
end

#nameType (readonly)

The name of the generic. This is the generic type variable that is substituted in later for an actual value. This is normally a single character module name, but can be as complicated as needed.

Examples:

type = Carbon::Type("Carbon::Pointer<T>")
type.generics.first.name # => #<Carbon::Concrete::Type T>

Returns:

  • (Type)

    The name.



28
29
30
# File 'lib/carbon/concrete/type/generic.rb', line 28

def name
  @name
end

Instance Method Details

#==(other) ⇒ ::Boolean Also known as: eql?

Compares this generic instance to another generic instance. If the other generic instance is this generic instance it returns true; otherwise, if the other value is a generic, and that generic's #to_s is equal to this one's, it returns true; otherwise, it returns false.

Examples:

type1 = Carbon::Type("Carbon::Pointer<T>")
type2 = Carbon::Type("Carbon::List<T>")
type1.generics == type2.generics # => true

Parameters:

Returns:

  • (::Boolean)

    True if the two are equivalent.



99
100
101
102
# File 'lib/carbon/concrete/type/generic.rb', line 99

def ==(other)
  equal?(other) ||
    (other.is_a?(Type::Generic) && other.to_s == to_s)
end

#accept(visitor, *params) ⇒ Object

Accepts the current visitor unto itself.

Parameters:

  • visitor (#visit)

Returns:

  • (Object)


128
129
130
# File 'lib/carbon/concrete/type/generic.rb', line 128

def accept(visitor, *params)
  visitor.visit(self, *params)
end

#sub(mapping) ⇒ Type::Generic, self

Returns the correct generic. This is a weird function, but essentially, if the #name's Carbon::Concrete::Type#intern is oen of the keys of the mapping, it returns the new generic; otherwise, it returns this object.

Examples:

generic.to_s # => "T: Carbon::Sized"
generic.is_a?(Generic) # => true
other.to_s # => "Carbon::String"
other.is_a?(Generic) # => true
result = generic.sub("T" => other)
result.to_s # => "Carbon::String: Carbon::Sized"

Parameters:

  • mapping ({::String => Type})

    The mapping.

Returns:

  • (Type::Generic)

    A different instance of the generic, if it's in the mapping.

  • (self)

    otherwise.



82
83
84
# File 'lib/carbon/concrete/type/generic.rb', line 82

def sub(mapping)
  Generic.new(mapping.fetch(@name, @name), @implements)
end

#to_s::String

A string representation of the generic. If there are no implements, this is a direct call to #name's Carbon::Concrete::Type#to_s; otherwise, this includes the name with a joined string of implements.

Examples:

name = "Carbon::Pointer<T: Carbon::Sized>"
type = Carbon::Type(name)
type.generics.first.to_s # => "T: Carbon::Sized"

Returns:

  • (::String)

    The string representation.



116
117
118
119
120
121
122
# File 'lib/carbon/concrete/type/generic.rb', line 116

def to_s
  if @implements.any?
    "#{@name}: #{@implements.map(&:to_s).join(' + ')}".freeze
  else
    @name.to_s
  end
end