steep 0.1.0.pre2 → 0.1.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 (119) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -1
  3. data/README.md +146 -33
  4. data/bin/smoke_runner.rb +43 -10
  5. data/lib/steep/ast/annotation/collection.rb +93 -0
  6. data/lib/steep/ast/annotation.rb +131 -0
  7. data/lib/steep/ast/buffer.rb +47 -0
  8. data/lib/steep/ast/location.rb +82 -0
  9. data/lib/steep/ast/method_type.rb +116 -0
  10. data/lib/steep/ast/signature/class.rb +33 -0
  11. data/lib/steep/ast/signature/const.rb +17 -0
  12. data/lib/steep/ast/signature/env.rb +123 -0
  13. data/lib/steep/ast/signature/extension.rb +21 -0
  14. data/lib/steep/ast/signature/gvar.rb +17 -0
  15. data/lib/steep/ast/signature/interface.rb +31 -0
  16. data/lib/steep/ast/signature/members.rb +71 -0
  17. data/lib/steep/ast/signature/module.rb +21 -0
  18. data/lib/steep/ast/type_params.rb +13 -0
  19. data/lib/steep/ast/types/any.rb +39 -0
  20. data/lib/steep/ast/types/bot.rb +39 -0
  21. data/lib/steep/ast/types/class.rb +35 -0
  22. data/lib/steep/ast/types/helper.rb +21 -0
  23. data/lib/steep/ast/types/instance.rb +39 -0
  24. data/lib/steep/ast/types/intersection.rb +74 -0
  25. data/lib/steep/ast/types/name.rb +124 -0
  26. data/lib/steep/ast/types/self.rb +39 -0
  27. data/lib/steep/ast/types/top.rb +39 -0
  28. data/lib/steep/ast/types/union.rb +74 -0
  29. data/lib/steep/ast/types/var.rb +57 -0
  30. data/lib/steep/ast/types/void.rb +35 -0
  31. data/lib/steep/cli.rb +28 -1
  32. data/lib/steep/drivers/annotations.rb +32 -0
  33. data/lib/steep/drivers/check.rb +53 -77
  34. data/lib/steep/drivers/scaffold.rb +303 -0
  35. data/lib/steep/drivers/utils/each_signature.rb +66 -0
  36. data/lib/steep/drivers/utils/validator.rb +115 -0
  37. data/lib/steep/drivers/validate.rb +39 -0
  38. data/lib/steep/errors.rb +291 -19
  39. data/lib/steep/interface/abstract.rb +44 -0
  40. data/lib/steep/interface/builder.rb +470 -0
  41. data/lib/steep/interface/instantiated.rb +126 -0
  42. data/lib/steep/interface/ivar_chain.rb +26 -0
  43. data/lib/steep/interface/method.rb +60 -0
  44. data/lib/steep/{interface.rb → interface/method_type.rb} +111 -100
  45. data/lib/steep/interface/substitution.rb +65 -0
  46. data/lib/steep/module_name.rb +116 -0
  47. data/lib/steep/parser.rb +1314 -814
  48. data/lib/steep/parser.y +536 -175
  49. data/lib/steep/source.rb +220 -25
  50. data/lib/steep/subtyping/check.rb +673 -0
  51. data/lib/steep/subtyping/constraints.rb +275 -0
  52. data/lib/steep/subtyping/relation.rb +41 -0
  53. data/lib/steep/subtyping/result.rb +126 -0
  54. data/lib/steep/subtyping/trace.rb +48 -0
  55. data/lib/steep/subtyping/variable_occurrence.rb +49 -0
  56. data/lib/steep/subtyping/variable_variance.rb +69 -0
  57. data/lib/steep/type_construction.rb +1630 -524
  58. data/lib/steep/type_inference/block_params.rb +100 -0
  59. data/lib/steep/type_inference/constant_env.rb +55 -0
  60. data/lib/steep/type_inference/send_args.rb +222 -0
  61. data/lib/steep/type_inference/type_env.rb +226 -0
  62. data/lib/steep/type_name.rb +27 -7
  63. data/lib/steep/typing.rb +4 -0
  64. data/lib/steep/version.rb +1 -1
  65. data/lib/steep.rb +71 -16
  66. data/smoke/and/a.rb +4 -2
  67. data/smoke/array/a.rb +4 -5
  68. data/smoke/array/b.rb +4 -4
  69. data/smoke/block/a.rb +2 -2
  70. data/smoke/block/a.rbi +2 -0
  71. data/smoke/block/b.rb +15 -0
  72. data/smoke/case/a.rb +3 -3
  73. data/smoke/class/a.rb +3 -3
  74. data/smoke/class/b.rb +0 -2
  75. data/smoke/class/d.rb +2 -2
  76. data/smoke/class/e.rb +1 -1
  77. data/smoke/class/f.rb +2 -2
  78. data/smoke/class/g.rb +8 -0
  79. data/smoke/const/a.rb +3 -3
  80. data/smoke/dstr/a.rb +1 -1
  81. data/smoke/ensure/a.rb +22 -0
  82. data/smoke/enumerator/a.rb +6 -6
  83. data/smoke/enumerator/b.rb +22 -0
  84. data/smoke/extension/a.rb +2 -2
  85. data/smoke/extension/b.rb +3 -3
  86. data/smoke/extension/c.rb +1 -1
  87. data/smoke/hello/hello.rb +2 -2
  88. data/smoke/if/a.rb +4 -2
  89. data/smoke/kwbegin/a.rb +8 -0
  90. data/smoke/literal/a.rb +5 -5
  91. data/smoke/method/a.rb +5 -5
  92. data/smoke/method/a.rbi +4 -0
  93. data/smoke/method/b.rb +29 -0
  94. data/smoke/module/a.rb +3 -3
  95. data/smoke/module/a.rbi +9 -0
  96. data/smoke/module/b.rb +2 -2
  97. data/smoke/module/c.rb +1 -1
  98. data/smoke/module/d.rb +5 -0
  99. data/smoke/module/e.rb +13 -0
  100. data/smoke/module/f.rb +13 -0
  101. data/smoke/rescue/a.rb +62 -0
  102. data/smoke/super/a.rb +2 -2
  103. data/smoke/type_case/a.rb +35 -0
  104. data/smoke/yield/a.rb +2 -2
  105. data/stdlib/builtin.rbi +463 -24
  106. data/steep.gemspec +3 -2
  107. metadata +91 -29
  108. data/lib/steep/annotation.rb +0 -223
  109. data/lib/steep/signature/class.rb +0 -450
  110. data/lib/steep/signature/extension.rb +0 -51
  111. data/lib/steep/signature/interface.rb +0 -49
  112. data/lib/steep/types/any.rb +0 -31
  113. data/lib/steep/types/class.rb +0 -27
  114. data/lib/steep/types/instance.rb +0 -27
  115. data/lib/steep/types/merge.rb +0 -32
  116. data/lib/steep/types/name.rb +0 -57
  117. data/lib/steep/types/union.rb +0 -42
  118. data/lib/steep/types/var.rb +0 -38
  119. data/lib/steep/types.rb +0 -4
