steep 0.1.0.pre2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/lib/steep/parser.y CHANGED
@@ -1,84 +1,191 @@
1
1
  class Steep::Parser
2
2
 
3
+ expect 1
4
+
3
5
  rule
4
6
 
5
7
  target: type_METHOD method_type { result = val[1] }
6
8
  | type_SIGNATURE signatures { result = val[1] }
7
9
  | type_ANNOTATION annotation { result = val[1] }
8
10
 
9
- method_type: type_params params block_opt ARROW return_type
10
- { result = Interface::MethodType.new(type_params: val[0], params: val[1], block: val[2], return_type: val[4]) }
11
+ method_type:
12
+ type_params params block_opt ARROW return_type {
13
+ result = AST::MethodType.new(location: AST::Location.concat(*val.compact.map(&:location)),
14
+ type_params: val[0],
15
+ params: val[1]&.value,
16
+ block: val[2],
17
+ return_type: val[4])
18
+ }
11
19
 
12
20
  return_type: simple_type
13
- | LPAREN union_seq RPAREN { result = Types::Union.new(types: val[1]) }
14
-
15
- params: { result = Interface::Params.empty }
16
- | LPAREN params0 RPAREN { result = val[1] }
17
- | type { result = Interface::Params.empty.with(required: [val[0]]) }
18
-
19
- params0: required_param { result = Interface::Params.empty.with(required: [val[0]]) }
20
- | required_param COMMA params0 { result = val[2].with(required: [val[0]] + val[2].required) }
21
+ | LPAREN union_seq RPAREN { result = AST::Types::Union.build(location: val[0].location + val[2].location,
22
+ types: val[1]) }
23
+
24
+ params: { result = nil }
25
+ | LPAREN params0 RPAREN { result = LocatedValue.new(location: val[0].location + val[2].location,
26
+ value: val[1]) }
27
+ | type { result = LocatedValue.new(location: val[0].location,
28
+ value: AST::MethodType::Params::Required.new(location: val[0].location, type: val[0])) }
29
+
30
+ params0: required_param { result = AST::MethodType::Params::Required.new(location: val[0].location, type: val[0]) }
31
+ | required_param COMMA params0 {
32
+ location = val[0].location
33
+ result = AST::MethodType::Params::Required.new(location: location,
34
+ type: val[0],
35
+ next_params: val[2])
36
+ }
21
37
  | params1 { result = val[0] }
22
38
 
23
- params1: optional_param { result = Interface::Params.empty.with(optional: [val[0]]) }
24
- | optional_param COMMA params1 { result = val[2].with(optional: [val[0]] + val[2].optional) }
39
+ params1: optional_param { result = AST::MethodType::Params::Optional.new(location: val[0].first, type: val[0].last) }
40
+ | optional_param COMMA params1 {
41
+ location = val[0].first
42
+ result = AST::MethodType::Params::Optional.new(type: val[0].last, location: location, next_params: val[2])
43
+ }
25
44
  | params2 { result = val[0] }
26
45
 
27
- params2: rest_param { result = Interface::Params.empty.with(rest: val[0]) }
28
- | rest_param COMMA params3 { result = val[2].with(rest: val[0]) }
46
+ params2: rest_param { result = AST::MethodType::Params::Rest.new(location: val[0].first, type: val[0].last) }
47
+ | rest_param COMMA params3 {
48
+ loc = val[0].first
49
+ result = AST::MethodType::Params::Rest.new(location: loc, type: val[0].last, next_params: val[2])
50
+ }
29
51
  | params3 { result = val[0] }
30
52
 
31
- params3: required_keyword { result = Interface::Params.empty.with(required_keywords: val[0]) }
32
- | optional_keyword { result = Interface::Params.empty.with(optional_keywords: val[0]) }
33
- | required_keyword COMMA params3 { result = val[2].with(required_keywords: val[2].required_keywords.merge(val[0])) }
34
- | optional_keyword COMMA params3 { result = val[2].with(optional_keywords: val[2].optional_keywords.merge(val[0])) }
53
+ params3: required_keyword {
54
+ location, name, type = val[0]
55
+ result = AST::MethodType::Params::RequiredKeyword.new(location: location, name: name, type: type)
56
+ }
57
+ | optional_keyword {
58
+ location, name, type = val[0]
59
+ result = AST::MethodType::Params::OptionalKeyword.new(location: location, name: name, type: type)
60
+ }
61
+ | required_keyword COMMA params3 {
62
+ location, name, type = val[0]
63
+ result = AST::MethodType::Params::RequiredKeyword.new(location: location,
64
+ name: name,
65
+ type: type,
66
+ next_params: val[2])
67
+ }
68
+ | optional_keyword COMMA params3 {
69
+ location, name, type = val[0]
70
+ result = AST::MethodType::Params::OptionalKeyword.new(location: location,
71
+ name: name,
72
+ type: type,
73
+ next_params: val[2])
74
+ }
35
75
  | params4 { result = val[0] }
36
76
 
