yadriggy 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,754 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ module Yadriggy
4
+ # @abstract
5
+ # Root of the classes representing a type.
6
+ # A {Type} object may consist of a chain of multiple {Type} objects.
7
+ #
8
+ # Don't use `is_a?` but use `has_role?` or `role`.
9
+ #
10
+ class Type
11
+ # @private
12
+ def self.get_instance_method_object(recv_type, method_name)
13
+ recv_type.get_method_object(method_name)
14
+ end
15
+
16
+ # Raises an error.
17
+ # @param [String] msg an error message.
18
+ def self.error_found!(msg)
19
+ raise TypeChecker::CheckError.new(msg)
20
+ end
21
+
22
+ # Obtains the name of this type.
23
+ # @return [String] the type name.
24
+ def name()
25
+ to_s
26
+ end
27
+
28
+ # Makes a copy of self. Note that a {Type} object may consist of
29
+ # a chain of multiple {Type} objects. The copied chain does not
30
+ # contain an instance of `without_role`.
31
+ #
32
+ # @param [Class] without_role a subclass of {OptionalRole}.
33
+ # @return [Type] the copy.
34
+ def copy(without_role)
35
+ self
36
+ end
37
+
38
+ # Check the inequality.
39
+ # @return [Boolean] false if `self` and `t` represent the same type.
40
+ def != (t)
41
+ !(self == t)
42
+ end
43
+
44
+ # An alias to `==`.
45
+ # @return [Boolean] true if `self` and `t` represent the same type.
46
+ def eql?(t)
47
+ self == t
48
+ end
49
+
50
+ # Check the subtype relation.
51
+ # @param [Type] t the other type.
52
+ # @return [Boolean] true if `self` is equivalent to `t` or a subtpye of `t`
53
+ def <= (t)
54
+ self == t
55
+ end
56
+
57
+ # @private
58
+ # Only {DynType}, {UnionType} and {OptionalRole} override this method.
59
+ def is_super_of? (t)
60
+ false
61
+ end
62
+
63
+ # Finds an instance of the receiver class in the chain starting with
64
+ # the given {Type} object.
65
+ # If such an instance is not found, the method returns nil.
66
+ # Also see {OptionalRole}.
67
+ #
68
+ # @param [Type] type a Type object.
69
+ # @return [Type|nil] an instance of the receiver class.
70
+ def self.role(type)
71
+ if type.is_a?(Type)
72
+ type.has_role?(self)
73
+ else
74
+ nil
75
+ end
76
+ end
77
+
78
+ # Finds an instance of the receiver class in the chain starting
79
+ # with `self`.
80
+ # If such an instance is not found, the method returns `nil`.
81
+ # Also see {OptionalRole}.
82
+ #
83
+ # @param [Module] a_role a subclass of Type.
84
+ # @return [Type|nil] an instance of `a_role`.
85
+ def has_role?(a_role)
86
+ if self.is_a?(a_role)
87
+ self
88
+ else
89
+ nil
90
+ end
91
+ end
92
+
93
+ # Gets the Ruby class represented by this Type.
94
+ # @return [Module|DynType] the corresponding Ruby class or {DynType}.
95
+ def exact_type
96
+ DynType
97
+ end
98
+
99
+ # @private
100
+ # Gets a method with the given name declared in this type.
101
+ # `nil` is returned when the method is not exactly determined.
102
+ #
103
+ # @return [Method|nil]
104
+ def get_method_object(method_name)
105
+ nil
106
+ end
107
+
108
+ # @return [Type] the type containing a wider range of values.
109
+ def supertype
110
+ nil
111
+ end
112
+ end
113
+
114
+ # @private
115
+ class NonRubyType < Type
116
+ def initialize(obj_name, type_name)
117
+ @obj_name = obj_name
118
+ @type_name = type_name
119
+ end
120
+
121
+ # Obtains the name of this type.
122
+ # @return [String] the type name.
123
+ def name
124
+ @type_name
125
+ end
126
+
127
+ # Checks the equality.
128
+ # @param [Type] t the other type.
129
+ # @return [Boolean] true if `self` and `t` represent the same type.
130
+ def == (t)
131
+ r = NonRubyType.role(t)
132
+ self.equal?(r)
133
+ end
134
+
135
+ # Check the subtype relation.
136
+ # @param [Type] t the other type.
137
+ # @return [Boolean] true if `self` is equivalent to `t`.
138
+ def <= (t)
139
+ self == t || t.is_super_of?(self)
140
+ end
141
+
142
+ def role(t)
143
+ r = NonRubyType.role(t)
144
+ self.equal?(r) ? self : nil
145
+ end
146
+
147
+ def inspect()
148
+ @obj_name
149
+ end
150
+ end
151
+
152
+ # Dynamic type.
153
+ DynType = NonRubyType.new('#<Yadriggy::DynType>', 'DynType')
154
+
155
+ # @private
156
+ def DynType.is_super_of?(t)
157
+ true
158
+ end
159
+
160
+ # Void type.
161
+ Void = NonRubyType.new('#<Yadriggy::Void>', 'Void')
162
+
163
+ # Union type. A value of this type is a value of one of
164
+ # the given types.
165
+ class UnionType < Type
166
+ # @return [Array<Type>] the given types.
167
+ attr_reader :types
168
+
169
+ # Makes an instance of {UnionType}
170
+ # @param [Array<Type>] ts the types included in the union type.
171
+ # @return [UnionType|DynType] the instance.
172
+ def self.make(*ts)
173
+ fts = ts.flatten
174
+ fts.each do |e|
175
+ return DynType if DynType == e
176
+ end
177
+
178
+ t = UnionType.new(fts)
179
+ if t.types.size == 1
180
+ t.types[0]
181
+ else
182
+ t
183
+ end
184
+ end
185
+
186
+ # @param [Array<Type>] ts the types included in the union type.
187
+ def initialize(*ts)
188
+ @types = ts.flatten.map {|e| UnionType.role(e)&.types || e }.flatten.uniq
189
+ end
190
+
191
+ # Checks equality.
192
+ # Ignores {OptionalRole} when comparing two {UnionType}s.
193
+ # @param [Type] t the other type.
194
+ # @return [Boolean] true if `self` is equivalent to `t`.
195
+ def == (t)
196
+ ut = UnionType.role(t)
197
+ !ut.nil? && @types.size == ut.types.size &&
198
+ (normalize(self) | normalize(ut)).size <= @types.size
199
+ end
200
+
201
+ # @private
202
+ def normalize(utype)
203
+ utype.types.map {|e| e.copy(OptionalRole) }
204
+ end
205
+
206
+ # @private
207
+ def hash
208
+ @types.hash
209
+ end
210
+
211
+ # @private
212
+ # Check the subtype relation.
213
+ # @param [Type] t the other type.
214
+ # @return [Boolean] true if `self` is equivalent to `t`
215
+ # or a subtype of `t`.
216
+ def <= (t)
217
+ DynType == t || @types.all? {|e| e <= t }
218
+ end
219
+
220
+ # @param [Type] t a type.
221
+ # @return [Boolean] true if `self` is a super type of `t`.
222
+ def is_super_of?(t)
223
+ @types.any? {|e| t <= e }
224
+ end
225
+
226
+ # Obtains the name of this type.
227
+ # @return [String] the type name.
228
+ def name
229
+ name = '(' << @types.map{|e| e.name }.join('|') << ')'
230
+ name
231
+ end
232
+ end
233
+
234
+ # The most specific common super type.
235
+ # A value of this type is either an instance of `self.type`
236
+ # or a subclass of `self.type`.
237
+ #
238
+ class CommonSuperType < Type
239
+ # @return [Module] the common super type.
240
+ attr_reader :type
241
+
242
+ # @param [Module] t the type.
243
+ def initialize(t)
244
+ @type = t
245
+ end
246
+
247
+ # @private
248
+ def == (t)
249
+ CommonSuperType.role(t)&.type == @type
250
+ end
251
+
252
+ # @private
253
+ def hash
254
+ @type.hash + 1
255
+ end
256
+
257
+ # @private
258
+ # Check the subtype relation.
259
+ # @param [Type] t the other type.
260
+ # @return [Boolean] true if `self` is equivalent to `t`
261
+ # or a subtype of `t`.
262
+ def <= (t)
263
+ if t.is_super_of?(self)
264
+ true
265
+ else
266
+ ct = CommonSuperType.role(t)
267
+ !ct.nil? && (@type <= ct.type || @type == NilClass)
268
+ end
269
+ end
270
+
271
+ # @private
272
+ def get_method_object(method_name)
273
+ nil
274
+ end
275
+
276
+ # @return [CommonSuperType|nil] the {CommonSuperType} for the super class.
277
+ def supertype
278
+ if @type.is_a?(Class) && !@type.superclass.nil?
279
+ CommonSuperType.new(@type.superclass)
280
+ else
281
+ nil
282
+ end
283
+ end
284
+
285
+ # Obtains the name of this type.
286
+ # @return [String] the type name.
287
+ def name
288
+ @type.name + '+'
289
+ end
290
+ end
291
+
292
+ # Type of immediate instances of a Ruby class.
293
+ # The instances of its subclass are excluded.
294
+ # A class type including its subclasses is represented
295
+ # by {CommonSuperType}.
296
+ #
297
+ class RubyClass < Type
298
+ # @private
299
+ Table = {}
300
+
301
+ # @private
302
+ def self.make(clazz)
303
+ obj = RubyClass.new(clazz)
304
+ Table[clazz] = obj
305
+ obj
306
+ end
307
+
308
+ # @private
309
+ def self.set_alias(clazz, ruby_class)
310
+ Table[clazz] = ruby_class
311
+ end
312
+
313
+ # @param [Module|Object] clazz a Ruby class or module.
314
+ # @return [RubyClass|Object] a {RubyClass} object for `clazz`
315
+ # if `clazz` is an instance of `Module`. Otherwise, `clazz`
316
+ # is returned. For example, `RubyClass[Void]` returns `Void`.
317
+ def self.[](clazz)
318
+ Table[clazz] || (clazz.is_a?(::Module) ? RubyClass.new(clazz) : clazz)
319
+ end
320
+
321
+ # @param [Module] clazz the Ruby class or module.
322
+ def initialize(clazz)
323
+ @ruby_class = clazz
324
+ end
325
+
326
+ # Checks the equality.
327
+ # @param [Type|Module] t the other object.
328
+ # @return [Boolean] true if `self` and `t` represent the same Ruby class.
329
+ def == (t)
330
+ RubyClass.role(t)&.exact_type == @ruby_class
331
+ end
332
+
333
+ # @private
334
+ def hash
335
+ @ruby_class.hash
336
+ end
337
+
338
+ # @private
339
+ # Check the subtype relation.
340
+ # @param [Type] t the other type.
341
+ # @return [Boolean] true if `self` is equivalent to `t`
342
+ # or a subtype of `t`.
343
+ def <= (t)
344
+ if t.is_super_of?(self)
345
+ true
346
+ else
347
+ rc = RubyClass.role(t)
348
+ if rc.nil?
349
+ CommonSuperType.new(@ruby_class) <= t
350
+ else
351
+ rc.exact_type == @ruby_class || @ruby_class == ::NilClass
352
+ end
353
+ end
354
+ end
355
+
356
+ # @private
357
+ def get_method_object(method_name)
358
+ @ruby_class.instance_method(method_name)
359
+ rescue NameError
360
+ Type.error_found!("no such method: #{@ruby_class}\##{method_name}")
361
+ end
362
+
363
+ # @private
364
+ def exact_type
365
+ @ruby_class
366
+ end
367
+
368
+ # @return [CommonSuperType] the {CommonSuperType} for this class.
369
+ def supertype
370
+ CommonSuperType.new(@ruby_class)
371
+ end
372
+
373
+ # Obtains the name of this type.
374
+ # @return [String] the type name.
375
+ def name
376
+ @ruby_class.name
377
+ end
378
+ end
379
+
380
+ RubyClass::Symbol = RubyClass.make(Symbol)
381
+ RubyClass::String = RubyClass.make(String)
382
+ RubyClass::Integer = RubyClass.make(Integer)
383
+ RubyClass::Float = RubyClass.make(Float)
384
+ RubyClass::Range = RubyClass.make(Range)
385
+ RubyClass::Hash = RubyClass.make(Hash)
386
+ RubyClass::Array = RubyClass.make(Array)
387
+ RubyClass::Proc = RubyClass.make(Proc)
388
+ RubyClass::Exception = RubyClass.make(Exception)
389
+ RubyClass::TrueClass = RubyClass.make(TrueClass)
390
+ RubyClass::FalseClass = RubyClass.make(FalseClass)
391
+
392
+ # Fixnum is a subclass of Integer in Ruby earlier than 2.4.
393
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new('2.4')
394
+ RubyClass.set_alias(Fixnum, RubyClass::Integer)
395
+ end
396
+
397
+ # The type for `nil`. Although ::NilClass is not a subtype of
398
+ # other classes, RubyClass::NilClass is a subtype of {RubyClass::String},
399
+ # etc.
400
+ RubyClass::NilClass = RubyClass.make(NilClass)
401
+
402
+ # An instance of {UnionType}. It represents either `TrueClass` or
403
+ # `FalseClass`.
404
+ RubyClass::Boolean = UnionType.new([RubyClass::TrueClass,
405
+ RubyClass::FalseClass])
406
+
407
+ # An instance of {CommonSuperType}. It represents `::Numeric` class.
408
+ RubyClass::Numeric = CommonSuperType.new(Numeric)
409
+
410
+ # Type of a particular Ruby object.
411
+ #
412
+ class InstanceType < Type
413
+ # @return [Object] the Ruby object.
414
+ attr_reader :object
415
+
416
+ def initialize(obj)
417
+ @object = obj
418
+ end
419
+
420
+ # @private
421
+ def == (t)
422
+ InstanceType.role(t)&.object == @object
423
+ end
424
+
425
+ # @private
426
+ def hash
427
+ @object.hash
428
+ end
429
+
430
+ # @private
431
+ # Check the subtype relation.
432
+ # @param [Type] t the other type.
433
+ # @return [Boolean] true if `self` is equivalent to `t`
434
+ # or a subtype of `t`.
435
+ def <= (t)
436
+ if t.is_super_of?(self)
437
+ true
438
+ else
439
+ it = InstanceType.role(t)
440
+ (!it.nil? && it.object == @object) ||
441
+ RubyClass[exact_type] <= t
442
+ end
443
+ end
444
+
445
+ # @private
446
+ # Recall that `1.class` was `Fixnum` in Ruby earlier than 2.4.
447
+ def exact_type
448
+ @object.is_a?(Integer) ? Integer : @object.class
449
+ end
450
+
451
+ # @private
452
+ def get_method_object(method_name)
453
+ @object.method(method_name)
454
+ rescue NameError
455
+ Type.error_found!("no such method: #{@object.class}\##{method_name}")
456
+ end
457
+
458
+ # @return [RubyClass] the {RubyClass} for this class.
459
+ def supertype
460
+ RubyClass[exact_type]
461
+ end
462
+
463
+ # Obtains the name of this type.
464
+ # @return [String] the type name.
465
+ def name
466
+ @object.to_s
467
+ end
468
+ end
469
+
470
+ # Type of methods.
471
+ #
472
+ class MethodType < Type
473
+ # @param [Parameters|nil] method_def method definition.
474
+ # @param [Array<Type|Module>|DynType] param_type_array parameter types.
475
+ # `param_type_array` can be {DynType}.
476
+ # @param [Type|Module|DynType] result_type the result type.
477
+ def initialize(method_def=nil, param_type_array, result_type)
478
+ @param_types = if param_type_array.is_a?(Array)
479
+ param_type_array.map do |t|
480
+ t.is_a?(Type) ? t : RubyClass[t]
481
+ end
482
+ else
483
+ param_type_array
484
+ end
485
+ @result_type = if result_type.is_a?(Type)
486
+ result_type
487
+ else
488
+ RubyClass[result_type]
489
+ end
490
+ @method_def = method_def
491
+ end
492
+
493
+ # Gets an array of the parameter types.
494
+ # @return [Array<Type>|DynType] the parameter types.
495
+ def params() @param_types end
496
+
497
+ # @return [Type] the result type.
498
+ def result_type() @result_type end
499
+
500
+ # @return [Parameters] the method definition.
501
+ def method_def() @method_def end
502
+
503
+ # @private
504
+ def == (t)
505
+ mt = MethodType.role(t)
506
+ !mt.nil? && @result_type == mt.result_type && @param_types == mt.params
507
+ end
508
+
509
+ # @private
510
+ def hash
511
+ @result_type.hash + @param_types.hash
512
+ end
513
+
514
+ # @private
515
+ def <= (t)
516
+ if t.is_super_of?(self)
517
+ true
518
+ else
519
+ mt = MethodType.role(t)
520
+ !mt.nil? && @result_type <= mt.result_type &&
521
+ compare_params(mt.params, @param_types)
522
+ end
523
+ end
524
+
525
+ # @return [ResultType] the result type. Note that a {ResultType} object
526
+ # is always returned.
527
+ def result()
528
+ ResultType.new(@result_type, @method_def)
529
+ end
530
+
531
+ # Obtains the name of this type.
532
+ # @return [String] the type name.
533
+ def name
534
+ name = ''
535
+ if @param_types.is_a?(Array)
536
+ name << '(' << @param_types.map{|e| e.name }.join(',') << ')'
537
+ else
538
+ name << @param_types.name
539
+ end
540
+ name << '->' << @result_type.name
541
+ name
542
+ end
543
+
544
+ private
545
+
546
+ # @return [Boolean] true if p <= q
547
+ def compare_params(p, q)
548
+ if p.is_a?(Array) && q.is_a?(Array)
549
+ p.size == q.size &&
550
+ (0...p.size).reduce(true) {|b,i| b && p[i] <= q[i] }
551
+ else
552
+ DynType == q
553
+ end
554
+ end
555
+ end
556
+
557
+ # Parametric types.
558
+ #
559
+ class CompositeType < Type
560
+ # @return [Module] type name. The value is a Ruby class.
561
+ attr_reader :ruby_class
562
+ # @return [Array<Type>] type arguments.
563
+ attr_reader :args
564
+
565
+ # @param [Module] name type name.
566
+ # @param [Array<Type>|Type] args type arguments.
567
+ def initialize(name, args)
568
+ @ruby_class = name
569
+ @args = args.is_a?(Array) ? args : [ args ]
570
+ end
571
+
572
+ # @return [Type] the first type argument.
573
+ def first_arg
574
+ @args[0]
575
+ end
576
+
577
+ # Checks the equality.
578
+ # @param [Type|Module] t the other object.
579
+ # @return [Boolean] true if `self` and `t` represent the same type
580
+ # and their type arguments are equivalent.
581
+ def == (t)
582
+ ct = CompositeType.role(t)
583
+ !ct.nil? && ct.ruby_class == @ruby_class &&
584
+ ct.args == @args
585
+ end
586
+
587
+ # @private
588
+ def hash
589
+ @ruby_class.hash + @args.reduce(0) {|h,p| h + p.hash }
590
+ end
591
+
592
+ # @private
593
+ # Check the subtype relation.
594
+ # @param [Type] t the other type.
595
+ # @return [Boolean] true if `self` is equivalent to `t`
596
+ # or a subtype of `t`.
597
+ def <= (t)
598
+ if t.is_super_of?(self)
599
+ true
600
+ else
601
+ ct = CompositeType.role(t)
602
+ if ct.nil?
603
+ RubyClass[@ruby_class] <= t
604
+ else
605
+ ct.ruby_class == @ruby_class &&
606
+ @args.zip(ct.args).all? {|tt| tt[0] <= tt[1] }
607
+ end
608
+ end
609
+ end
610
+
611
+ # @private
612
+ def exact_type
613
+ @ruby_class
614
+ end
615
+
616
+ # @return [RubyClass] the {RubyClass} for this class.
617
+ def supertype
618
+ RubyClass[@ruby_class]
619
+ end
620
+
621
+ # Obtains the name of this type.
622
+ # @return [String] the type name.
623
+ def name
624
+ name = @ruby_class.name
625
+ name << '<' << @args.map{|e| e.name }.join(',') << '>'
626
+ name
627
+ end
628
+ end
629
+
630
+ # A role that can be attached to a {Type} object.
631
+ # It makes a chain of {Type} objects.
632
+ #
633
+ class OptionalRole < Type
634
+ # @param [Type] type a Type object that this role is added to.
635
+ def initialize(type)
636
+ @type = type
637
+ end
638
+
639
+ # @private
640
+ def copy(without_role)
641
+ chain = @type.copy(without_role)
642
+ if self.is_a?(without_role)
643
+ chain
644
+ else
645
+ if @type.equal?(chain)
646
+ self
647
+ else
648
+ new_self = self.clone()
649
+ new_self.update_type = chain
650
+ new_self
651
+ end
652
+ end
653
+ end
654
+
655
+ # @private
656
+ def update_type(t)
657
+ @type = t
658
+ end
659
+
660
+ # Checks the equality. The roles (a {OptionalRole} objects) in the chain
661
+ # are ignored when objects are compared.
662
+ def == (t)
663
+ @type == t
664
+ end
665
+
666
+ # @private
667
+ def hash
668
+ @type.hash
669
+ end
670
+
671
+ # @private
672
+ def <= (t)
673
+ @type <= t
674
+ end
675
+
676
+ # @private
677
+ def is_super_of?(t)
678
+ @type.is_super_of?(t)
679
+ end
680
+
681
+ # @private
682
+ def has_role?(a_role)
683
+ if self.is_a?(a_role)
684
+ self
685
+ else
686
+ @type.has_role?(a_role)
687
+ end
688
+ end
689
+
690
+ # @private
691
+ def exact_type
692
+ @type.exact_type
693
+ end
694
+
695
+ # @private
696
+ def get_method_object(method_name)
697
+ Type.get_instance_method_object(@type, method_name)
698
+ end
699
+
700
+ # @return [Type] the super type.
701
+ def supertype
702
+ @type.supertype
703
+ end
704
+ end # of OptionalRole
705
+
706
+ # Type of values returned by a method.
707
+ #
708
+ class ResultType < OptionalRole
709
+ # @return [Parameters] The definition of the method returning
710
+ # a value of this type.
711
+ attr_reader :method_def
712
+
713
+ # @param [Type] type a Type object that this role is added to.
714
+ # @param [Parameters] method_def the method.
715
+ def initialize(type, method_def)
716
+ super(type)
717
+ @method_def = method_def
718
+ end
719
+ end
720
+
721
+ # Type of the value of a local variable.
722
+ #
723
+ class LocalVarType < OptionalRole
724
+ # @return [ASTnode|Undef|nil] the AST node where the variable appears
725
+ # for the first time, in other words,
726
+ # where the variable's type is defined.
727
+ # `Undef` if a value is assigned to the variable
728
+ # more than once.
729
+ # `nil` if an initial value has not been assigned
730
+ # to the variable yet.
731
+ attr_reader :definition
732
+
733
+ # @param [Type] type a Type object that this role is added to.
734
+ # @param [ASTnode|nil] definition the AST node of the local variable.
735
+ # `nil` if an initial value is not set.
736
+ def initialize(type, definition)
737
+ super(type)
738
+ @definition = definition
739
+ end
740
+
741
+ # @param [ASTnode] ast the AST node of the local variable where
742
+ # a new value is assigned to it.
743
+ # @return [self]
744
+ def definition=(ast)
745
+ if @definition.nil?
746
+ @definition = ast
747
+ else
748
+ @definition = Undef
749
+ end
750
+ self
751
+ end
752
+
753
+ end
754
+ end