carbon-core 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitattributes +17 -0
- data/.gitignore +0 -0
- data/.rspec +0 -0
- data/.rubocop.yml +0 -0
- data/.travis.yml +0 -0
- data/.yardopts +0 -0
- data/CODE_OF_CONDUCT.md +0 -0
- data/Gemfile +0 -0
- data/LICENSE.txt +0 -0
- data/README.md +0 -0
- data/Rakefile +0 -0
- data/Vagrantfile +0 -0
- data/carbon.gemspec +0 -0
- data/lib/carbon.rb +25 -1
- data/lib/carbon/concrete.rb +4 -2
- data/lib/carbon/concrete/build.rb +21 -13
- data/lib/carbon/concrete/index.rb +53 -159
- data/lib/carbon/concrete/item.rb +0 -0
- data/lib/carbon/concrete/item/base.rb +14 -27
- data/lib/carbon/concrete/item/class.rb +71 -0
- data/lib/carbon/concrete/item/class/element.rb +42 -0
- data/lib/carbon/concrete/item/data.rb +0 -0
- data/lib/carbon/concrete/item/function.rb +35 -39
- data/lib/carbon/concrete/item/internal.rb +17 -19
- data/lib/carbon/concrete/item/struct.rb +12 -7
- data/lib/carbon/concrete/item/struct/element.rb +0 -0
- data/lib/carbon/concrete/item/trait.rb +9 -10
- data/lib/carbon/concrete/item/trait/expectation.rb +0 -0
- data/lib/carbon/concrete/request.rb +137 -136
- data/lib/carbon/concrete/type.rb +126 -21
- data/lib/carbon/concrete/type/function.rb +26 -10
- data/lib/carbon/concrete/type/generic.rb +19 -3
- data/lib/carbon/concrete/type/name.rb +0 -0
- data/lib/carbon/concrete/type/parse.rb +1 -0
- data/lib/carbon/concrete/type/part.rb +9 -1
- data/lib/carbon/core.rb +6 -1
- data/lib/carbon/core/int.rb +0 -0
- data/lib/carbon/core/integer.rb +0 -0
- data/lib/carbon/core/integer/cast.rb +0 -0
- data/lib/carbon/core/integer/math.rb +0 -0
- data/lib/carbon/core/integer/misc.rb +17 -1
- data/lib/carbon/core/integer/pole.rb +0 -0
- data/lib/carbon/core/integer/ship.rb +8 -4
- data/lib/carbon/core/integer/sign.rb +0 -0
- data/lib/carbon/core/integer/type.rb +0 -0
- data/lib/carbon/core/integer/zero.rb +0 -0
- data/lib/carbon/core/main.rb +50 -0
- data/lib/carbon/core/pointer.rb +0 -0
- data/lib/carbon/core/pointer/access.rb +1 -1
- data/lib/carbon/core/pointer/cast.rb +0 -0
- data/lib/carbon/core/pointer/math.rb +14 -0
- data/lib/carbon/core/pointer/memory.rb +2 -4
- data/lib/carbon/core/pointer/type.rb +0 -0
- data/lib/carbon/core/void.rb +20 -0
- data/lib/carbon/counter.rb +27 -0
- data/lib/carbon/errors.rb +13 -0
- data/lib/carbon/tacky.rb +0 -0
- data/lib/carbon/tacky/block.rb +0 -0
- data/lib/carbon/tacky/builder.rb +3 -6
- data/lib/carbon/tacky/context.rb +4 -10
- data/lib/carbon/tacky/function.rb +0 -24
- data/lib/carbon/tacky/instruction.rb +2 -5
- data/lib/carbon/tacky/instruction/generation.rb +19 -41
- data/lib/carbon/tacky/parameter.rb +0 -0
- data/lib/carbon/tacky/reference.rb +0 -0
- data/lib/carbon/tacky/typed.rb +0 -0
- data/lib/carbon/tacky/value.rb +0 -2
- data/lib/carbon/version.rb +1 -1
- data/scripts/core.rb +0 -0
- data/scripts/test.rb +5 -7
- metadata +9 -4
- data/lib/carbon/tacky/instruction/dependencies.rb +0 -33
- data/lib/carbon/tacky/instruction/typeof.rb +0 -25
File without changes
|
@@ -19,7 +19,7 @@ module Carbon
|
|
19
19
|
|
20
20
|
# (see Item::Base.from)
|
21
21
|
def self.from(type)
|
22
|
-
{
|
22
|
+
{ type: type, expectations: [] }
|
23
23
|
end
|
24
24
|
|
25
25
|
# The expectations for the trait.
|
@@ -34,14 +34,13 @@ module Carbon
|
|
34
34
|
# Initialize the trait with data.
|
35
35
|
#
|
36
36
|
# @param data [::Hash] The data to initialize the trait with.
|
37
|
-
# @option data [Type] :
|
37
|
+
# @option data [Type] :type The name of the trait type.
|
38
38
|
# @option data [<(::String, <Type>, Type)>] :expectations
|
39
39
|
# The expectations that the trait requires.
|
40
40
|
def initialize(data)
|
41
|
-
@
|
42
|
-
@generics = @
|
43
|
-
@
|
44
|
-
@name = @module.to_s
|
41
|
+
@type = data.fetch(:type)
|
42
|
+
@generics = @type.generics
|
43
|
+
@name = @type.to_s
|
45
44
|
|
46
45
|
derive_expectations(data.fetch(:expectations))
|
47
46
|
derive_dependencies
|
@@ -49,8 +48,8 @@ module Carbon
|
|
49
48
|
end
|
50
49
|
|
51
50
|
# (see Base#call)
|
52
|
-
def call(
|
53
|
-
|
51
|
+
def call(_build, _generics)
|
52
|
+
# do nothing.
|
54
53
|
end
|
55
54
|
|
56
55
|
private
|
@@ -62,8 +61,8 @@ module Carbon
|
|
62
61
|
|
63
62
|
def derive_dependencies
|
64
63
|
@expectations.each do |expect|
|
65
|
-
@dependencies.merge(expect.parameters
|
66
|
-
@dependencies << expect.return
|
64
|
+
@dependencies.merge(expect.parameters)
|
65
|
+
@dependencies << expect.return
|
67
66
|
end
|
68
67
|
end
|
69
68
|
end
|
File without changes
|
@@ -1,137 +1,138 @@
|
|
1
|
-
# encoding: utf-8
|
1
|
+
# # encoding: utf-8
|
2
2
|
# frozen_string_literal: true
|
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
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
3
|
+
# # frozen_string_literal: true
|
4
|
+
#
|
5
|
+
# require "forwardable"
|
6
|
+
#
|
7
|
+
# module Carbon
|
8
|
+
# module Concrete
|
9
|
+
# # A "request." This is used to note the generics that a given module
|
10
|
+
# # should be compiled with. This is used for items to note the dependencies
|
11
|
+
# # that an item has; otherwise, it is used in the index for build
|
12
|
+
# # information.
|
13
|
+
# #
|
14
|
+
# # @note
|
15
|
+
# # **This class is frozen upon initialization.** This means that any
|
16
|
+
# # attempt to modify it will result in an error. In most cases, the
|
17
|
+
# # attributes on this class will also be frozen, as well.
|
18
|
+
# class Request
|
19
|
+
# extend Forwardable
|
20
|
+
#
|
21
|
+
# # The interned name of a module. This is used for module lookup. This
|
22
|
+
# # contains no generic information. For generic functions, all generics
|
23
|
+
# # are pushed onto the defining module.
|
24
|
+
# #
|
25
|
+
# # @api public
|
26
|
+
# # @example
|
27
|
+
# # request.intern # => "Carbon::Pointer"
|
28
|
+
# # @note See {Item::Base#intern} For more information about interned
|
29
|
+
# # names.
|
30
|
+
# # @return [::String]
|
31
|
+
# attr_reader :intern
|
32
|
+
#
|
33
|
+
# # The generics of the request. Even if the request has no definable
|
34
|
+
# # generics, these are still kept in place for both name information and
|
35
|
+
# # for placement information (e.g. identity and size).
|
36
|
+
# #
|
37
|
+
# # @api public
|
38
|
+
# # @example
|
39
|
+
# # request.generics # => [#<Carbon::Concrete::Type::Generic T>]
|
40
|
+
# # @return [<Type::Generic>]
|
41
|
+
# attr_reader :generics
|
42
|
+
#
|
43
|
+
# # Initialize the request with the given interned name and generics,
|
44
|
+
# # and then freezes the request.
|
45
|
+
# #
|
46
|
+
# # @api public
|
47
|
+
# # @see #intern
|
48
|
+
# # @see #generics
|
49
|
+
# # @param intern [::String] The interned name.
|
50
|
+
# # @param generics [<Type::Generic>] The generics.
|
51
|
+
# def initialize(intern, generics)
|
52
|
+
# @intern = intern
|
53
|
+
# @generics = generics
|
54
|
+
# deep_freeze!
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# # Replaces this request or this request's generics with the corresponding
|
58
|
+
# # correct module. This is designed to resolve generic names; for
|
59
|
+
# # example, it resolves `Carbon::Pointer<T>` to
|
60
|
+
# # `Carbon::Pointer<Carbon::String>` with the right argument. It checks
|
61
|
+
# # for three seperate cases.
|
62
|
+
# #
|
63
|
+
# # 1. The request has no generics, and the request's {#intern} has a
|
64
|
+
# # mapping in the argument. In this case, it creates a new request
|
65
|
+
# # object with the new module's name and no generics (because the
|
66
|
+
# # mapping could not have added any worthwhile generics).
|
67
|
+
# # 2. The request has no generics, and the request's {#intern} has no
|
68
|
+
# # mapping in the argument. In this case, it returns itself.
|
69
|
+
# # 3. The request has generics. In this case, the generics are mapped
|
70
|
+
# # using {Type::Generic#sub}, and a new request is created with the
|
71
|
+
# # mapped generics.
|
72
|
+
# #
|
73
|
+
# # @api public
|
74
|
+
# # @example
|
75
|
+
# # string # => #<Carbon::Concrete::Type::Generic Carbon::String>
|
76
|
+
# # request.intern # => "Carbon::Pointer"
|
77
|
+
# # request.generics # => [#<Carbon::Concrete::Type::Generic T>]
|
78
|
+
# # mapped = request.sub("T" => string)
|
79
|
+
# # mapped.intern # => "Carbon::Pointer"
|
80
|
+
# # request.generics.first.equal?(string) # => true
|
81
|
+
# # @param mapping [{::String => Type::Generic}] The mapping.
|
82
|
+
# # @return [Request] The new request, if the request has no generics,
|
83
|
+
# # and the request's {#intern} is not a key in the mapping, or if
|
84
|
+
# # the request has generics.
|
85
|
+
# # @return [self] If the request has no generics and it is not a key
|
86
|
+
# # in the mapping.
|
87
|
+
# def sub(mapping)
|
88
|
+
# case [@generics.none?, mapping.key?(@intern)]
|
89
|
+
# when [true, true]
|
90
|
+
# Request.new(mapping[@intern].name.intern, [])
|
91
|
+
# when [true, false]
|
92
|
+
# self
|
93
|
+
# else
|
94
|
+
# generics = @generics.map { |generic| generic.sub(mapping) }
|
95
|
+
# Request.new(intern, generics)
|
96
|
+
# end
|
97
|
+
# end
|
98
|
+
#
|
99
|
+
# # Compares this request to another. If this request _is_ the other
|
100
|
+
# # request, it returns true; otherwise, if the other is a request, and
|
101
|
+
# # the other request's {#intern} is equal to this request's, it
|
102
|
+
# # returns true; otherwise, it returns false.
|
103
|
+
# #
|
104
|
+
# # @api public
|
105
|
+
# # @param other [Request, ::String, ::Object] The object to compare.
|
106
|
+
# # @return [::Boolean]
|
107
|
+
# def ==(other)
|
108
|
+
# equal?(other) ||
|
109
|
+
# (other.is_a?(Request) && other.intern == intern &&
|
110
|
+
# other.generics == generics)
|
111
|
+
# end
|
112
|
+
#
|
113
|
+
# alias_method :eql?, :==
|
114
|
+
#
|
115
|
+
# # Creates a hash of the request. This is used mostly in the Hash
|
116
|
+
# # class.
|
117
|
+
# #
|
118
|
+
# # @api private
|
119
|
+
# # @return [Numeric]
|
120
|
+
# def hash
|
121
|
+
# @intern.hash
|
122
|
+
# end
|
123
|
+
#
|
124
|
+
# # Returns a string representation of this request. This includes all
|
125
|
+
# # generics that are associated with the request, if applicable.
|
126
|
+
# #
|
127
|
+
# # @api public
|
128
|
+
# # @return [::String]
|
129
|
+
# def to_s
|
130
|
+
# if @generics.any?
|
131
|
+
# "#{@intern}<#{@generics.map(&:to_s).join(', ')}>".freeze
|
132
|
+
# else
|
133
|
+
# @intern
|
134
|
+
# end
|
135
|
+
# end
|
136
|
+
# end
|
137
|
+
# end
|
138
|
+
# end
|
data/lib/carbon/concrete/type.rb
CHANGED
@@ -19,8 +19,6 @@ module Carbon
|
|
19
19
|
# **This class is frozen upon initialization.** This means that any
|
20
20
|
# attempt to modify it will result in an error. In most cases, the
|
21
21
|
# attributes on this class will also be frozen, as well.
|
22
|
-
# @todo
|
23
|
-
# TODO: Add function generics.
|
24
22
|
class Type
|
25
23
|
# A cache of types. This maps unparsed strings to their parsed
|
26
24
|
# derivatives. The cache is guarenteed to be thread-safe.
|
@@ -70,14 +68,23 @@ module Carbon
|
|
70
68
|
# @return [<Type::Generic>]
|
71
69
|
attr_reader :generics
|
72
70
|
|
71
|
+
# The location of the type. This is used for interfacing with other
|
72
|
+
# programs that require a location of some sort.
|
73
|
+
#
|
74
|
+
# @api semiprivate
|
75
|
+
# @return [Object]
|
76
|
+
attr_reader :location
|
77
|
+
|
73
78
|
# Initialize the type with the given name. After initialization, this
|
74
79
|
# freezes the type, preventing modification.
|
75
80
|
#
|
76
81
|
# @api public
|
77
82
|
# @param name [Type::Name] The name.
|
78
|
-
def initialize(name)
|
83
|
+
def initialize(name, location: nil)
|
79
84
|
@name = name
|
80
85
|
@generics = name.last.generics
|
86
|
+
@generics += function.generics if function?
|
87
|
+
@location = location
|
81
88
|
deep_freeze!
|
82
89
|
end
|
83
90
|
|
@@ -95,7 +102,27 @@ module Carbon
|
|
95
102
|
# type.function? # => true
|
96
103
|
# @return [::Boolean] True if the type is a function, false otherwise.
|
97
104
|
def function?
|
98
|
-
|
105
|
+
!function.nil?
|
106
|
+
end
|
107
|
+
|
108
|
+
# Returns the function information of the type. If this isn't a function
|
109
|
+
# type (see {#function?}), then this returns `nil`.
|
110
|
+
#
|
111
|
+
# @api public
|
112
|
+
# @example Not a function.
|
113
|
+
# type.to_s # => "Carbon::Pointer<T>"
|
114
|
+
# type.function? # => false
|
115
|
+
# type.function # => nil
|
116
|
+
# @example A function.
|
117
|
+
# type.to_s
|
118
|
+
# # => "Carbon::Pointer<T>.add(Carbon::Pointer<T>, Carbon::Int32)"
|
119
|
+
# type.function? # => true
|
120
|
+
# type.function # => #<Carbon::Concrete::Type::Function ...>
|
121
|
+
# @return [Concrete::Type::Function] The function information, if this is
|
122
|
+
# a function type; otherwise,
|
123
|
+
# @return [nil] returns nil.
|
124
|
+
def function
|
125
|
+
@name.function
|
99
126
|
end
|
100
127
|
|
101
128
|
# Compares this type to another type. If the other type _is_ this type,
|
@@ -123,6 +150,25 @@ module Carbon
|
|
123
150
|
|
124
151
|
alias_method :eql?, :==
|
125
152
|
|
153
|
+
# Checks if the given type "matches" the current type. This
|
154
|
+
# matches if any of the following conditions apply:
|
155
|
+
#
|
156
|
+
# 1. If the types match exactly, with no generics; otherwise,
|
157
|
+
# 2. If the types match exactly, with generics; otherwise,
|
158
|
+
# 3. If the given type can be made to look like the item type by
|
159
|
+
# introducing generics; otherwise,
|
160
|
+
# 4. They don't match.
|
161
|
+
#
|
162
|
+
# The base item provides a good default for most items.
|
163
|
+
#
|
164
|
+
# @param type [Concrete::Type] The type to check for matching.
|
165
|
+
# @return [Boolean] If the type matches the item.
|
166
|
+
def match?(other, generics = {})
|
167
|
+
(@generics.none? && to_s == other.to_s && generics) ||
|
168
|
+
(!function? && match_generic_module?(other, generics)) ||
|
169
|
+
(function? && match_generic_function?(other, generics))
|
170
|
+
end
|
171
|
+
|
126
172
|
# Creates a hash of the request. This is used mostly in the Hash class.
|
127
173
|
#
|
128
174
|
# @api private
|
@@ -158,8 +204,8 @@ module Carbon
|
|
158
204
|
# @param parameters [<Type>] The parameters that the function is
|
159
205
|
# called with.
|
160
206
|
# @return [Type] The new type.
|
161
|
-
def call(name, parameters)
|
162
|
-
func = Type::Function.new(name, parameters)
|
207
|
+
def call(name, parameters, generics = [])
|
208
|
+
func = Type::Function.new(name.to_s, parameters, generics)
|
163
209
|
name = Name.new(@name.parts, func)
|
164
210
|
Type.new(name)
|
165
211
|
end
|
@@ -185,7 +231,8 @@ module Carbon
|
|
185
231
|
# replace.
|
186
232
|
# @return [Concrete::Type] The new type.
|
187
233
|
def sub(generics)
|
188
|
-
return generics
|
234
|
+
return sub_function(generics) if function?
|
235
|
+
return generics[self] if generics.key?(self)
|
189
236
|
return self if generics.none?
|
190
237
|
replace_generics(generics)
|
191
238
|
end
|
@@ -204,26 +251,13 @@ module Carbon
|
|
204
251
|
# "Carbon::Int32)"
|
205
252
|
# type = Carbon::Type(form)
|
206
253
|
# type.to_s == form # => true
|
207
|
-
# second = Carbon::Type
|
254
|
+
# second = Carbon::Type(type.to_s)
|
208
255
|
# type == second # => true
|
209
256
|
# @return [::String] The string representation of the type.
|
210
257
|
def to_s
|
211
258
|
@name.to_s
|
212
259
|
end
|
213
260
|
|
214
|
-
# Creates a request based on this type.
|
215
|
-
#
|
216
|
-
# @api semipublic
|
217
|
-
# @example
|
218
|
-
# type = Carbon::Type("Carbon::Pointer<T>")
|
219
|
-
# req = type.to_request
|
220
|
-
# req.intern # => "Carbon::Pointer"
|
221
|
-
# req.generics # => [#<Carbon::Concrete::Type::Generic T>]
|
222
|
-
# @return [Request]
|
223
|
-
def to_request
|
224
|
-
Request.new(intern, generics)
|
225
|
-
end
|
226
|
-
|
227
261
|
# Removes all function information from the type. This is the complete
|
228
262
|
# opposite of {#call}. This just leaves the module that the function
|
229
263
|
# was defined on.
|
@@ -239,6 +273,21 @@ module Carbon
|
|
239
273
|
Type.new(name)
|
240
274
|
end
|
241
275
|
|
276
|
+
# Converts the type into a pointer type. Essentially, it just
|
277
|
+
# encapsulates the current type in a pointer.
|
278
|
+
#
|
279
|
+
# @example
|
280
|
+
# inner = Carbon::Boolean
|
281
|
+
# inner.to_s # => "Carbon::Boolean"
|
282
|
+
# inner.to_pointer.to_s # => "Carbon::Pointer<Carbon::Boolean>"
|
283
|
+
# @return [Type] The encapsulated type.
|
284
|
+
def to_pointer
|
285
|
+
ptype = Carbon::Type("Carbon::Pointer<T>")
|
286
|
+
tgen = Carbon::Type("T")
|
287
|
+
|
288
|
+
ptype.sub(tgen => self)
|
289
|
+
end
|
290
|
+
|
242
291
|
# Pretty inspect.
|
243
292
|
#
|
244
293
|
# @api private
|
@@ -247,8 +296,64 @@ module Carbon
|
|
247
296
|
"#<Carbon::Concrete::Type #{self}>".freeze
|
248
297
|
end
|
249
298
|
|
299
|
+
# Accepts the current visitor unto itself.
|
300
|
+
#
|
301
|
+
# @param visitor [#visit]
|
302
|
+
# @return [Object]
|
303
|
+
def accept(visitor, *params)
|
304
|
+
visitor.visit(self, *params)
|
305
|
+
end
|
306
|
+
|
250
307
|
private
|
251
308
|
|
309
|
+
def sub_function(generics)
|
310
|
+
return self if !@generics.any? &&
|
311
|
+
function.parameters.all? { |p| !p.generics.any? }
|
312
|
+
basic = to_module.sub(generics)
|
313
|
+
gens = function.generics.map { |p| p.sub(generics) }
|
314
|
+
params = function.parameters.map { |p| p.sub(generics) }
|
315
|
+
basic.call(function.name, params, gens)
|
316
|
+
end
|
317
|
+
|
318
|
+
def match_generic_module?(other, generics)
|
319
|
+
return intern == other.intern && {} unless generics.any?
|
320
|
+
intern == other.intern &&
|
321
|
+
other.generics.all? { |g| generics.values.include?(g.name) } &&
|
322
|
+
generics
|
323
|
+
end
|
324
|
+
|
325
|
+
def match_generic_function_preflight?(other, _)
|
326
|
+
# If neither have generics, then this can't match them.
|
327
|
+
@generics.any? && other.generics.any? &&
|
328
|
+
# If the types are modules, then they should have matched earlier.
|
329
|
+
function? && other.function? &&
|
330
|
+
# The function names should be the same.
|
331
|
+
(function.name == other.function.name) &&
|
332
|
+
# They should have the same number of generics.
|
333
|
+
(@generics.size == other.generics.size) &&
|
334
|
+
# They should have the same number of parameters.
|
335
|
+
(function.parameters.size == other.function.parameters.size)
|
336
|
+
end
|
337
|
+
|
338
|
+
def match_generic_function?(other, generics)
|
339
|
+
return false unless match_generic_function_preflight?(other, generics)
|
340
|
+
mapping = generics.merge(@generics.map(&:name)
|
341
|
+
.zip(other.generics.map(&:name)).to_h)
|
342
|
+
params = function.parameters.zip(other.function.parameters)
|
343
|
+
# If any of the parameters don't match, then the whole doesn't match.
|
344
|
+
# However, if one of the parameters is a generic, then we check to make
|
345
|
+
# sure that the same generic placement is used in the other type.
|
346
|
+
# For example, `A<T>.+(A<T>, T)` would match `A<B>.+(A<B>, B)`, but not
|
347
|
+
# `A<B>.+(A<B>, C)`.
|
348
|
+
params.all? do |(ours, theirs)|
|
349
|
+
if mapping.key?(ours)
|
350
|
+
mapping[ours].match?(theirs, mapping)
|
351
|
+
else
|
352
|
+
ours.match?(theirs, mapping)
|
353
|
+
end
|
354
|
+
end && mapping
|
355
|
+
end
|
356
|
+
|
252
357
|
def replace_generics(generics)
|
253
358
|
part = Part.new(@name.parts.last.value,
|
254
359
|
@generics.map { |g| g.sub(generics) })
|