37
- params4: { result = Interface::Params.empty }
38
- | STAR2 type { result = Interface::Params.empty.with(rest_keywords: val[1]) }
77
+ params4: { result = nil }
78
+ | STAR2 type {
79
+ result = AST::MethodType::Params::RestKeyword.new(location: val[0].location + val[1].location,
80
+ type: val[1])
81
+ }
39
82
 
40
83
  required_param: type { result = val[0] }
41
- optional_param: QUESTION type { result = val[1] }
42
- rest_param: STAR type { result = val[1] }
43
- required_keyword: keyword COLON type { result = { val[0] => val[2] } }
44
- optional_keyword: QUESTION keyword COLON type { result = { val[1] => val[3] } }
84
+ optional_param: QUESTION type { result = [val[0].location + val[1].location,
85
+ val[1]] }
86
+ rest_param: STAR type { result = [val[0].location + val[1].location,
87
+ val[1]] }
88
+ required_keyword: keyword COLON type { result = [val[0].location + val[2].location,
89
+ val[0].value,
90
+ val[2]] }
91
+ optional_keyword: QUESTION keyword COLON type { result = [val[0].location + val[3].location,
92
+ val[1].value,
93
+ val[3]] }
45
94
 
46
95
  block_opt: { result = nil }
47
- | LBRACE RBRACE { result = Interface::Block.new(params: Interface::Params.empty.with(rest: Types::Any.new),
48
- return_type: Types::Any.new) }
49
- | LBRACE block_params ARROW type RBRACE { result = Interface::Block.new(params: val[1], return_type: val[3]) }
50
-
51
- block_params: LPAREN block_params0 RPAREN { result = val[1] }
52
- | { result = Interface::Params.empty.with(rest: Types::Any.new) }
53
-
54
- block_params0: required_param { result = Interface::Params.empty.with(required: [val[0]]) }
55
- | required_param COMMA block_params0 { result = val[2].with(required: [val[0]] + val[2].required) }
96
+ | LBRACE RBRACE {
97
+ result = AST::MethodType::Block.new(params: nil,
98
+ return_type: nil,
99
+ location: val[0].location + val[1].location)
100
+ }
101
+ | LBRACE block_params ARROW type RBRACE {
102
+ result = AST::MethodType::Block.new(params: val[1],
103
+ return_type: val[3],
104
+ location: val[0].location + val[4].location)
105
+ }
106
+
107
+ block_params: { result = nil }
108
+ | LPAREN block_params0 RPAREN {
109
+ result = val[1]
110
+ }
111
+
112
+ block_params0: required_param {
113
+ result = AST::MethodType::Params::Required.new(location: val[0].location,
114
+ type: val[0])
115
+ }
116
+ | required_param COMMA block_params0 {
117
+ result = AST::MethodType::Params::Required.new(location: val[0].location,
118
+ type: val[0],
119
+ next_params: val[2])
120
+ }
56
121
  | block_params1 { result = val[0] }
57
122
 
58
- block_params1: optional_param { result = Interface::Params.empty.with(optional: [val[0]]) }
59
- | optional_param COMMA block_params1 { result = val[2].with(optional: [val[0]] + val[2].optional) }
123
+ block_params1: optional_param {
124
+ result = AST::MethodType::Params::Optional.new(location: val[0].first,
125
+ type: val[0].last)
126
+ }
127
+ | optional_param COMMA block_params1 {
128
+ loc = val.first[0] + (val[2] || val[1]).location
129
+ type = val.first[1]
130
+ next_params = val[2]
131
+ result = AST::MethodType::Params::Optional.new(location: loc, type: type, next_params: next_params)
132
+ }
60
133
  | block_params2 { result = val[0] }
61
134
 
