steep 0.33.0 → 0.38.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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/lib/steep.rb +9 -0
  4. data/lib/steep/annotation_parser.rb +1 -1
  5. data/lib/steep/ast/types/factory.rb +167 -102
  6. data/lib/steep/ast/types/logic.rb +20 -1
  7. data/lib/steep/ast/types/proc.rb +32 -20
  8. data/lib/steep/cli.rb +15 -2
  9. data/lib/steep/drivers/print_project.rb +11 -0
  10. data/lib/steep/drivers/stats.rb +85 -0
  11. data/lib/steep/drivers/vendor.rb +1 -20
  12. data/lib/steep/errors.rb +38 -15
  13. data/lib/steep/index/rbs_index.rb +334 -0
  14. data/lib/steep/index/signature_symbol_provider.rb +154 -0
  15. data/lib/steep/index/source_index.rb +100 -0
  16. data/lib/steep/interface/block.rb +79 -0
  17. data/lib/steep/interface/function.rb +770 -0
  18. data/lib/steep/interface/method_type.rb +41 -832
  19. data/lib/steep/method_name.rb +28 -0
  20. data/lib/steep/project/completion_provider.rb +24 -15
  21. data/lib/steep/project/dsl.rb +13 -17
  22. data/lib/steep/project/options.rb +4 -4
  23. data/lib/steep/project/source_file.rb +2 -1
  24. data/lib/steep/project/target.rb +19 -10
  25. data/lib/steep/server/interaction_worker.rb +1 -1
  26. data/lib/steep/server/master.rb +5 -1
  27. data/lib/steep/server/signature_worker.rb +63 -6
  28. data/lib/steep/subtyping/check.rb +70 -32
  29. data/lib/steep/subtyping/variable_occurrence.rb +4 -2
  30. data/lib/steep/subtyping/variable_variance.rb +2 -2
  31. data/lib/steep/type_construction.rb +780 -495
  32. data/lib/steep/type_inference/block_params.rb +1 -1
  33. data/lib/steep/type_inference/constant_env.rb +5 -1
  34. data/lib/steep/type_inference/context.rb +7 -3
  35. data/lib/steep/type_inference/local_variable_type_env.rb +10 -1
  36. data/lib/steep/type_inference/logic_type_interpreter.rb +3 -0
  37. data/lib/steep/type_inference/method_call.rb +116 -0
  38. data/lib/steep/typing.rb +46 -10
  39. data/lib/steep/version.rb +1 -1
  40. data/smoke/regression/range.rb +5 -0
  41. data/smoke/tsort/Steepfile +6 -0
  42. data/smoke/tsort/a.rb +15 -0
  43. data/steep.gemspec +1 -1
  44. metadata +17 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e93086efe3704ac8b59a1450fda301b7ab91f409c13c53a679a2ed3b3419ca84
4
- data.tar.gz: b00e2030a9ea2171b6f967c78f469204c903cb937d421e5dcab896021fce2919
3
+ metadata.gz: 1662ab3cd8c9b1630d38939e491bd9db3b46701a5ab6f09061e4470c95fbbae8
4
+ data.tar.gz: 9fea79ba28f595b1a51812708c0b3a98170110f0367a0baa287623232fe64156
5
5
  SHA512:
6
- metadata.gz: 06023d31b509f58efdea8c8f0e13c49b38f3a4936debbe3a0d88bfd84b356e7a761506a8f105c035bd454a4b2f39ae6af13d16b84d29e6d0050d9d58d7062e82
7
- data.tar.gz: '0601459d31ad8ca758c95c29215eb237b5bc50490b5133e574057ec1836396d9189c3dd22628244c1d8d432e0f945a746c280ae96ca20b768c063fbae0c696af'
6
+ metadata.gz: 2f42e7e12ff24d1d4acbebc7693b1bb7f1417f4d44f0cc2b2590990a50a1c20ee690d23a316414113e9a65601971cd3bf19b13babc9e09a64cfcebae1fe8c4ec
7
+ data.tar.gz: 6aa3693092fa2811fe0663c4266ed3cf9ccd2b79d7e0e8e6c3c79e3c3a29b1d19954ac0127ed0c62a1619dac2555c67ae987f3a4386001cbdf6a73a76e405829
@@ -2,6 +2,34 @@
2
2
 
