yadriggy 1.0.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.
@@ -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