62
- block_params2: { result = Interface::Params.empty }
63
- | rest_param { result = Interface::Params.empty.with(rest: val[0]) }
64
-
65
- simple_type: INTERFACE_NAME { result = Types::Name.interface(name: val[0]) }
66
- | INTERFACE_NAME LT type_seq GT { result = Types::Name.interface(name: val[0], params: val[2]) }
67
- | MODULE_NAME { result = Types::Name.instance(name: val[0])}
68
- | MODULE_NAME LT type_seq GT { result = Types::Name.instance(name: val[0], params: val[2]) }
69
- | CLASS_IDENT constructor { result = Types::Name.module(name: val[0], constructor: val[1]) }
70
- | ANY { result = Types::Any.new }
71
- | TVAR { result = Types::Var.new(name: val[0]) }
72
- | CLASS { result = Types::Class.new }
73
- | MODULE { result = Types::Class.new }
74
- | INSTANCE { result = Types::Instance.new }
135
+ block_params2: { result = nil }
136
+ | rest_param {
137
+ result = AST::MethodType::Params::Rest.new(location: val[0].first, type: val[0].last)
138
+ }
139
+
140
+ simple_type: type_name {
141
+ result = AST::Types::Name.new(name: val[0].value, location: val[0].location, args: [])
142
+ }
143
+ | instance_type_name LT type_seq GT {
144
+ loc = val[0].location + val[3].location
145
+ name = val[0].value
146
+ args = val[2]
147
+ result = AST::Types::Name.new(location: loc, name: name, args: args)
148
+ }
149
+ | ANY { result = AST::Types::Any.new(location: val[0].location) }
150
+ | TVAR { result = AST::Types::Var.new(location: val[0].location, name: val[0].value) }
151
+ | CLASS { result = AST::Types::Class.new(location: val[0].location) }
152
+ | MODULE { result = AST::Types::Class.new(location: val[0].location) }
153
+ | INSTANCE { result = AST::Types::Instance.new(location: val[0].location) }
154
+ | SELF { result = AST::Types::Self.new(location: val[0].location) }
155
+ | VOID { result = AST::Types::Void.new(location: val[0].location) }
156
+ | NIL { result = AST::Types::Name.new_instance(name: ModuleName.new(name: "NilClass", absolute: true),
157
+ location: val[0].location) }
158
+
159
+ instance_type_name: module_name {
160
+ result = LocatedValue.new(value: TypeName::Instance.new(name: val[0].value),
161
+ location: val[0].location)
162
+ }
163
+ | INTERFACE_NAME {
164
+ result = LocatedValue.new(value: TypeName::Interface.new(name: val[0].value),
165
+ location: val[0].location)
166
+ }
167
+
168
+ type_name: instance_type_name
169
+ | module_name DOT CLASS constructor {
170
+ loc = val[0].location + (val[3] || val[2]).location
171
+ result = LocatedValue.new(value: TypeName::Class.new(name: val[0].value, constructor: val[3]&.value),
172
+ location: loc)
173
+ }
174
+ | module_name DOT MODULE {
175
+ loc = val[0].location + val.last.location
176
+ result = LocatedValue.new(value: TypeName::Module.new(name: val[0].value),
177
+ location: loc)
178
+ }
75
179
 
76
180
  constructor: { result = nil }
77
181
  | CONSTRUCTOR
78
182
  | NOCONSTRUCTOR
79
183
 
80
184
  type: simple_type
81
- | union_seq { result = Types::Union.new(types: val[0]) }
185
+ | union_seq {
186
+ loc = val[0].first.location + val[0].last.location
187
+ result = AST::Types::Union.build(types: val[0], location: loc)
188
+ }
82
189
 
83
190
  type_seq: type { result = [val[0]] }
84
191
  | type COMMA type_seq { result = [val[0]] + val[2] }
@@ -89,62 +196,195 @@ union_seq: simple_type BAR simple_type { result = [val[0], val[2]] }
89
196
  keyword: IDENT
90
197
  | MODULE_NAME
91
198
  | INTERFACE_NAME
92
- | ANY { result = :any }
93
- | CLASS { result = :class }
94
- | MODULE { result = :module }
95
- | INSTANCE { result = :instance }
96
- | BLOCK { result = :block }
97
- | INCLUDE { result = :include }
199
+ | ANY
200
+ | CLASS
201
+ | MODULE
202
+ | INSTANCE
203
+ | BLOCK
204
+ | INCLUDE
98
205
 
99
206
  signatures: { result = [] }
100
207
  | interface signatures { result = [val[0]] + val[1] }
101
208
  | class_decl signatures { result = [val[0]] + val[1] }
102
209
  | module_decl signatures { result = [val[0]] + val[1] }
103
210
  | extension_decl signatures { result = [val[0]] + val[1] }
104
-
105
- interface: INTERFACE interface_name type_params method_decls END { result = Signature::Interface.new(name: val[1], params: val[2], methods: val[3]) }
106
- class_decl: CLASS class_name type_params super_opt class_members END { result = Signature::Class.new(name: val[1], params: val[2], super_class: val[3], members: val[4] )}
107
- module_decl: MODULE class_name type_params self_type_opt class_members END { result = Signature::Module.new(name: val[1], params: val[2], self_type: val[3], members: val[4]) }
108
- extension_decl: EXTENSION class_name LPAREN class_name RPAREN class_members END { result = Signature::Extension.new(module_name: val[1], extension_name: val[3], members: val[5]) }
211
+ | const_decl signatures { result = [val[0]] + val[1] }
212
+ | gvar_decl signatures { result = [val[0]] + val[1] }
213
+
214
+ gvar_decl: GVAR COLON type {
215
+ loc = val.first.location + val.last.location
216
+ result = AST::Signature::Gvar.new(
217
+ location: loc,
218
+ name: val[0].value,
219
+ type: val[2]
220
+ )
221
+ }
222
+
223
+ const_decl: module_name COLON type {
224
+ loc = val.first.location + val.last.location
225
+ result = AST::Signature::Const.new(
226
+ location: loc,
227
+ name: val[0].value,
228
+ type: val[2]
229
+ )
230
+ }
231
+
232
+ interface: INTERFACE interface_name type_params interface_members END {
233
+ loc = val.first.location + val.last.location
234
+ result = AST::Signature::Interface.new(
235
+ location: loc,
236
+ name: val[1].value,
237
+ params: val[2],
238
+ methods: val[3]
239
+ )
240
+ }
241
+
242
+ class_decl: CLASS module_name type_params super_opt class_members END {
243
+ loc = val.first.location + val.last.location
244
+ result = AST::Signature::Class.new(name: val[1].value.absolute!,
245
+ params: val[2],
246
+ super_class: val[3],
247
+ members: val[4],
248
+ location: loc)
249
+ }
250
+ module_decl: MODULE module_name type_params self_type_opt class_members END {
251
+ loc = val.first.location + val.last.location
252
+ result = AST::Signature::Module.new(name: val[1].value.absolute!,
253
+ location: loc,
254
+ params: val[2],
255
+ self_type: val[3],
256
+ members: val[4])
257
+ }
258
+ extension_decl: EXTENSION module_name type_params LPAREN UIDENT RPAREN class_members END {
259
+ loc = val.first.location + val.last.location
260
+ result = AST::Signature::Extension.new(module_name: val[1].value.absolute!,
261
+ name: val[4].value,
262
+ location: loc,
263
+ params: val[2],
264
+ members: val[6])
265
+ }
109
266
 
