typeprof 0.21.11 → 0.30.1

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 (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +178 -0
  7. data/lib/typeprof/cli.rb +3 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +259 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +433 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +339 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +366 -0
  31. data/lib/typeprof/core/graph/box.rb +998 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +225 -0
  35. data/lib/typeprof/core/service.rb +514 -0
  36. data/lib/typeprof/core/type.rb +352 -0
  37. data/lib/typeprof/core/util.rb +81 -0
  38. data/lib/typeprof/core.rb +31 -0
  39. data/lib/typeprof/diagnostic.rb +35 -0
  40. data/lib/typeprof/lsp/messages.rb +415 -0
  41. data/lib/typeprof/lsp/server.rb +203 -0
  42. data/lib/typeprof/lsp/text.rb +69 -0
  43. data/lib/typeprof/lsp/util.rb +51 -0
  44. data/lib/typeprof/lsp.rb +4 -907
  45. data/lib/typeprof/version.rb +1 -1
  46. data/lib/typeprof.rb +4 -18
  47. data/typeprof.gemspec +5 -7
  48. metadata +47 -33
  49. data/.github/dependabot.yml +0 -6
  50. data/.github/workflows/main.yml +0 -39
  51. data/.gitignore +0 -9
  52. data/Gemfile +0 -17
  53. data/Gemfile.lock +0 -41
  54. data/Rakefile +0 -10
  55. data/exe/typeprof +0 -10
  56. data/lib/typeprof/analyzer.rb +0 -2598
  57. data/lib/typeprof/arguments.rb +0 -414
  58. data/lib/typeprof/block.rb +0 -176
  59. data/lib/typeprof/builtin.rb +0 -893
  60. data/lib/typeprof/code-range.rb +0 -177
  61. data/lib/typeprof/config.rb +0 -158
  62. data/lib/typeprof/container-type.rb +0 -912
  63. data/lib/typeprof/export.rb +0 -589
  64. data/lib/typeprof/import.rb +0 -852
  65. data/lib/typeprof/insns-def.rb +0 -65
  66. data/lib/typeprof/iseq.rb +0 -864
  67. data/lib/typeprof/method.rb +0 -355
  68. data/lib/typeprof/type.rb +0 -1140
  69. data/lib/typeprof/utils.rb +0 -212
  70. data/tools/coverage.rb +0 -14
  71. data/tools/setup-insns-def.rb +0 -30
  72. data/typeprof-lsp +0 -3
@@ -0,0 +1,339 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ def self.get_rbs_comment_before(raw_node, lenv)
4
+ comments = Fiber[:comments]
5
+ i = comments.bsearch_index {|comment| comment.location.start_line >= raw_node.location.start_line } || comments.size
6
+ lineno = raw_node.location.start_line
7
+ rbs_comments = []
8
+ while i > 0
9
+ i -= 1
10
+ lineno -= 1
11
+ comment = comments[i]
12
+ comment_loc = comment.location
13
+ comment_text = comment_loc.slice
14
+ if comment_loc.start_line == lineno && comment_text.start_with?("#:")
15
+ rbs_comments[comment_loc.start_line] = " " * (comment_loc.start_column + 2) + comment_text[2..]
16
+ else
17
+ break
18
+ end
19
+ end
20
+ return nil if rbs_comments.empty?
21
+ rbs_comments = rbs_comments.map {|line| line || "" }.join("\n")
22
+ method_type = RBS::Parser.parse_method_type(rbs_comments)
23
+ if method_type
24
+ AST.create_rbs_func_type(method_type, method_type.type_params, method_type.block, lenv)
25
+ else
26
+ nil
27
+ end
28
+ rescue RBS::ParsingError
29
+ # TODO: report the error
30
+ nil
31
+ end
32
+
33
+ def self.parse_params(tbl, raw_args, lenv)
34
+ unless raw_args
35
+ return {
36
+ req_positionals: [],
37
+ opt_positionals: [],
38
+ opt_positional_defaults: [],
39
+ rest_positionals: nil,
40
+ post_positionals: [],
41
+ req_keywords: [],
42
+ opt_keywords: [],
43
+ opt_keyword_defaults: [],
44
+ rest_keywords: nil,
45
+ block: nil,
46
+ }
47
+ end
48
+
49
+ args_code_ranges = []
50
+ req_positionals = []
51
+ raw_args.requireds.each do |n|
52
+ args_code_ranges << TypeProf::CodeRange.from_node(n.location)
53
+ req_positionals << (n.is_a?(Prism::MultiTargetNode) ? nil : n.name)
54
+ end
55
+
56
+ # pre_init = args[1]
57
+
58
+ opt_positionals = []
59
+ opt_positional_defaults = []
60
+ raw_args.optionals.each do |n|
61
+ opt_positionals << n.name
62
+ opt_positional_defaults << AST.create_node(n.value, lenv)
63
+ end
64
+
65
+ post_positionals = raw_args.posts.map {|n| (n.is_a?(Prism::MultiTargetNode) ? nil : n.name) }
66
+
67
+ rest_positionals = raw_args.rest&.name
68
+
69
+ req_keywords = []
70
+ opt_keywords = []
71
+ opt_keyword_defaults = []
72
+
73
+ raw_args.keywords.each do |kw|
74
+ case kw.type
75
+ when :required_keyword_parameter_node
76
+ req_keywords << kw.name
77
+ when :optional_keyword_parameter_node
78
+ opt_keywords << kw.name
79
+ opt_keyword_defaults << AST.create_node(kw.value, lenv)
80
+ end
81
+ end
82
+
83
+ case raw_args.keyword_rest
84
+ when Prism::KeywordRestParameterNode
85
+ rest_keywords = raw_args.keyword_rest.name if raw_args.keyword_rest
86
+ when Prism::NoKeywordsParameterNode
87
+ # what to do?
88
+ when nil
89
+ # nothing to do
90
+ else
91
+ raise "unexpected keyword rest: #{ raw_args.keyword_rest.class }"
92
+ end
93
+
94
+ block = raw_args.block.name if raw_args.block
95
+
96
+ {
97
+ req_positionals:,
98
+ opt_positionals:,
99
+ opt_positional_defaults:,
100
+ rest_positionals:,
101
+ post_positionals:,
102
+ req_keywords:,
103
+ opt_keywords:,
104
+ opt_keyword_defaults:,
105
+ rest_keywords:,
106
+ block:,
107
+ args_code_ranges:
108
+ }
109
+ end
110
+
111
+ class DefNode < Node
112
+ def initialize(raw_node, lenv, use_result)
113
+ super(raw_node, lenv)
114
+ # TODO: warn "def self.foo" in a metaclass
115
+ singleton = !!raw_node.receiver || lenv.cref.scope_level == :metaclass
116
+ mid = raw_node.name
117
+ mid_code_range = TypeProf::CodeRange.from_node(raw_node.name_loc)
118
+ @tbl = raw_node.locals
119
+ raw_args = raw_node.parameters
120
+ raw_body = raw_node.body
121
+
122
+ @rbs_method_type = AST.get_rbs_comment_before(raw_node, lenv)
123
+
124
+ @singleton = singleton
125
+ @mid = mid
126
+ @mid_code_range = mid_code_range
127
+
128
+ ncref = CRef.new(lenv.cref.cpath, @singleton ? :class : :instance, @mid, lenv.cref)
129
+ nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
130
+ if raw_body
131
+ @body = AST.create_node(raw_body, nlenv)
132
+ else
133
+ pos = code_range.last.left.left.left # before "end"
134
+ cr = TypeProf::CodeRange.new(pos, pos)
135
+ @body = DummyNilNode.new(cr, nlenv)
136
+ end
137
+
138
+ h = AST.parse_params(@tbl, raw_args, nlenv)
139
+ @req_positionals = h[:req_positionals]
140
+ @opt_positionals = h[:opt_positionals]
141
+ @opt_positional_defaults = h[:opt_positional_defaults]
142
+ @rest_positionals = h[:rest_positionals]
143
+ @post_positionals = h[:post_positionals]
144
+ @req_keywords = h[:req_keywords]
145
+ @opt_keywords = h[:opt_keywords]
146
+ @opt_keyword_defaults = h[:opt_keyword_defaults]
147
+ @rest_keywords = h[:rest_keywords]
148
+ @block = h[:block]
149
+ @args_code_ranges = h[:args_code_ranges] || []
150
+
151
+ # If the result of `def` statement, stop reusing this node
152
+ # TODO: `private def ...` should be handled well
153
+ @reusable = !use_result
154
+ end
155
+
156
+ attr_reader :singleton, :mid, :mid_code_range
157
+ attr_reader :tbl
158
+ attr_reader :req_positionals
159
+ attr_reader :opt_positionals
160
+ attr_reader :opt_positional_defaults
161
+ attr_reader :rest_positionals
162
+ attr_reader :post_positionals
163
+ attr_reader :req_keywords
164
+ attr_reader :opt_keywords
165
+ attr_reader :opt_keyword_defaults
166
+ attr_reader :rest_keywords
167
+ attr_reader :block
168
+ attr_reader :body
169
+ attr_reader :rbs_method_type
170
+ attr_reader :reusable
171
+
172
+ def subnodes = {
173
+ body:,
174
+ opt_positional_defaults:,
175
+ opt_keyword_defaults:,
176
+ rbs_method_type:,
177
+ }
178
+ def attrs = {
179
+ singleton:,
180
+ mid:,
181
+ mid_code_range:,
182
+ tbl:,
183
+ req_positionals:,
184
+ opt_positionals:,
185
+ rest_positionals:,
186
+ post_positionals:,
187
+ req_keywords:,
188
+ opt_keywords:,
189
+ rest_keywords:,
190
+ block:,
191
+ reusable:,
192
+ }
193
+
194
+ def mname_code_range(_name) = @mid_code_range
195
+
196
+ def define(genv) # NOT define0
197
+ return define_copy(genv) if @prev_node && @reusable
198
+ super(genv)
199
+ end
200
+
201
+ def install(genv) # NOT install0
202
+ return install_copy(genv) if @prev_node && @reusable
203
+ super(genv)
204
+ end
205
+
206
+ def install0(genv)
207
+ if @rbs_method_type
208
+ @changes.add_method_decl_box(genv, @lenv.cref.cpath, @singleton, @mid, [@rbs_method_type], false)
209
+ end
210
+
211
+ @tbl.each {|var| @body.lenv.locals[var] = Source.new(genv.nil_type) }
212
+ @body.lenv.locals[:"*self"] = @body.lenv.cref.get_self(genv)
213
+
214
+ req_positionals = @req_positionals.map {|var| @body.lenv.new_var(var, self) }
215
+ opt_positionals = @opt_positionals.map {|var| @body.lenv.new_var(var, self) }
216
+ rest_positionals = @rest_positionals ? @body.lenv.new_var(@rest_positionals, self) : nil
217
+ post_positionals = @post_positionals.map {|var| @body.lenv.new_var(var, self) }
218
+ req_keywords = @req_keywords.map {|var| @body.lenv.new_var(var, self) }
219
+ opt_keywords = @opt_keywords.map {|var| @body.lenv.new_var(var, self) }
220
+ rest_keywords = @rest_keywords ? @body.lenv.new_var(@rest_keywords, self) : nil
221
+ block = @block ? @body.lenv.new_var(@block, self) : nil
222
+
223
+ if rest_positionals
224
+ @changes.add_edge(genv, Source.new(genv.gen_ary_type(Vertex.new(self))), rest_positionals)
225
+ end
226
+
227
+ @opt_positional_defaults.zip(opt_positionals) do |expr, vtx|
228
+ @changes.add_edge(genv, expr.install(genv), vtx)
229
+ end
230
+ @opt_keyword_defaults.zip(opt_keywords) do |expr, vtx|
231
+ @changes.add_edge(genv, expr.install(genv), vtx)
232
+ end
233
+
234
+ if block
235
+ block = @body.lenv.set_var(:"*given_block", block)
236
+ else
237
+ block = @body.lenv.new_var(:"*given_block", self)
238
+ end
239
+
240
+ if @body
241
+ e_ret = @body.lenv.locals[:"*expected_method_ret"] = Vertex.new(self)
242
+ @body.install(genv)
243
+ @body.lenv.add_return_box(@changes.add_escape_box(genv, @body.ret, e_ret))
244
+ end
245
+
246
+ f_args = FormalArguments.new(
247
+ req_positionals,
248
+ opt_positionals,
249
+ rest_positionals,
250
+ post_positionals,
251
+ req_keywords,
252
+ opt_keywords,
253
+ rest_keywords,
254
+ block,
255
+ )
256
+
257
+ @changes.add_method_def_box(genv, @lenv.cref.cpath, @singleton, @mid, f_args, @body.lenv.return_boxes)
258
+
259
+ Source.new(Type::Symbol.new(genv, @mid))
260
+ end
261
+
262
+ def last_stmt_code_range
263
+ if @body
264
+ if @body.is_a?(AST::StatementsNode)
265
+ @body.stmts.last.code_range
266
+ else
267
+ @body.code_range
268
+ end
269
+ else
270
+ nil
271
+ end
272
+ end
273
+
274
+ def retrieve_at(pos, &blk)
275
+ if @rbs_method_type
276
+ if @rbs_method_type.code_range.include?(pos) # annotation
277
+ @rbs_method_type.retrieve_at(pos, &blk)
278
+ end
279
+ end
280
+ @args_code_ranges.each_with_index do |cr, i|
281
+ if cr.include?(pos)
282
+ yield DummySymbolNode.new(@tbl[i], cr, @body.lenv.get_var(@tbl[i]))
283
+ break
284
+ end
285
+ end
286
+ super(pos, &blk)
287
+ end
288
+
289
+ def modified_vars(tbl, vars)
290
+ # skip
291
+ end
292
+ end
293
+
294
+ class AliasNode < Node
295
+ def initialize(raw_node, lenv)
296
+ super(raw_node, lenv)
297
+ @new_mid = AST.create_node(raw_node.new_name, lenv)
298
+ @old_mid = AST.create_node(raw_node.old_name, lenv)
299
+ end
300
+
301
+ attr_reader :new_mid, :old_mid
302
+
303
+ def subnodes = { new_mid:, old_mid: }
304
+
305
+ def install0(genv)
306
+ @new_mid.install(genv)
307
+ @old_mid.install(genv)
308
+ if @new_mid.is_a?(SymbolNode) && @old_mid.is_a?(SymbolNode)
309
+ new_mid = @new_mid.lit
310
+ old_mid = @old_mid.lit
311
+ box = @changes.add_method_alias_box(genv, @lenv.cref.cpath, false, new_mid, old_mid)
312
+ box.ret
313
+ else
314
+ Source.new(genv.nil_type)
315
+ end
316
+ end
317
+ end
318
+
319
+ class UndefNode < Node
320
+ def initialize(raw_node, lenv)
321
+ super(raw_node, lenv)
322
+ @names = raw_node.names.map do |raw_name|
323
+ AST.create_node(raw_name, lenv)
324
+ end
325
+ end
326
+
327
+ attr_reader :names
328
+
329
+ def subnodes = { names: }
330
+
331
+ def install0(genv)
332
+ @names.each do |name|
333
+ name.install(genv)
334
+ end
335
+ Source.new(genv.nil_type)
336
+ end
337
+ end
338
+ end
339
+ end
@@ -0,0 +1,263 @@
1
+ module TypeProf::Core
2
+ class AST
3
+ class StatementsNode < Node
4
+ def initialize(raw_node, lenv, use_result)
5
+ super(raw_node, lenv)
6
+ stmts = raw_node.body
7
+ @stmts = stmts.map.with_index do |n, i|
8
+ if n
9
+ AST.create_node(n, lenv, i == stmts.length - 1 ? use_result : false)
10
+ else
11
+ last = code_range.last
12
+ DummyNilNode.new(TypeProf::CodeRange.new(last, last), lenv)
13
+ end
14
+ end
15
+ end
16
+
17
+ attr_reader :stmts
18
+
19
+ def subnodes = { stmts: }
20
+
21
+ def install0(genv)
22
+ ret = nil
23
+ @stmts.each do |stmt|
24
+ ret = stmt ? stmt.install(genv) : nil
25
+ end
26
+ if ret
27
+ ret2 = Vertex.new(self)
28
+ @changes.add_edge(genv, ret, ret2)
29
+ ret2
30
+ else
31
+ Source.new(genv.nil_type)
32
+ end
33
+ end
34
+
35
+ def diff(prev_node)
36
+ if prev_node.is_a?(StatementsNode)
37
+ i = 0
38
+ while i < @stmts.size
39
+ @stmts[i].diff(prev_node.stmts[i])
40
+ if !@stmts[i].prev_node
41
+ j1 = @stmts.size - 1
42
+ j2 = prev_node.stmts.size - 1
43
+ while j1 >= i && j2 >= i
44
+ @stmts[j1].diff(prev_node.stmts[j2])
45
+ if !@stmts[j1].prev_node
46
+ return
47
+ end
48
+ j1 -= 1
49
+ j2 -= 1
50
+ end
51
+ return
52
+ end
53
+ i += 1
54
+ end
55
+ @prev_node = prev_node if i == prev_node.stmts.size
56
+ end
57
+ end
58
+ end
59
+
60
+ class MultiWriteNode < Node
61
+ def initialize(raw_node, lenv)
62
+ super(raw_node, lenv)
63
+ @value = AST.create_node(raw_node.value, lenv)
64
+ @lefts = raw_node.lefts.map do |raw_lhs|
65
+ AST.create_target_node(raw_lhs, lenv)
66
+ end
67
+ if raw_node.rest
68
+ # TODO: need more complex case handling
69
+ @rest_exist = true
70
+ case raw_node.rest.type
71
+ when :splat_node
72
+ if raw_node.rest.expression
73
+ @rest = AST.create_target_node(raw_node.rest.expression, lenv)
74
+ end
75
+ when :implicit_rest_node
76
+ else
77
+ raise "unexpected rest node: #{raw_node.rest.type}"
78
+ end
79
+ end
80
+ @rights = raw_node.rights.map do |raw_lhs|
81
+ AST.create_target_node(raw_lhs, lenv)
82
+ end
83
+ # TODO: raw_node.rest, raw_node.rights
84
+ end
85
+
86
+ attr_reader :value, :lefts, :rest, :rest_exist, :rights
87
+
88
+ def subnodes = { value:, lefts:, rest:, rights: }
89
+ def attrs = { rest_exist: }
90
+
91
+ def install0(genv)
92
+ value = @value.install(genv)
93
+
94
+ @lefts.each {|lhs| lhs.install(genv) }
95
+ @lefts.each {|lhs| lhs.rhs.ret || raise(lhs.rhs.inspect) }
96
+ lefts = @lefts.map {|lhs| lhs.rhs.ret }
97
+
98
+ if @rest_exist
99
+ rest_elem = Vertex.new(self)
100
+ if @rest
101
+ @rest.install(genv)
102
+ @rest.rhs.ret || raise(@rest.rhs.inspect)
103
+ @changes.add_edge(genv, Source.new(Type::Instance.new(genv, genv.mod_ary, [rest_elem])), @rest.rhs.ret)
104
+ end
105
+ end
106
+
107
+ if @rights
108
+ @rights.each {|lhs| lhs.install(genv) }
109
+ @rights.each {|lhs| lhs.rhs.ret || raise(lhs.rhs.inspect) }
110
+ rights = @rights.map {|rhs| rhs.ret }
111
+ end
112
+
113
+ box = @changes.add_masgn_box(genv, value, lefts, rest_elem, rights)
114
+ box.ret
115
+ end
116
+
117
+ def retrieve_at(pos, &blk)
118
+ yield self if @var_code_range && @var_code_range.include?(pos)
119
+ super(pos, &blk)
120
+ end
121
+ end
122
+
123
+ class MatchWriteNode < Node
124
+ def initialize(raw_node, lenv)
125
+ super(raw_node, lenv)
126
+ @call = AST.create_node(raw_node.call, lenv)
127
+ @targets = raw_node.targets.map do |raw_lhs|
128
+ AST.create_target_node(raw_lhs, lenv)
129
+ end
130
+ end
131
+
132
+ attr_reader :call, :targets
133
+ def subnodes = { call:, targets: }
134
+
135
+ def install0(genv)
136
+ ret = @call.install(genv)
137
+ @targets.each do |target|
138
+ target.install(genv)
139
+ target.rhs.ret || raise(target.rhs.inspect)
140
+ @changes.add_edge(genv, Source.new(Type::Instance.new(genv, genv.mod_str, [])), target.rhs.ret)
141
+ end
142
+ ret
143
+ end
144
+ end
145
+
146
+ class DefinedNode < Node
147
+ def initialize(raw_node, lenv)
148
+ super(raw_node, lenv)
149
+ @arg = AST.create_node(raw_node.value, lenv)
150
+ end
151
+
152
+ attr_reader :arg
153
+
154
+ def subnodes = {} # no arg!
155
+
156
+ def install0(genv)
157
+ Source.new(genv.true_type, genv.false_type)
158
+ end
159
+ end
160
+
161
+ class SourceEncodingNode < Node
162
+ def install0(genv)
163
+ Source.new(Type::Instance.new(genv, genv.resolve_cpath([:Encoding]), []))
164
+ end
165
+ end
166
+
167
+ class SplatNode < Node
168
+ def initialize(raw_node, lenv)
169
+ super(raw_node, lenv)
170
+ @expr = AST.create_node(raw_node.expression, lenv)
171
+ end
172
+
173
+ attr_reader :expr
174
+
175
+ def subnodes = { expr: }
176
+
177
+ def mid_code_range = nil
178
+
179
+ def install0(genv)
180
+ vtx = @expr.install(genv)
181
+
182
+ a_args = ActualArguments.new([], [], nil, nil)
183
+ vtx = @changes.add_method_call_box(genv, vtx, :to_a, a_args, false).ret
184
+
185
+ @changes.add_splat_box(genv, vtx).ret
186
+ end
187
+ end
188
+
189
+ class ForNode < Node
190
+ def initialize(raw_node, lenv)
191
+ super(raw_node, lenv)
192
+ # XXX: tentative implementation
193
+ # raw_node.index
194
+ @expr = AST.create_node(raw_node.collection, lenv)
195
+ @body = raw_node.statements ? AST.create_node(raw_node.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.new(code_range.last, code_range.last), lenv)
196
+ end
197
+
198
+ attr_reader :expr, :body
199
+
200
+ def subnodes = { expr:, body: }
201
+
202
+ def install0(genv)
203
+ @expr.install(genv)
204
+ @body.install(genv)
205
+ Source.new(genv.nil_type)
206
+ end
207
+ end
208
+
209
+ class FlipFlopNode < Node
210
+ def initialize(raw_node, lenv)
211
+ super(raw_node, lenv)
212
+ @e1 = AST.create_node(raw_node.left, lenv)
213
+ @e2 = AST.create_node(raw_node.right, lenv)
214
+ end
215
+
216
+ attr_reader :e1, :e2
217
+
218
+ def subnodes = { e1:, e2: }
219
+
220
+ def install0(genv)
221
+ @e1.install(genv)
222
+ @e2.install(genv)
223
+ Source.new(genv.true_type, genv.false_type)
224
+ end
225
+ end
226
+
227
+ class MatchRequiredNode < Node
228
+ def initialize(raw_node, lenv)
229
+ super(raw_node, lenv)
230
+ @value = AST.create_node(raw_node.value, lenv)
231
+ @pat = AST.create_pattern_node(raw_node.pattern, lenv)
232
+ end
233
+
234
+ attr_reader :value, :pat
235
+
236
+ def subnodes = { value:, pat: }
237
+
238
+ def install0(genv)
239
+ @value.install(genv)
240
+ @pat.install(genv)
241
+ Source.new(genv.nil_type)
242
+ end
243
+ end
244
+
245
+ class MatchPreidcateNode < Node
246
+ def initialize(raw_node, lenv)
247
+ super(raw_node, lenv)
248
+ @value = AST.create_node(raw_node.value, lenv)
249
+ @pat = AST.create_pattern_node(raw_node.pattern, lenv)
250
+ end
251
+
252
+ attr_reader :value, :pat
253
+
254
+ def subnodes = { value:, pat: }
255
+
256
+ def install0(genv)
257
+ @value.install(genv)
258
+ @pat.install(genv)
259
+ Source.new(genv.true_type, genv.false_type)
260
+ end
261
+ end
262
+ end
263
+ end