3
3
  ## master
4
4
 
5
+ ## 0.38.0 (2020-12-10)
6
+
7
+ * Improve `break`/`next` typing ([#271](https://github.com/soutaro/steep/pull/271))
8
+ * Add LSP `workspace/symbol` feature ([#267](https://github.com/soutaro/steep/pull/267))
9
+
10
+ ## 0.37.0 (2020-12-06)
11
+
12
+ * Update to RBS 0.20.0 with _singleton attribute_ syntax and _proc types with blocks_. ([#264](https://github.com/soutaro/steep/pull/264))
13
+
14
+ ## 0.36.0 (2020-11-16)
15
+
16
+ * Flow-sensitive typing improvements with `||` and `&&` ([#260](https://github.com/soutaro/steep/pull/260))
17
+ * Type-case improvement ([#259](https://github.com/soutaro/steep/pull/259))
18
+ * Subtyping between `bool` and logic types ([#258](https://github.com/soutaro/steep/pull/258))
19
+
20
+ ## 0.35.0 (2020-11-14)
21
+
22
+ * Support third party RBS repository ([#231](https://github.com/soutaro/steep/pull/231), [#254](https://github.com/soutaro/steep/pull/254), [#255](https://github.com/soutaro/steep/pull/255))
23
+ * Boolean type semantics update ([#252](https://github.com/soutaro/steep/pull/252))
24
+ * More flexible record typing ([#256](https://github.com/soutaro/steep/pull/256))
25
+
26
+ ## 0.34.0 (2020-10-27)
27
+
28
+ * Add `steep stats` command to show method call typing stats ([#246](https://github.com/soutaro/steep/pull/246))
29
+ * Fix attribute assignment typing ([#243](https://github.com/soutaro/steep/pull/243))
30
+ * Let `Range[T]` be covariant ([#242](https://github.com/soutaro/steep/pull/242))
31
+ * Fix constant typing ([#247](https://github.com/soutaro/steep/pull/247), [#248](https://github.com/soutaro/steep/pull/248))
32
+
5
33
  ## 0.33.0 (2020-10-13)
6
34
 
7
35
  * Make `!` typing flow sensitive ([#240](https://github.com/soutaro/steep/pull/240))
@@ -16,6 +16,7 @@ require 'uri'
16
16
 
17
17
  require "rbs"
18
18
 
19
+ require "steep/method_name"
19
20
  require "steep/ast/types/helper"
20
21
  require "steep/ast/types/any"
21
22
  require "steep/ast/types/instance"
@@ -41,6 +42,8 @@ require "steep/ast/annotation/collection"
41
42
  require "steep/ast/builtin"
42
43
  require "steep/ast/types/factory"
43
44
 
45
+ require "steep/interface/function"
46
+ require "steep/interface/block"
44
47
  require "steep/interface/method_type"
45
48
  require "steep/interface/substitution"
46
49
  require "steep/interface/interface"
@@ -70,8 +73,13 @@ require "steep/type_inference/type_env"
70
73
  require "steep/type_inference/local_variable_type_env"
71
74
  require "steep/type_inference/logic"
72
75
  require "steep/type_inference/logic_type_interpreter"
76
+ require "steep/type_inference/method_call"
73
77
  require "steep/ast/types"
74
78
 
79
+ require "steep/index/rbs_index"
80
+ require "steep/index/signature_symbol_provider"
81
+ require "steep/index/source_index"
82
+
75
83
  require "steep/server/utils"
76
84
  require "steep/server/base_worker"
77
85
  require "steep/server/code_worker"
@@ -91,6 +99,7 @@ require "steep/project/hover_content"
91
99
  require "steep/project/completion_provider"
92
100
  require "steep/drivers/utils/driver_helper"
93
101
  require "steep/drivers/check"
102
+ require "steep/drivers/stats"
94
103
  require "steep/drivers/validate"
95
104
  require "steep/drivers/annotations"
96
105
  require "steep/drivers/watch"
@@ -68,7 +68,7 @@ module Steep
68
68
  name = match[:name]
69
69
  type = match[:type]
70
70
 
71
- method_type = factory.method_type(RBS::Parser.parse_method_type(type), self_type: AST::Types::Self.new)
71
+ method_type = factory.method_type(RBS::Parser.parse_method_type(type), self_type: AST::Types::Self.new, method_decls: Set[])
72
72
 
73
73
  AST::Annotation::MethodType.new(name: name.to_sym,
74
74
  type: method_type,
@@ -75,9 +75,23 @@ module Steep
75
75
  end
76
76
  Record.new(elements: elements, location: nil)
77
77
  when RBS::Types::Proc
78
- params = params(type.type)
79
- return_type = type(type.type.return_type)
80
- Proc.new(params: params, return_type: return_type, location: nil)
78
+ func = Interface::Function.new(
79
+ params: params(type.type),
80
+ return_type: type(type.type.return_type),
81
+ location: type.location
82
+ )
83
+ block = if type.block
84
+ Interface::Block.new(
85
+ type: Interface::Function.new(
86
+ params: params(type.block.type),
87
+ return_type: type(type.block.type.return_type),
88
+ location: type.location
89
+ ),
90
+ optional: !type.block.required
91
+ )
92
+ end
93
+
94
+ Proc.new(type: func, block: block)
81
95
  else
82
96
  raise "Unexpected type given: #{type}"
83
97
  end
@@ -145,16 +159,28 @@ module Steep
145
159
  end
146
160
  RBS::Types::Record.new(fields: fields, location: nil)
147
161
  when Proc
162
+ block = if type.block
163
+ RBS::Types::Block.new(
164
+ type: function_1(type.block.type),
165
+ required: !type.block.optional?
166
+ )
167
+ end
148
168
  RBS::Types::Proc.new(
149
- type: function_1(type.params, type.return_type),
169
+ type: function_1(type.type),
170
+ block: block,
150
171
  location: nil
151
172
  )
173
+ when Logic::Base
174
+ RBS::Types::Bases::Bool.new(location: nil)
152
175
  else
153
176
  raise "Unexpected type given: #{type} (#{type.class})"
154
177
  end
155
178
  end
156
179
 
157
- def function_1(params, return_type)
180
+ def function_1(func)
181
+ params = func.params
182
+ return_type = func.return_type
183
+
158
184
  RBS::Types::Function.new(
159
185
  required_positionals: params.required.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
160
186
  optional_positionals: params.optional.map {|type| RBS::Types::Function::Param.new(name: nil, type: type_1(type)) },
@@ -168,7 +194,7 @@ module Steep
168
194
  end
169
195
 
170
196
  def params(type)
171
- Interface::Params.new(
197
+ Interface::Function::Params.new(
172
198
  required: type.required_positionals.map {|param| type(param.type) },
173
199
  optional: type.optional_positionals.map {|param| type(param.type) },
174
200
  rest: type.rest_positionals&.yield_self {|param| type(param.type) },
@@ -178,7 +204,7 @@ module Steep
178
204
  )
179
205
  end
180
206
 
181
- def method_type(method_type, self_type:, subst2: nil, method_def: nil)
207
+ def method_type(method_type, self_type:, subst2: nil, method_decls:)
182
208
  fvs = self_type.free_variables()
183
209
 
184
210
  type_params = []
@@ -200,17 +226,22 @@ module Steep
200
226
 
201
227
  type = Interface::MethodType.new(
202
228
  type_params: type_params,
203
- return_type: type(method_type.type.return_type).subst(subst),
204
- params: params(method_type.type).subst(subst),
229
+ type: Interface::Function.new(
230
+ params: params(method_type.type).subst(subst),
231
+ return_type: type(method_type.type.return_type).subst(subst),
232
+ location: method_type.location
233
+ ),
205
234
  block: method_type.block&.yield_self do |block|
206
235
  Interface::Block.new(
207
236
  optional: !block.required,
208
- type: Proc.new(params: params(block.type).subst(subst),
209
- return_type: type(block.type.return_type).subst(subst), location: nil)
237
+ type: Interface::Function.new(
238
+ params: params(block.type).subst(subst),
239
+ return_type: type(block.type.return_type).subst(subst),
240
+ location: nil
241
+ )
210
242
  )
211
243
  end,
212
- method_def: method_def,
213
- location: method_def&.member&.location
244
+ method_decls: method_decls
214
245
  )
215
246
 
216
247
  if block_given?
@@ -241,12 +272,12 @@ module Steep
241
272
 
242
273
  type = RBS::MethodType.new(
243
274
  type_params: type_params,
244
- type: function_1(method_type.params.subst(subst), method_type.return_type.subst(subst)),
275
+ type: function_1(method_type.type.subst(subst)),
245
276
  block: method_type.block&.yield_self do |block|
246
277
  block_type = block.type.subst(subst)
247
278
 
248
- RBS::MethodType::Block.new(
249
- type: function_1(block_type.params, block_type.return_type),
279
+ RBS::Types::Block.new(
280
+ type: function_1(block_type),
250
281
  required: !block.optional
251
282
  )
252
283
  end,
@@ -344,46 +375,52 @@ module Steep
344
375
 
345
376
  NilClassName = TypeName("::NilClass")
346
377
 
347
- def setup_primitives(method_name, method_type)
348
- if method_def = method_type.method_def
349
- defined_in = method_def.defined_in
350
- member = method_def.member
351
-
352
- if member.is_a?(RBS::AST::Members::MethodDefinition)
353
- case method_name
354
- when :is_a?, :kind_of?, :instance_of?
355
- if defined_in == RBS::BuiltinNames::Object.name && member.instance?
356
- return method_type.with(
357
- return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.return_type.location)
378
+ def setup_primitives(method_name, method_def, method_type)
379
+ defined_in = method_def.defined_in
380
+ member = method_def.member
381
+
382
+ if member.is_a?(RBS::AST::Members::MethodDefinition)
383
+ case method_name
384
+ when :is_a?, :kind_of?, :instance_of?
385
+ if defined_in == RBS::BuiltinNames::Object.name && member.instance?
386
+ return method_type.with(
387
+ type: method_type.type.with(
388
+ return_type: AST::Types::Logic::ReceiverIsArg.new(location: method_type.type.return_type.location)
358
389
  )
359
- end
390
+ )
391
+ end
360
392
 
361
- when :nil?
362
- case defined_in
363
- when RBS::BuiltinNames::Object.name,
364
- NilClassName
365
- return method_type.with(
366
- return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.return_type.location)
393
+ when :nil?
394
+ case defined_in
395
+ when RBS::BuiltinNames::Object.name,
396
+ NilClassName
397
+ return method_type.with(
398
+ type: method_type.type.with(
399
+ return_type: AST::Types::Logic::ReceiverIsNil.new(location: method_type.type.return_type.location)
367
400
  )
368
- end
401
+ )
402
+ end
369
403
 
370
- when :!
371
- case defined_in
372
- when RBS::BuiltinNames::BasicObject.name,
373
- RBS::BuiltinNames::TrueClass.name,
374
- RBS::BuiltinNames::FalseClass.name
375
- return method_type.with(
376
- return_type: AST::Types::Logic::Not.new(location: method_type.return_type.location)
404
+ when :!
405
+ case defined_in
406
+ when RBS::BuiltinNames::BasicObject.name,
407
+ RBS::BuiltinNames::TrueClass.name,
408
+ RBS::BuiltinNames::FalseClass.name
409
+ return method_type.with(
410
+ type: method_type.type.with(
411
+ return_type: AST::Types::Logic::Not.new(location: method_type.type.return_type.location)
377
412
  )
378
- end
413
+ )
414
+ end
379
415
 
380
- when :===
381
- case defined_in
382
- when RBS::BuiltinNames::Module.name
383
- return method_type.with(
384
- return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.return_type.location)
416
+ when :===
417
+ case defined_in
418
+ when RBS::BuiltinNames::Module.name
419
+ return method_type.with(
420
+ type: method_type.type.with(
421
+ return_type: AST::Types::Logic::ArgIsReceiver.new(location: method_type.type.return_type.location)
385
422
  )
386
- end
423
+ )
387
424
  end
388
425
  end
389
426
  end
@@ -433,10 +470,13 @@ module Steep
433
470
 
434
471
  interface.methods[name] = Interface::Interface::Entry.new(
435
472
  method_types: method.defs.map do |type_def|
473
+ method_name = InstanceMethodName.new(type_name: type_def.implemented_in || type_def.defined_in, method_name: name)
474
+ decl = TypeInference::MethodCall::MethodDecl.new(method_name: method_name, method_def: type_def)
436
475
  setup_primitives(
437
476
  name,
477
+ type_def,
438
478
  method_type(type_def.type,
439
- method_def: type_def,
479
+ method_decls: Set[decl],
440
480
  self_type: self_type,
441
481
  subst2: subst)
442
482
  )
@@ -460,7 +500,11 @@ module Steep
460
500
  definition.methods.each do |name, method|
461
501
  interface.methods[name] = Interface::Interface::Entry.new(
462
502
  method_types: method.defs.map do |type_def|
463
- method_type(type_def.type, method_def: type_def, self_type: self_type, subst2: subst)
503
+ decls = Set[TypeInference::MethodCall::MethodDecl.new(
504
+ method_name: InstanceMethodName.new(type_name: type_def.implemented_in || type_def.defined_in, method_name: name),
505
+ method_def: type_def
506
+ )]
507
+ method_type(type_def.type, method_decls: decls, self_type: self_type, subst2: subst)
464
508
  end
465
509
  )
466
510
  end
@@ -485,10 +529,16 @@ module Steep
485
529
 
486
530
  interface.methods[name] = Interface::Interface::Entry.new(
487
531
  method_types: method.defs.map do |type_def|
532
+ decl = TypeInference::MethodCall::MethodDecl.new(
533
+ method_name: SingletonMethodName.new(type_name: type_def.implemented_in || type_def.defined_in,
534
+ method_name: name),
535
+ method_def: type_def
536
+ )
488
537
  setup_primitives(
489
538
  name,
539
+ type_def,
490
540
  method_type(type_def.type,
491
- method_def: type_def,
541
+ method_decls: Set[decl],
492
542
  self_type: self_type,
493
543
  subst2: subst)
494
544
  )
@@ -560,16 +610,18 @@ module Steep
560
610
  method_types: type.types.map.with_index {|elem_type, index|
561
611
  Interface::MethodType.new(
562
612
  type_params: [],
563
- params: Interface::Params.new(required: [AST::Types::Literal.new(value: index)],
564
- optional: [],
565
- rest: nil,
566
- required_keywords: {},
567
- optional_keywords: {},
568
- rest_keywords: nil),
613
+ type: Interface::Function.new(
614
+ params: Interface::Function::Params.new(required: [AST::Types::Literal.new(value: index)],
615
+ optional: [],
616
+ rest: nil,
617
+ required_keywords: {},
618
+ optional_keywords: {},
619
+ rest_keywords: nil),
620
+ return_type: elem_type,
621
+ location: nil
622
+ ),
569
623
  block: nil,
570
- return_type: elem_type,
571
- method_def: nil,
572
- location: nil
624
+ method_decls: Set[]
573
625
  )
574
626
  } + aref.method_types
575
627
  )
@@ -580,16 +632,18 @@ module Steep
580
632
  method_types: type.types.map.with_index {|elem_type, index|
581
633
  Interface::MethodType.new(
582
634
  type_params: [],
583
- params: Interface::Params.new(required: [AST::Types::Literal.new(value: index), elem_type],
584
- optional: [],
585
- rest: nil,
586
- required_keywords: {},
587
- optional_keywords: {},
588
- rest_keywords: nil),
635
+ type: Interface::Function.new(
636
+ params: Interface::Function::Params.new(required: [AST::Types::Literal.new(value: index), elem_type],
637
+ optional: [],
638
+ rest: nil,
639
+ required_keywords: {},
640
+ optional_keywords: {},
641
+ rest_keywords: nil),
642
+ return_type: elem_type,
643
+ location: nil
644
+ ),
589
645
  block: nil,
590
- return_type: elem_type,
591
- method_def: nil,
592
- location: nil
646
+ method_decls: Set[]
593
647
  )
594
648
  } + update.method_types
595
649
  )
@@ -600,11 +654,13 @@ module Steep
600
654
  method_types: [
601
655
  Interface::MethodType.new(
602
656
  type_params: [],
603
- params: Interface::Params.empty,
657
+ type: Interface::Function.new(
658
+ params: Interface::Function::Params.empty,
659
+ return_type: type.types[0] || AST::Builtin.nil_type,
660
+ location: nil
661
+ ),
604
662
  block: nil,
605
- return_type: type.types[0] || AST::Builtin.nil_type,
606
- method_def: nil,
607
- location: nil
663
+ method_decls: Set[]
608
664
  )
609
665
  ]
610
666
  )
@@ -615,11 +671,13 @@ module Steep
615
671
  method_types: [
616
672
  Interface::MethodType.new(
617
673
  type_params: [],
618
- params: Interface::Params.empty,
674
+ type: Interface::Function.new(
675
+ params: Interface::Function::Params.empty,
676
+ return_type: type.types.last || AST::Builtin.nil_type,
677
+ location: nil
678
+ ),
619
679
  block: nil,
620
- return_type: type.types.last || AST::Builtin.nil_type,
621
- method_def: nil,
622
- location: nil
680
+ method_decls: Set[]
623
681
  )
624
682
  ]
625
683
  )
@@ -640,18 +698,21 @@ module Steep
640
698
  Interface::Interface::Entry.new(
641
699
  method_types: type.elements.map {|key_value, value_type|
642
700
  key_type = Literal.new(value: key_value, location: nil)
701
+
643
702
  Interface::MethodType.new(
644
703
  type_params: [],
645
- params: Interface::Params.new(required: [key_type],
646
- optional: [],
647
- rest: nil,
648
- required_keywords: {},
649
- optional_keywords: {},
650
- rest_keywords: nil),
704
+ type: Interface::Function.new(
705
+ params: Interface::Function::Params.new(required: [key_type],
706
+ optional: [],
707
+ rest: nil,
708
+ required_keywords: {},
709
+ optional_keywords: {},
710
+ rest_keywords: nil),
711
+ return_type: value_type,
712
+ location: nil
713
+ ),
651
714
  block: nil,
652
- return_type: value_type,
653
- method_def: nil,
654
- location: nil
715
+ method_decls: Set[]
655
716
  )
656
717
  } + ref.method_types
657
718
  )
@@ -663,16 +724,17 @@ module Steep
663
724
  key_type = Literal.new(value: key_value, location: nil)
664
725
  Interface::MethodType.new(
665
726
  type_params: [],
666
- params: Interface::Params.new(required: [key_type, value_type],
667
- optional: [],
668
- rest: nil,
669
- required_keywords: {},
670
- optional_keywords: {},
671
- rest_keywords: nil),
727
+ type: Interface::Function.new(
728
+ params: Interface::Function::Params.new(required: [key_type, value_type],
729
+ optional: [],
730
+ rest: nil,
731
+ required_keywords: {},
732
+ optional_keywords: {},
733
+ rest_keywords: nil),
734
+ return_type: value_type,
735
+ location: nil),
672
736
  block: nil,
673
- return_type: value_type,
674
- method_def: nil,
675
- location: nil
737
+ method_decls: Set[]
676
738
  )
677
739
  } + update.method_types
678
740
  )
@@ -684,15 +746,18 @@ module Steep
684
746
  interface(Builtin::Proc.instance_type, private: private, self_type: self_type).tap do |interface|
685
747
  method_type = Interface::MethodType.new(
686
748
  type_params: [],
687
- params: type.params,
688
- return_type: type.return_type,
689
- block: nil,
690
- method_def: nil,
691
- location: nil
749
+ type: type.type,
750
+ block: type.block,
751
+ method_decls: Set[]
692
752
  )
693
753
 
694
- interface.methods[:[]] = Interface::Interface::Entry.new(method_types: [method_type])
695
754
  interface.methods[:call] = Interface::Interface::Entry.new(method_types: [method_type])
755
+
756
+ if type.block_required?
757
+ interface.methods.delete(:[])
758
+ else
759
+ interface.methods[:[]] = Interface::Interface::Entry.new(method_types: [method_type.with(block: nil)])
760
+ end
696
761
  end
697
762
 
698
763
  when Logic::Base