110
267
  self_type_opt: { result = nil }
111
268
  | COLON type { result = val[1] }
112
269
 
113
- interface_name: INTERFACE_NAME { result = val[0] }
270
+ interface_name: INTERFACE_NAME
271
+
272
+ module_name: module_name0
273
+ | COLON2 module_name0 {
274
+ loc = val.first.location + val.last.location
275
+ result = LocatedValue.new(location: loc, value: val[1].value.absolute!)
276
+ }
114
277
 
115
- class_name: MODULE_NAME { result = val[0] }
278
+ module_name0: UIDENT {
279
+ result = LocatedValue.new(location: val[0].location, value: ModuleName.parse(val[0].value))
280
+ }
281
+ | UIDENT COLON2 module_name0 {
282
+ location = val[0].location + val.last.location
283
+ name = ModuleName.parse(val[0].value) + val.last.value
284
+ result = LocatedValue.new(location: location, value: name)
285
+ }
116
286
 
117
287
  class_members: { result = [] }
118
288
  | class_member class_members { result = [val[0]] + val[1] }
119
289
 
120
- class_member: instance_method_member { result = val[0] }
121
- | class_method_member { result = val[0] }
122
- | class_instance_method_member { result = val[0] }
123
- | include_member { result = val[0] }
124
- | extend_member { result = val[0] }
125
-
126
- instance_method_member: DEF constructor_method method_name COLON method_type_union { result = Signature::Members::InstanceMethod.new(name: val[2], types: val[4], constructor: val[1]) }
127
- class_method_member: DEF constructor_method SELF DOT method_name COLON method_type_union { result = Signature::Members::ModuleMethod.new(name: val[4], types: val[6], constructor: val[1]) }
128
- class_instance_method_member: DEF constructor_method SELFQ DOT method_name COLON method_type_union { result = Signature::Members::ModuleInstanceMethod.new(name: val[4], types: val[6], constructor: val[1]) }
129
- include_member: INCLUDE type { result = Signature::Members::Include.new(name: val[1]) }
130
- extend_member: EXTEND type { result = Signature::Members::Extend.new(name: val[1]) }
290
+ class_member: instance_method_member
291
+ | module_method_member
292
+ | module_instance_method_member
293
+ | include_member
294
+ | extend_member
295
+ | ivar_member
296
+
297
+ ivar_member: IVAR_NAME COLON type {
298
+ loc = val.first.location + val.last.location
299
+ result = AST::Signature::Members::Ivar.new(
300
+ location: loc,
301
+ name: val[0].value,
302
+ type: val[2]
303
+ )
304
+ }
305
+
306
+ instance_method_member: DEF constructor_method method_name COLON method_type_union {
307
+ loc = val.first.location + val.last.last.location
308
+ result = AST::Signature::Members::Method.new(
309
+ name: val[2].value,
310
+ types: val[4],
311
+ kind: :instance,
312
+ location: loc,
313
+ attributes: [val[1] ? :constructor : nil].compact
314
+ )
315
+ }
316
+ module_method_member: DEF constructor_method SELF DOT method_name COLON method_type_union {
317
+ loc = val.first.location + val.last.last.location
318
+ result = AST::Signature::Members::Method.new(
319
+ name: val[4].value,
320
+ types: val[6],
321
+ kind: :module,
322
+ location: loc,
323
+ attributes: [val[1] ? :constructor : nil].compact
324
+ )
325
+ }
326
+ module_instance_method_member: DEF constructor_method SELFQ DOT method_name COLON method_type_union {
327
+ loc = val.first.location + val.last.last.location
328
+ result = AST::Signature::Members::Method.new(
329
+ name: val[4].value,
330
+ types: val[6],
331
+ kind: :module_instance,
332
+ location: loc,
333
+ attributes: [val[1] ? :constructor : nil].compact
334
+ )
335
+ }
336
+ include_member: INCLUDE module_name {
337
+ loc = val.first.location + val.last.location
338
+ name = val[1].value
339
+ result = AST::Signature::Members::Include.new(name: name, location: loc, args: [])
340
+ }
341
+ | INCLUDE module_name LT type_seq GT {
342
+ loc = val.first.location + val.last.location
343
+ name = val[1].value
344
+ result = AST::Signature::Members::Include.new(name: name, location: loc, args: val[3])
345
+ }
346
+ extend_member: EXTEND module_name {
347
+ loc = val.first.location + val.last.location
348
+ name = val[1].value
349
+ result = AST::Signature::Members::Extend.new(name: name, location: loc, args: [])
350
+ }
351
+ | EXTEND module_name LT type_seq GT {
352
+ loc = val.first.location + val.last.location
353
+ name = val[1].value
354
+ result = AST::Signature::Members::Extend.new(name: name, location: loc, args: val[3])
355
+ }
131
356
 
