-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
/
Copy pathclass.cr
171 lines (153 loc) · 3.76 KB
/
class.cr
1
2
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
138
139
140
141
142
143
144
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
class Class
def inspect(io : IO) : Nil
to_s(io)
end
# See `Object#hash(hasher)`
def hash(hasher)
hasher.class(self)
end
# Returns whether this class is the same as *other*.
#
# ```
# Int32 == Int32 # => true
# Int32 == String # => false
# ```
def ==(other : Class) : Bool
crystal_type_id == other.crystal_type_id
end
# Returns whether this class inherits or includes *other*.
#
# ```
# Int32 < Number # => true
# Int32 < Value # => true
# Int32 < Int32 # => false
# Int32 <= String # => false
# ```
def <(other : T.class) : Bool forall T
# This is so that the method is expanded differently for each type
{% @type %}
other._gt(self)
end
# Returns whether this class inherits or includes *other*, or
# is equal to *other*.
#
# ```
# Int32 < Number # => true
# Int32 < Value # => true
# Int32 <= Int32 # => true
# Int32 <= String # => false
# ```
def <=(other : T.class) : Bool forall T
# This is so that the method is expanded differently for each type
{% @type %}
other._gte(self)
end
# Returns whether *other* inherits or includes `self`.
#
# ```
# Number > Int32 # => true
# Number > Number # => false
# Number > Object # => false
# ```
def >(other : T.class) : Bool forall T
# This is so that the method is expanded differently for each type
{% @type %}
other._lt(self)
end
# Returns whether *other* inherits or includes `self`, or is equal
# to `self`.
#
# ```
# Number >= Int32 # => true
# Number >= Number # => true
# Number >= Object # => false
# ```
def >=(other : T.class) forall T
# This is so that the method is expanded differently for each type
{% @type %}
other._lte(self)
end
# :nodoc:
def _lt(other : T.class) forall T
{{ @type < T }}
end
# :nodoc:
def _lte(other : T.class) forall T
{{ @type <= T }}
end
# :nodoc:
def _gt(other : T.class) forall T
{{ @type > T }}
end
# :nodoc:
def _gte(other : T.class) forall T
{{ @type >= T }}
end
def ===(other)
# This branch handles `Int32.class === 1` case.
# In this case, `@type` is `Class` and `other.is_a?(self)` means `other.is_a?(Object)`
# because type of `self` is an instance type of the scope type and the instance type of `Class` is `Object`.
# See https://github.com/crystal-lang/crystal/issues/10736.
{% if @type == Class %}
other.is_a?(Class)
{% else %}
other.is_a?(self)
{% end %}
end
# Returns the name of this class.
#
# ```
# String.name # => "String"
# ```
def name : String
{{ @type.name.stringify }}
end
# Casts *other* to this class.
#
# This is the same as using `as`, but allows the class to be passed around as
# an argument. See the
# [documentation on as](//crystal-lang.org/docs/syntax_and_semantics/as.html)
# for more information.
#
# ```
# klass = Int32
# number = [99, "str"][0]
# typeof(number) # => (String | Int32)
# typeof(klass.cast(number)) # => Int32
# ```
def cast(other) : self
other.as(self)
end
# Returns the union type of `self` and *other*.
#
# ```
# Int32 | Char # => (Int32 | Char)
# ```
def self.|(other : U.class) forall U
t = uninitialized self
u = uninitialized U
typeof(t, u)
end
# Returns `true` if `nil` is an instance of this type.
#
# ```
# Int32.nilable? # => false
# Nil.nilable? # => true
# (Int32 | String).nilable? # => false
# (Int32 | Nil).nilable? # => true
# NoReturn.nilable? # => false
# Value.nilable? # => true
# ```
def nilable? : Bool
{{ @type >= Nil }}
end
def to_s(io : IO) : Nil
io << {{ @type.name.stringify }}
end
def dup
self
end
def clone
self
end
end