@@ -0,0 +1,82 @@
1
+ module Steep
2
+ module AST
3
+ class Location
4
+ attr_reader :buffer
5
+ attr_reader :start_pos
6
+ attr_reader :end_pos
7
+
8
+ def initialize(buffer:, start_pos:, end_pos:)
9
+ @buffer = buffer
10
+ @start_pos = start_pos
11
+ @end_pos = end_pos
12
+ end
13
+
14
+ def inspect
15
+ "#<#{self.class}:#{self.__id__} @buffer=..., @start_pos=#{start_pos}, @end_pos=#{end_pos}, source='#{source.lines.first}', start_line=#{start_line}, start_column=#{start_column}>"
16
+ end
17
+
18
+ def name
19
+ buffer.name
20
+ end
21
+
22
+ def start_line
23
+ start_loc[0]
24
+ end
25
+
26
+ def start_column
27
+ start_loc[1]
28
+ end
29
+
30
+ def end_line
31
+ end_loc[0]
32
+ end
33
+
34
+ def end_column
35
+ end_loc[1]
36
+ end
37
+
38
+ def start_loc
39
+ @start_loc ||= buffer.pos_to_loc(start_pos)
40
+ end
41
+
42
+ def end_loc
43
+ @end_loc ||= buffer.pos_to_loc(end_pos)
44
+ end
45
+
46
+ def source
47
+ @source ||= buffer.source(start_pos...end_pos)
48
+ end
49
+
50
+ def to_s
51
+ "#{start_line}:#{start_column}...#{end_line}:#{end_column}"
52
+ end
53
+
54
+ def ==(other)
55
+ other.is_a?(Location) &&
56
+ other.buffer == buffer &&
57
+ other.start_pos == start_pos &&
58
+ other.end_pos == end_pos
59
+ end
60
+
61
+ def +(other)
62
+ raise "Invalid concat: buffer=#{buffer.name}, other.buffer=#{other.buffer.name}" unless other.buffer == buffer
63
+
64
+ self.class.new(buffer: buffer,
65
+ start_pos: start_pos,
66
+ end_pos: other.end_pos)
67
+ end
68
+
69
+ def self.concat(*locations)
70
+ locations.inject {|l1, l2|
71
+ l1 + l2
72
+ }
73
+ end
74
+
75
+ def pred?(loc)
76
+ loc.is_a?(Location) &&
77
+ loc.name == name &&
78
+ loc.start_pos == end_pos
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,116 @@
1
+ module Steep
2
+ module AST
3
+ class MethodType
4
+ module Params
5
+ class Base
6
+ attr_reader :location
7
+
8
+ def initialize(location:)
9
+ @location = location
10
+ end
11
+
12
+ def update_location(location)
13
+ dup.instance_eval do
14
+ @location = location
15
+ self
16
+ end
17
+ end
18
+ end
19
+
20
+ class Required < Base
21
+ attr_reader :type
22
+ attr_reader :next_params
23
+
24
+ def initialize(location:, type:, next_params: nil)
25
+ super(location: location)
26
+ @type = type
27
+ @next_params = next_params
28
+ end
29
+ end
30
+
31
+ class Optional < Base
32
+ attr_reader :type
33
+ attr_reader :next_params
34
+
35
+ def initialize(location:, type:, next_params: nil)
36
+ super(location: location)
37
+ @type = type
38
+ @next_params = next_params
39
+ end
40
+ end
41
+
42
+ class Rest < Base
43
+ attr_reader :type
44
+ attr_reader :next_params
45
+
46
+ def initialize(location:, type:, next_params: nil)
47
+ super(location: location)
48
+ @type = type
49
+ @next_params = next_params
50
+ end
51
+ end
52
+
53
+ class RequiredKeyword < Base
54
+ attr_reader :name
55
+ attr_reader :type
56
+ attr_reader :next_params
57
+
58
+ def initialize(location:, name:, type:, next_params: nil)
59
+ super(location: location)
60
+ @name = name
61
+ @type = type
62
+ @next_params = next_params
63
+ end
64
+ end
65
+
66
+ class OptionalKeyword < Base
67
+ attr_reader :name
68
+ attr_reader :type
69
+ attr_reader :next_params
70
+
71
+ def initialize(location:, name:, type:, next_params: nil)
72
+ super(location: location)
73
+ @name = name
74
+ @type = type
75
+ @next_params = next_params
76
+ end
77
+ end
78
+
79
+ class RestKeyword < Base
80
+ attr_reader :type
81
+
82
+ def initialize(location:, type:)
83
+ super(location: location)
84
+ @type = type
85
+ end
86
+ end
87
+ end
88
+
89
+ class Block
90
+ attr_reader :location
91
+ attr_reader :params
92
+ attr_reader :return_type
93
+
94
+ def initialize(location:, params:, return_type:)
95
+ @location = location
96
+ @params = params
97
+ @return_type = return_type
98
+ end
99
+ end
100
+
101
+ attr_reader :location
102
+ attr_reader :type_params
103
+ attr_reader :params
104
+ attr_reader :block
105
+ attr_reader :return_type
106
+
107
+ def initialize(location:, type_params:, params:, block:, return_type:)
108
+ @location = location
109
+ @type_params = type_params
110
+ @params = params
111
+ @block = block
112
+ @return_type = return_type
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,33 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class SuperClass
5
+ attr_reader :location
6
+ attr_reader :name
7
+ attr_reader :args
8
+
9
+ def initialize(name:, args:, location:)
10
+ @name = name
11
+ @args = args
12
+ @location = location
13
+ end
14
+ end
15
+
16
+ class Class
17
+ attr_reader :location
18
+ attr_reader :name
19
+ attr_reader :params
20
+ attr_reader :super_class
21
+ attr_reader :members
22
+
23
+ def initialize(name:, params:, super_class:, location:, members:)
24
+ @name = name
25
+ @params = params
26
+ @super_class = super_class
27
+ @location = location
28
+ @members = members
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class Const
5
+ attr_reader :location
6
+ attr_reader :name
7
+ attr_reader :type
8
+
9
+ def initialize(location:, name:, type:)
10
+ @location = location
11
+ @name = name
12
+ @type = type
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,123 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class Env
5
+ attr_reader :modules
6
+ attr_reader :classes
7
+ attr_reader :extensions
8
+ attr_reader :interfaces
9
+ attr_reader :constants
10
+ attr_reader :globals
11
+
12
+ def initialize()
13
+ @modules = {}
14
+ @classes = {}
15
+ @extensions = {}
16
+ @interfaces = {}
17
+ @constants = {}
18
+ @globals = {}
19
+ end
20
+
21
+ def add(sig)
22
+ case sig
23
+ when Signature::Class
24
+ raise "Duplicated class: #{sig.name}" if classes.key?(sig.name.absolute!) || modules.key?(sig.name.absolute!)
25
+ classes[sig.name.absolute!] = sig
26
+ when Signature::Module
27
+ raise "Duplicated module: #{sig.name}" if classes.key?(sig.name.absolute!) || modules.key?(sig.name.absolute!)
28
+ modules[sig.name.absolute!] = sig
29
+ when Signature::Interface
30
+ raise "Duplicated interface: #{sig.name}" if interfaces.key?(sig.name)
31
+ interfaces[sig.name] = sig
32
+ when Signature::Extension
33
+ extensions[sig.module_name.absolute!] ||= []
34
+ if extensions[sig.module_name.absolute!].any? {|ext| ext.name == sig.name }
35
+ raise "Duplicated extension: #{sig.module_name.absolute!} (#{sig.name})"
36
+ end
37
+ extensions[sig.module_name.absolute!] << sig
38
+ when Signature::Const
39
+ constants[sig.name.absolute!] = sig
40
+ when Signature::Gvar
41
+ raise "Duplicated global: #{sig.name}" if globals.key?(sig.name)
42
+ globals[sig.name] = sig
43
+ else
44
+ raise "Unknown signature:: #{sig}"
45
+ end
46
+ end
47
+
48
+ def find_module(name, current_module: nil)
49
+ find_name(modules, name, current_module: current_module) or raise "Unknown module: #{name}"
50
+ end
51
+
52
+ def find_class(name, current_module: nil)
53
+ find_name(classes, name, current_module: current_module) or raise "Unknown class: #{name}"
54
+ end
55
+
56
+ def find_class_or_module(name, current_module: nil)
57
+ sig =
58
+ find_name(modules, name, current_module: current_module) ||
59
+ find_name(classes, name, current_module: current_module)
60
+
61
+ sig or raise "Unknown class/module: #{name}}"
62
+ end
63
+
64
+ def find_extensions(name, current_module: nil)
65
+ find_name(extensions, name, current_module: current_module) || []
66
+ end
67
+
68
+ def find_const(name, current_module: nil)
69
+ find_name(constants, name, current_module: current_module)
70
+ end
71
+
72
+ def find_gvar(name)
73
+ globals[name]
74
+ end
75
+
76
+ def find_name(hash, name, current_module:)
77
+ if current_module
78
+ hash[current_module + name] || find_name(hash, name, current_module: current_module.parent)
79
+ else
80
+ hash[name.absolute!]
81
+ end
82
+ end
83
+
84
+ def find_interface(name)
85
+ interfaces[name] or raise "Unknown interface: #{name}"
86
+ end
87
+
88
+ def module?(type_name, current_module: nil)
89
+ name = type_name.map_module_name {|m| current_module ? current_module + m : m.absolute! }.name
90
+ modules.key?(name)
91
+ end
92
+
93
+ def class?(type_name, current_module: nil)
94
+ name = type_name.map_module_name {|m| current_module ? current_name + m : m.absolute! }.name
95
+ classes.key?(name)
96
+ end
97
+
98
+ def class_name?(name, current_module: nil)
99
+ classes.key?(current_module ? current_module + name : name.absolute!)
100
+ end
101
+
102
+ def module_name?(name, current_module: nil)
103
+ modules.key?(current_module ? current_module + name : name.absolute!)
104
+ end
105
+
106
+ def const_name?(name, current_module: nil)
107
+ constants.key?(current_module ? current_module + name : name.absolute!)
108
+ end
109
+
110
+ def each(&block)
111
+ if block_given?
112
+ classes.each_value(&block)
113
+ modules.each_value(&block)
114
+ interfaces.each_value(&block)
115
+ constants.each_value(&block)
116
+ else
117
+ enum_for :each
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,21 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class Extension
5
+ attr_reader :location
6
+ attr_reader :module_name
7
+ attr_reader :name
8
+ attr_reader :members
9
+ attr_reader :params
10
+
11
+ def initialize(location:, module_name:, params:, name:, members:)
12
+ @location = location
13
+ @module_name = module_name
14
+ @params = params
15
+ @name = name
16
+ @members = members
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,17 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class Gvar
5
+ attr_reader :location
6
+ attr_reader :name
7
+ attr_reader :type
8
+
9
+ def initialize(location:, name:, type:)
10
+ @location = location
11
+ @name = name
12
+ @type = type
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,31 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class Interface
5
+ class Method
6
+ attr_reader :location
7
+ attr_reader :name
8
+ attr_reader :types
9
+
10
+ def initialize(location:, name:, types:)
11
+ @location = location
12
+ @name = name
13
+ @types = types
14
+ end
15
+ end
16
+
17
+ attr_reader :location
18
+ attr_reader :name
19
+ attr_reader :params
20
+ attr_reader :methods
21
+
22
+ def initialize(location:, name:, params:, methods:)
23
+ @location = location
24
+ @name = name
25
+ @params = params
26
+ @methods = methods
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,71 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ module Members
5
+ class Include
6
+ attr_reader :location
7
+ attr_reader :name
8
+ attr_reader :args
9
+
10
+ def initialize(location:, name:, args:)
11
+ @location = location
12
+ @name = name
13
+ @args = args
14
+ end
15
+ end
16
+
17
+ class Extend
18
+ attr_reader :location
19
+ attr_reader :name
20
+ attr_reader :args
21
+
22
+ def initialize(location:, name:, args:)
23
+ @location = location
24
+ @name = name
25
+ @args = args
26
+ end
27
+ end
28
+
29
+ class Method
30
+ attr_reader :location
31
+ attr_reader :name
32
+ attr_reader :kind
33
+ attr_reader :types
34
+ attr_reader :attributes
35
+
36
+ def initialize(location:, name:, kind:, types:, attributes:)
37
+ @location = location
38
+ @name = name
39
+ @kind = kind
40
+ @types = types
41
+ @attributes = attributes
42
+ end
43
+
44
+ def module_method?
45
+ kind == :module || kind == :module_instance
46
+ end
47
+
48
+ def instance_method?
49
+ kind == :instance || kind == :module_instance
50
+ end
51
+
52
+ def constructor?
53
+ attributes.include?(:constructor)
54
+ end
55
+ end
56
+
57
+ class Ivar
58
+ attr_reader :location
59
+ attr_reader :name
60
+ attr_reader :type
61
+
62
+ def initialize(location:, name:, type:)
63
+ @location = location
64
+ @name = name
65
+ @type = type
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,21 @@
1
+ module Steep
2
+ module AST
3
+ module Signature
4
+ class Module
5
+ attr_reader :location
6
+ attr_reader :name
7
+ attr_reader :params
8
+ attr_reader :self_type
9
+ attr_reader :members
10
+
11
+ def initialize(name:, location:, params:, self_type:, members:)
12
+ @name = name
13
+ @location = location
14
+ @params = params
15
+ @self_type = self_type
16
+ @members = members
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module Steep
2
+ module AST
3
+ class TypeParams
4
+ attr_reader :location
5
+ attr_reader :variables
6
+
7
+ def initialize(location: nil, variables:)
8
+ @location = location
9
+ @variables = variables
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,39 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ class Any
5
+ attr_reader :location
6
+
7
+ def initialize(location: nil)
8
+ @location = location
9
+ end
10
+
11
+ def ==(other)
12
+ other.is_a?(Any)
13
+ end
14
+
15
+ def hash
16
+ self.class.hash
17
+ end
18
+
19
+ alias eql? ==
20
+
21
+ def subst(s)
22
+ self
23
+ end
24
+
25
+ def to_s
26
+ "any"
27
+ end
28
+
29
+ def free_variables
30
+ Set.new
31
+ end
32
+
33
+ def level
34
+ [1]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,39 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ class Bot
5
+ attr_reader :location
6
+
7
+ def initialize(location: nil)
8
+ @location = location
9
+ end
10
+
11
+ def ==(other)
12
+ other.is_a?(Bot)
13
+ end
14
+
15
+ def hash
16
+ self.class.hash
17
+ end
18
+
19
+ alias eql? ==
20
+
21
+ def subst(s)
22
+ self
23
+ end
24
+
25
+ def to_s
26
+ "⟘"
27
+ end
28
+
29
+ def free_variables
30
+ Set.new
31
+ end
32
+
33
+ def level
34
+ [2]
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,35 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ class Class
5
+ attr_reader :location
6
+
7
+ def initialize(location: nil)
8
+ @location = location
9
+ end
10
+
11
+ def ==(other)
12
+ other.is_a?(Class)
13
+ end
14
+
15
+ def hash
16
+ self.class.hash
17
+ end
18
+
19
+ alias eql? ==
20
+
21
+ def subst(s)
22
+ s.module_type or raise "Unexpected substitution: #{inspect}"
23
+ end
24
+
25
+ def free_variables
26
+ Set.new
27
+ end
28
+
29
+ def level
30
+ [0]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,21 @@
1
+ module Steep
2
+ module AST
3
+ module Types
4
+ module Helper
5
+ module ChildrenLevel
6
+ def level_of_children(children)
7
+ children.map(&:level).sort {|a, b| b.size <=> a.size }.inject() do |a, b|
8
+ a.zip(b).map do |(x, y)|
9
+ if x && y
10
+ x + y
11
+ else
12
+ x || y
13
+ end
14
+ end
15
+ end || []
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end