132
357
  constructor_method: { result = false }
133
358
  | LPAREN CONSTRUCTOR RPAREN { result = true }
134
359
 
135
360
  super_opt: { result = nil }
136
- | LTCOLON type { result = val[1] }
137
-
138
- type_params: { result = [] }
139
- | LT type_param_seq GT { result = val[1] }
140
-
141
- type_param_seq: TVAR { result = [val[0]] }
142
- | TVAR COMMA type_param_seq { result = [val[0]] + val[2] }
143
-
144
- method_decls: { result = {} }
145
- | method_decl method_decls { result = val[1].merge(val[0]) }
146
-
147
- method_decl: DEF method_name COLON method_type_union { result = { val[1] => val[3] }}
361
+ | LTCOLON super_class { result = val[1] }
362
+
363
+ super_class: module_name {
364
+ result = AST::Signature::SuperClass.new(location: val[0].location, name: val[0].value, args: [])
365
+ }
366
+ | module_name LT type_seq GT {
367
+ loc = val[0].location + val[3].location
368
+ name = val[0].value
369
+ result = AST::Signature::SuperClass.new(location: loc, name: name, args: val[2])
370
+ }
371
+
372
+ type_params: { result = nil }
373
+ | LT type_param_seq GT {
374
+ location = val[0].location + val[2].location
375
+ result = AST::TypeParams.new(location: location, variables: val[1])
376
+ }
377
+
378
+ type_param_seq: TVAR { result = [val[0].value] }
379
+ | TVAR COMMA type_param_seq { result = [val[0].value] + val[2] }
380
+
381
+ interface_members: { result = [] }
382
+ | interface_method interface_members { result = val[1].unshift(val[0]) }
383
+
384
+ interface_method: DEF method_name COLON method_type_union {
385
+ loc = val[0].location + val[3].last.location
386
+ result = AST::Signature::Interface::Method.new(location: loc, name: val[1].value, types: val[3])
387
+ }
148
388
 
149
389
  method_type_union: method_type { result = [val[0]] }
150
390
  | method_type BAR method_type_union { result = [val[0]] + val[2] }
@@ -152,34 +392,107 @@ method_type_union: method_type { result = [val[0]] }
152
392
  method_name: IDENT
153
393
  | MODULE_NAME
154
394
  | INTERFACE_NAME
155
- | ANY { result = :any }
156
- | INTERFACE { result = :interface }
157
- | END { result = :end }
158
- | PLUS { result = :+ }
159
- | CLASS { result = :class }
160
- | MODULE { result = :module }
161
- | INSTANCE { result = :instance }
395
+ | ANY | VOID
396
+ | INTERFACE
397
+ | END
398
+ | PLUS
399
+ | CLASS
400
+ | MODULE
401
+ | INSTANCE
402
+ | EXTEND
403
+ | INCLUDE
162
404
  | OPERATOR
163
405
  | METHOD_NAME
164
- | BLOCK { result = :block }
165
- | INCLUDE { result = :include }
166
- | CONSTRUCTOR { result = :constructor }
167
- | NOCONSTRUCTOR { result = :noconstructor }
168
- | GT GT { result = :>> }
169
-
170
- annotation: AT_TYPE VAR subject COLON type { result = Annotation::VarType.new(var: val[2], type: val[4]) }
171
- | AT_TYPE METHOD subject COLON method_type { result = Annotation::MethodType.new(method: val[2], type: val[4]) }
172
- | AT_TYPE RETURN COLON type { result = Annotation::ReturnType.new(type: val[3]) }
173
- | AT_TYPE BLOCK COLON type { result = Annotation::BlockType.new(type: val[3]) }
174
- | AT_TYPE SELF COLON type { result = Annotation::SelfType.new(type: val[3]) }
175
- | AT_TYPE CONST CONST_PATH COLON type { result = Annotation::ConstType.new(name: val[2], type: val[4]) }
176
- | AT_TYPE CONST MODULE_NAME COLON type { result = Annotation::ConstType.new(name: val[2], type: val[4]) }
177
- | AT_TYPE INSTANCE COLON type { result = Annotation::InstanceType.new(type: val[3]) }
178
- | AT_TYPE MODULE COLON type { result = Annotation::ModuleType.new(type: val[3]) }
179
- | AT_TYPE IVAR IVAR_NAME COLON type { result = Annotation::IvarType.new(name: val[2], type: val[4]) }
180
- | AT_TYPE { raise "Invalid type annotation" }
181
- | AT_IMPLEMENTS MODULE_NAME { result = Annotation::Implements.new(module_name: val[1]) }
182
- | AT_DYNAMIC method_name { result = Annotation::Dynamic.new(name: val[1]) }
406
+ | BLOCK
407
+ | UIDENT
408
+ | BREAK
409
+ | STAR | STAR2
410
+ | PERCENT | MINUS
411
+ | LT | GT
412
+ | METHOD
413
+ | BAR { result = LocatedValue.new(location: val[0].location, value: :|) }
414
+ | CONSTRUCTOR { result = LocatedValue.new(location: val[0].location, value: :constructor) }
415
+ | NOCONSTRUCTOR { result = LocatedValue.new(location: val[0].location, value: :noconstructor) }
416
+ | ANY QUESTION {
417
+ raise ParseError, "\nunexpected method name any ?" unless val[0].location.pred?(val[1].location)
418
+ result = LocatedValue.new(location: val[0].location + val[1].location, value: :any?)
419
+ }
420
+ | GT GT {
421
+ raise ParseError, "\nunexpected method name > >" unless val[0].location.pred?(val[1].location)
422
+ result = LocatedValue.new(location: val[0].location + val[1].location, value: :>>)
423
+ }
424
+
425
+ annotation: AT_TYPE VAR subject COLON type {
426
+ loc = val.first.location + val.last.location
427
+ result = AST::Annotation::VarType.new(location: loc,
428
+ name: val[2].value,
429
+ type: val[4])
430
+ }
431
+ | AT_TYPE METHOD subject COLON method_type {
432
+ loc = val.first.location + val.last.location
433
+ result = AST::Annotation::MethodType.new(location: loc,
434
+ name: val[2].value,
435
+ type: val[4])
436
+ }
437
+ | AT_TYPE RETURN COLON type {
438
+ loc = val.first.location + val.last.location
439
+ result = AST::Annotation::ReturnType.new(type: val[3], location: loc)
440
+ }
441
+ | AT_TYPE BLOCK COLON type {
442
+ loc = val.first.location + val.last.location
443
+ result = AST::Annotation::BlockType.new(type: val[3], location: loc)
444
+ }
445
+ | AT_TYPE SELF COLON type {
446
+ loc = val.first.location + val.last.location
447
+ result = AST::Annotation::SelfType.new(type: val[3], location: loc)
448
+ }
449
+ | AT_TYPE CONST module_name COLON type {
450
+ loc = val.first.location + val.last.location
451
+ result = AST::Annotation::ConstType.new(name: val[2].value,
452
+ type: val[4],
453
+ location: loc)
454
+ }
455
+ | AT_TYPE INSTANCE COLON type {
456
+ loc = val.first.location + val.last.location
457
+ result = AST::Annotation::InstanceType.new(type: val[3], location: loc)
458
+ }
459
+ | AT_TYPE MODULE COLON type {
460
+ loc = val.first.location + val.last.location
461
+ result = AST::Annotation::ModuleType.new(type: val[3], location: loc)
462
+ }
463
+ | AT_TYPE IVAR IVAR_NAME COLON type {
464
+ loc = val.first.location + val.last.location
465
+ result = AST::Annotation::IvarType.new(name: val[2].value, type: val[4], location: loc)
466
+ }
467
+ | AT_IMPLEMENTS module_name type_params {
468
+ loc = val[0].location + (val[2]&.location || val[1].location)
469
+ args = val[2]&.variables || []
470
+ name = AST::Annotation::Implements::Module.new(name: val[1].value, args: args)
471
+ result = AST::Annotation::Implements.new(name: name, location: loc)
472
+ }
473
+ | AT_DYNAMIC dynamic_names {
474
+ loc = val[0].location + val[1].last.location
475
+ result = AST::Annotation::Dynamic.new(names: val[1], location: loc)
476
+ }
477
+ | AT_TYPE BREAK COLON type {
478
+ loc = val.first.location + val.last.location
479
+ result = AST::Annotation::BreakType.new(type: val[3], location: loc)
480
+ }
481
+
482
+ dynamic_names: dynamic_name COMMA dynamic_names { result = [val[0]] + val[2] }
483
+ | dynamic_name { result = val }
484
+
485
+ dynamic_name: method_name {
486
+ result = AST::Annotation::Dynamic::Name.new(name: val[0].value, location: val[0].location, kind: :instance)
487
+ }
488
+ | SELF DOT method_name {
489
+ loc = val.first.location + val.last.location
490
+ result = AST::Annotation::Dynamic::Name.new(name: val[2].value, location: loc, kind: :module)
491
+ }
492
+ | SELFQ DOT method_name {
493
+ loc = val.first.location + val.last.location
494
+ result = AST::Annotation::Dynamic::Name.new(name: val[2].value, location: loc, kind: :module_instance)
495
+ }
183
496
 
184
497
  subject: IDENT { result = val[0] }
185
498
 
@@ -190,27 +503,53 @@ end
190
503
  require "strscan"
191
504
 
192
505
  attr_reader :input
506
+ attr_reader :buffer
507
+ attr_reader :offset
193
508
 
194
- def initialize(type, input)
509
+ def initialize(type, buffer:, offset:, input: nil)
195
510
  super()
196
511
  @type = type
197
- @input = StringScanner.new(input)
512
+ @buffer = buffer
513
+ @input = StringScanner.new(input || buffer.content)
514
+ @offset = offset
198
515
  end
199
516
 
200
- def self.parse_method(input)
201
- new(:METHOD, input).do_parse
517
+ def self.parse_method(input, name: nil)
518
+ new(:METHOD, buffer: AST::Buffer.new(name: name, content: input), offset: 0).do_parse
202
519
  end
203
520
 
204
- def self.parse_signature(input)
205
- new(:SIGNATURE, input).do_parse
521
+ def self.parse_signature(input, name: nil)
522
+ new(:SIGNATURE, buffer: AST::Buffer.new(name: name, content: input), offset: 0).do_parse
206
523
  end
207
524
 
208
- def self.parse_annotation_opt(input)
209
- new(:ANNOTATION, input).do_parse
210
- rescue
525
+ def self.parse_annotation_opt(input, buffer:, offset: 0)
526
+ new(:ANNOTATION, input: input, buffer: buffer, offset: offset).do_parse
527
+ rescue => exn
528
+ Steep.logger.debug "Parsing comment failed: #{exn.inspect}"
211
529
  nil
212
530
  end
213
531
 
532
+ class LocatedValue
533
+ attr_reader :location
534
+ attr_reader :value
535
+
536
+ def initialize(location:, value:)
537
+ @location = location
538
+ @value = value
539
+ end
540
+ end
541
+
542
+ def new_token(type, value = nil)
543
+ start_index = offset + input.pos - input.matched.bytesize
544
+ end_index = offset + input.pos
545
+
546
+ location = AST::Location.new(buffer: buffer,
547
+ start_pos: start_index,
548
+ end_pos: end_index)
549
+
550
+ [type, LocatedValue.new(location: location, value: value)]
551
+ end
552
+
214
553
  def next_token
215
554
  if @type
216
555
  type = @type
@@ -226,104 +565,126 @@ def next_token
226
565
  when input.eos?
227
566
  [false, false]
228
567
  when input.scan(/->/)
229
- [:ARROW, nil]
568
+ new_token(:ARROW)
230
569
  when input.scan(/\?/)
231
- [:QUESTION, nil]
570
+ new_token(:QUESTION)
232
571
  when input.scan(/\(/)
233
- [:LPAREN, nil]
572
+ new_token(:LPAREN, nil)
234
573
  when input.scan(/\)/)
235
- [:RPAREN, nil]
574
+ new_token(:RPAREN, nil)
236
575
  when input.scan(/{/)
237
- [:LBRACE, nil]
576
+ new_token(:LBRACE, nil)
238
577
  when input.scan(/}/)
239
- [:RBRACE, nil]
578
+ new_token(:RBRACE, nil)
240
579
  when input.scan(/,/)
241
- [:COMMA, nil]
242
- when input.scan(/[A-Z]\w*(::[A-Z]\w*)+/)
243
- [:CONST_PATH, input.matched.to_sym]
244
- when input.scan(/::[A-Z]\w*(::[A-Z]\w*)*/)
245
- [:CONST_PATH, input.matched.to_sym]
580
+ new_token(:COMMA, nil)
581
+ when input.scan(/::/)
582
+ new_token(:COLON2)
246
583
  when input.scan(/:/)
247
- [:COLON, nil]
584
+ new_token(:COLON)
248
585
  when input.scan(/\*\*/)
249
- [:STAR2, nil]
586
+ new_token(:STAR2, :**)
250
587
  when input.scan(/\*/)
251
- [:STAR, nil]
588
+ new_token(:STAR, :*)
252
589
  when input.scan(/\+/)
253
- [:PLUS, nil]
590
+ new_token(:PLUS, :+)
254
591
  when input.scan(/\./)
255
- [:DOT, nil]
592
+ new_token(:DOT)
256
593
  when input.scan(/<:/)
257
- [:LTCOLON, nil]
594
+ new_token(:LTCOLON)
258
595
  when input.scan(/(\[\]=)|(\[\])|===|==|\^|!=|<</)
259
- [:OPERATOR, input.matched.to_sym]
596
+ new_token(:OPERATOR, input.matched.to_sym)
597
+ when input.scan(/<=/)
598
+ new_token(:OPERATOR, :<=)
599
+ when input.scan(/>=/)
600
+ new_token(:OPERATOR, :>=)
260
601
  when input.scan(/</)
261
- [:LT, nil]
602
+ new_token(:LT, :<)
262
603
  when input.scan(/>/)
263
- [:GT, nil]
604
+ new_token(:GT, :>)
605
+ when input.scan(/nil\b/)
606
+ new_token(:NIL, :nil)
264
607
  when input.scan(/any\b/)
265
- [:ANY, nil]
608
+ new_token(:ANY, :any)
609
+ when input.scan(/void\b/)
610
+ new_token(:VOID, :void)
266
611
  when input.scan(/interface\b/)
267
- [:INTERFACE, nil]
612
+ new_token(:INTERFACE, :interface)
268
613
  when input.scan(/end\b/)
269
- [:END, nil]
614
+ new_token(:END, :end)
270
615
  when input.scan(/\|/)
271
- [:BAR, nil]
616
+ new_token(:BAR, :bar)
272
617
  when input.scan(/def\b/)
273
- [:DEF, nil]
618
+ new_token(:DEF)
274
619
  when input.scan(/@type\b/)
275
- [:AT_TYPE, nil]
620
+ new_token(:AT_TYPE)
276
621
  when input.scan(/@implements\b/)
277
- [:AT_IMPLEMENTS, nil]
622
+ new_token(:AT_IMPLEMENTS)
278
623
  when input.scan(/@dynamic\b/)
279
- [:AT_DYNAMIC, nil]
624
+ new_token(:AT_DYNAMIC)
280
625
  when input.scan(/const\b/)
281
- [:CONST, nil]
626
+ new_token(:CONST, :const)
282
627
  when input.scan(/var\b/)
283
- [:VAR, nil]
628
+ new_token(:VAR, :var)
284
629
  when input.scan(/return\b/)
285
- [:RETURN, nil]
630
+ new_token(:RETURN)
286
631
  when input.scan(/block\b/)
287
- [:BLOCK, nil]
632
+ new_token(:BLOCK, :block)
633
+ when input.scan(/break\b/)
634
+ new_token(:BREAK, :break)
288
635
  when input.scan(/method\b/)
289
- [:METHOD, nil]
636
+ new_token(:METHOD, :method)
290
637
  when input.scan(/self\?/)
291
- [:SELFQ, nil]
638
+ new_token(:SELFQ)
292
639
  when input.scan(/self\b/)
293
- [:SELF, nil]
640
+ new_token(:SELF, :self)
294
641
  when input.scan(/'\w+/)
295
- [:TVAR, input.matched.gsub(/\A'/, '').to_sym]
642
+ new_token(:TVAR, input.matched.gsub(/\A'/, '').to_sym)
296
643
  when input.scan(/instance\b/)
297
- [:INSTANCE, nil]
644
+ new_token(:INSTANCE, :instance)
298
645
  when input.scan(/class\b/)
299
- [:CLASS, nil]
646
+ new_token(:CLASS, :class)
300
647
  when input.scan(/module\b/)
301
- [:MODULE, nil]
648
+ new_token(:MODULE, :module)
649
+ when input.scan(/include\?/)
650
+ new_token(:METHOD_NAME, :include?)
302
651
  when input.scan(/include\b/)
303
- [:INCLUDE, nil]
652
+ new_token(:INCLUDE, :include)
304
653
  when input.scan(/extend\b/)
305
- [:EXTEND, nil]
654
+ new_token(:EXTEND, :extend)
306
655
  when input.scan(/instance\b/)
307
- [:INSTANCE, nil]
656
+ new_token(:INSTANCE, :instance)
308
657
  when input.scan(/ivar\b/)
309
- [:IVAR, nil]
658
+ new_token(:IVAR, :ivar)
659
+ when input.scan(/%/)
660
+ new_token(:PERCENT, :%)
661
+ when input.scan(/-/)
662
+ new_token(:MINUS, :-)
663
+ when input.scan(/&/)
664
+ new_token(:OPERATOR, :&)
665
+ when input.scan(/~/)
666
+ new_token(:OPERATOR, :~)
667
+ when input.scan(/\//)
668
+ new_token(:OPERATOR, :/)
669
+ when input.scan(/!/)
670
+ new_token(:OPERATOR, :!)
310
671
  when input.scan(/extension\b/)
311
- [:EXTENSION, nil]
672
+ new_token(:EXTENSION, :extension)
312
673
  when input.scan(/constructor\b/)
313
- [:CONSTRUCTOR, true]
674
+ new_token(:CONSTRUCTOR, true)
314
675
  when input.scan(/noconstructor\b/)
315
- [:NOCONSTRUCTOR, false]
316
- when input.scan(/[A-Z]\w*\.(class|module)\b/)
317
- [:CLASS_IDENT, input.matched.gsub(/\.(class|module)$/, '').to_sym]
318
- when input.scan(/\w+(\!|\?)/)
319
- [:METHOD_NAME, input.matched.to_sym]
676
+ new_token(:NOCONSTRUCTOR, false)
677
+ when input.scan(/\w+(\!|\?|=)/)
678
+ new_token(:METHOD_NAME, input.matched.to_sym)
679
+ when input.scan(/\$\w+\b/)
680
+ new_token(:GVAR, input.matched.to_sym)
320
681
  when input.scan(/[A-Z]\w*/)
321
- [:MODULE_NAME, input.matched.to_sym]
682
+ new_token(:UIDENT, input.matched.to_sym)
322
683
  when input.scan(/_\w+/)
323
- [:INTERFACE_NAME, input.matched.to_sym]
324
- when input.scan(/@[\w_]+/)
325
- [:IVAR_NAME, input.matched.to_sym]
684
+ new_token(:INTERFACE_NAME, input.matched.to_sym)
685
+ when input.scan(/@\w+/)
686
+ new_token(:IVAR_NAME, input.matched.to_sym)
326
687
  when input.scan(/\w+/)
327
- [:IDENT, input.matched.to_sym]
688
+ new_token(:IDENT, input.matched.to_sym)
328
689
  end
329
690
  end