yadriggy 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,159 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ require 'yadriggy/eval'
4
+
5
+ module Yadriggy
6
+
7
+ # A simple visitor.
8
+ #
9
+ class EvalAll < Eval
10
+ def nil_value(expr) end
11
+
12
+ def name(expr) end
13
+
14
+ def symbol(expr) end
15
+
16
+ def super_method(expr) end
17
+
18
+ def number(expr) end
19
+
20
+ # expressions, or progn in Lisp.
21
+ #
22
+ def exprs(expr)
23
+ expr.expressions.each {|e| evaluate(e) }
24
+ end
25
+
26
+ def paren(expr)
27
+ evaluate(expr.expression)
28
+ end
29
+
30
+ def array(expr)
31
+ expr.elements.each {|e| evaluate(e) }
32
+ end
33
+
34
+ def string_interpolation(expr)
35
+ expr.contents.each {|e| evaluate(e) }
36
+ end
37
+
38
+ def string_literal(expr) end
39
+
40
+ def const_path_ref(expr)
41
+ evaluate(expr.scope)
42
+ evaluate(expr.name)
43
+ end
44
+
45
+ def unary(expr)
46
+ evaluate(expr.expr)
47
+ end
48
+
49
+ def binary(expr)
50
+ evaluate(expr.left)
51
+ evaluate(expr.right)
52
+ end
53
+
54
+ def hash(expr)
55
+ expr.pairs.each {|p| p.each {|e| evaluate(e) }}
56
+ end
57
+
58
+ def call(expr)
59
+ evaluate(expr.receiver)
60
+ expr.args.each {|e| evaluate(e) }
61
+ evaluate(expr.block_arg)
62
+ evaluate(expr.block)
63
+ end
64
+
65
+ def array_ref(expr)
66
+ evaluate(expr.array)
67
+ expr.indexes.each {|e| evaluate(e) }
68
+ end
69
+
70
+ def conditional(expr)
71
+ evaluate(expr.cond)
72
+ evaluate(expr.then)
73
+ expr.all_elsif.each do |e|
74
+ evaluate(e[0]) # condition
75
+ evaluate(e[1]) # elsif body
76
+ end
77
+ evaluate(expr.else) unless expr.else.nil?
78
+ end
79
+
80
+ def loop(expr)
81
+ evaluate(expr.cond)
82
+ evaluate(expr.body)
83
+ end
84
+
85
+ def for_loop(expr)
86
+ evaluate(expr.set)
87
+ evaluate(expr.body)
88
+ end
89
+
90
+ def break_out(expr)
91
+ expr.values.each {|e| evaluate(e) }
92
+ end
93
+
94
+ def return_values(expr)
95
+ expr.values.each {|e| evaluate(e) }
96
+ end
97
+
98
+ def block(expr)
99
+ parameters(expr)
100
+ evaluate(expr.body)
101
+ end
102
+
103
+ def begin_end(expr)
104
+ evaluate(expr.body)
105
+ evaluate(expr.rescue)
106
+ end
107
+
108
+ # def
109
+ #
110
+ def define(expr)
111
+ evaluate(expr.singular)
112
+ evaluate(expr.name)
113
+ parameters(expr)
114
+ evaluate(expr.body)
115
+ evaluate(expr.rescue)
116
+ end
117
+
118
+ def rescue_end(expr)
119
+ evaluate(expr.body)
120
+ evaluate(expr.nested_rescue)
121
+ evaluate(expr.else)
122
+ evaluate(expr.ensure)
123
+ end
124
+
125
+ def module_def(expr)
126
+ evaluate(expr.name)
127
+ evaluate(expr.body)
128
+ evaluate(expr.rescue)
129
+ end
130
+
131
+ def class_def(expr)
132
+ evaluate(expr.name)
133
+ evaluate(expr.superclass)
134
+ evaluate(expr.body)
135
+ evaluate(expr.rescue)
136
+ end
137
+
138
+ def singular_class_def(expr)
139
+ evaluate(expr.name)
140
+ evaluate(expr.body)
141
+ evaluate(expr.rescue)
142
+ end
143
+
144
+ def program(expr)
145
+ evaluate(expr.elements)
146
+ end
147
+
148
+ private
149
+ def parameters(expr)
150
+ expr.params.each {|e| evaluate(e) }
151
+ expr.optionals.each {|p| p.each {|e| evaluate(e) }}
152
+ evaluate(expr.rest_of_params)
153
+ expr.params_after_rest.each {|e| evaluate(e) }
154
+ expr.keywords.each {|e| evaluate(e[0]); evaluate(e[1]) }
155
+ evaluate(expr.rest_of_keywords)
156
+ evaluate(expr.block_param)
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,492 @@
1
+ # Copyright (C) 2017- Shigeru Chiba. All rights reserved.
2
+
3
+ require 'yadriggy/typecheck'
4
+ require 'yadriggy/printer'
5
+
6
+ module Yadriggy
7
+ # Pretty printer for Ruby
8
+ class PrettyPrinter < Checker
9
+ # Obtains the string representation of the given AST.
10
+ #
11
+ # @param [ASTree|ASTnode] an_ast the AST.
12
+ # @return [String] the string representation of the AST.
13
+ def self.ast_to_s(an_ast)
14
+ pp = PrettyPrinter.new(Printer.new)
15
+ pp.print(an_ast).printer.output
16
+ end
17
+
18
+ # @return [Printer] a {Printer} object.
19
+ attr_reader :printer
20
+
21
+ # @param [Printer] printer
22
+ def initialize(printer)
23
+ super()
24
+ @printer = printer
25
+ end
26
+
27
+ # Prints a given AST by {#printer}.
28
+ # @param [ASTree|ASTnode] an_ast the AST.
29
+ # @return [PrettyPrinter] the `self` object.
30
+ def print(an_ast)
31
+ check_all(an_ast)
32
+ self
33
+ end
34
+
35
+ rule(Assign) do
36
+ print(ast.left)
37
+ @printer << ' ' << ast.op << ' '
38
+ print(ast.right)
39
+ end
40
+
41
+ rule(Name) do
42
+ @printer << ast.name
43
+ end
44
+
45
+ rule(Label) do
46
+ @printer << ast.name << ':'
47
+ end
48
+
49
+ rule(Super) do
50
+ @printer << 'super'
51
+ end
52
+
53
+ rule(Number) do
54
+ @printer << ast.value.to_s
55
+ end
56
+
57
+ rule(SymbolLiteral) do
58
+ @printer << ":'" << ast.name << "'"
59
+ end
60
+
61
+ rule(Exprs) do
62
+ ast.expressions.each do |e|
63
+ print(e)
64
+ @printer.nl
65
+ end
66
+ end
67
+
68
+ rule(Paren) do
69
+ @printer << '('
70
+ print(ast.expression)
71
+ @printer << ')'
72
+ end
73
+
74
+ rule(ArrayLiteral) do
75
+ @printer << '['
76
+ print_each(ast.elements, true)
77
+ @printer << ']'
78
+ end
79
+
80
+ rule(StringInterpolation) do
81
+ @printer << '"'
82
+ ast.contents.each do |c|
83
+ if c.is_a?(StringLiteral)
84
+ @printer << c.value.dump[1..-2]
85
+ else
86
+ @printer << '#{'
87
+ print(c)
88
+ @printer << '}'
89
+ end
90
+ end
91
+ @printer << '"'
92
+ end
93
+
94
+ rule(StringLiteral) do
95
+ @printer << ast.value.dump
96
+ end
97
+
98
+ rule(ConstPathRef) do
99
+ print(ast.scope)
100
+ @printer << '::'
101
+ print(ast.name)
102
+ end
103
+
104
+ rule(Unary) do
105
+ @printer << ast.real_operator
106
+ print(ast.expr)
107
+ end
108
+
109
+ rule(Binary) do
110
+ print(ast.left)
111
+ @printer << ' ' << ast.op << ' '
112
+ print(ast.right)
113
+ end
114
+
115
+ rule(Dots) do
116
+ print(ast.left)
117
+ @printer << ast.op
118
+ print(ast.right)
119
+ end
120
+
121
+ rule(HashLiteral) do
122
+ @printer << '{'
123
+ print_hash_elements(ast)
124
+ @printer << '}'
125
+ end
126
+
127
+ def print_hash_elements(hash_ast)
128
+ print_list(hash_ast.pairs, true) do |pair|
129
+ print(pair[0])
130
+ @printer << ' '
131
+ @printer << '=> ' unless pair[0].is_a?(Label)
132
+ print(pair[1])
133
+ end
134
+ end
135
+
136
+ rule(Call) do
137
+ is_cmd = ast.is_a?(Command)
138
+ print(ast.receiver) if ast.receiver
139
+ @printer << ast.op if ast.op
140
+ @printer << ast.name.name
141
+ print_arguments(ast.args, ast.block_arg, ast.block, is_cmd)
142
+ end
143
+
144
+ # Prints an argument list.
145
+ #
146
+ # @param [Array<ASTnode>] args_ast an argument list.
147
+ # @param [ASTnode] block_arg a block argument.
148
+ # @param [ASTnode] block a block.
149
+ # @param [Boolean] is_cmd true if opening/closing parentheses are not written
150
+ # (true if the arguments are for a command).
151
+ # @param [Boolean] no_empty_paren true if `()` is not printed when an argument list is empty.
152
+ # @return [void]
153
+ def print_arguments(args_ast, block_arg, block, is_cmd, no_empty_paren=true)
154
+ if is_cmd
155
+ @printer << ' '
156
+ else
157
+ @printer << '(' unless no_empty_paren && args_ast.empty?
158
+ end
159
+
160
+ is_first = print_list(args_ast, true) do |a|
161
+ if a.is_a?(HashLiteral) && args_ast.last == a
162
+ print_hash_elements(a)
163
+ else
164
+ print(a)
165
+ end
166
+ end
167
+
168
+ if block_arg
169
+ @printer << ', ' unless is_first
170
+ @printer << '&'
171
+ print(block_arg)
172
+ end
173
+ unless is_cmd
174
+ @printer << ')' unless no_empty_paren && args_ast.empty?
175
+ end
176
+ if block
177
+ @printer << ' '
178
+ print(block)
179
+ end
180
+ end
181
+
182
+ rule(ArrayRef) do
183
+ print(ast.array)
184
+ @printer << '['
185
+ print_each(ast.indexes, true)
186
+ @printer << ']'
187
+ end
188
+
189
+ rule(Conditional) do
190
+ case ast.op
191
+ when :if, :unless
192
+ @printer << ast.op << ' '
193
+ print(ast.cond)
194
+ @printer.down
195
+ print(ast.then)
196
+ @printer.up
197
+ ast.all_elsif.each do | expr |
198
+ @printer << 'elsif '
199
+ print(expr[0])
200
+ @printer.down
201
+ print(expr[1])
202
+ @printer.up
203
+ end
204
+ if ast.else
205
+ @printer << 'else'
206
+ @printer.down
207
+ print(ast.else)
208
+ @printer.up
209
+ end
210
+ @printer << 'end' << :nl
211
+ when :if_mod, :unless_mod
212
+ print(ast.then)
213
+ @printer << (ast.op == :if_mod ? ' if ' : ' unless ')
214
+ print(ast.cond)
215
+ else # :ifop
216
+ print(ast.cond)
217
+ @printer << ' ? '
218
+ print(ast.then)
219
+ @printer << ' : '
220
+ print(ast.else)
221
+ end
222
+ end
223
+
224
+ rule(Loop) do
225
+ case ast.op
226
+ when :while, :until
227
+ @printer << ast.op << ' '
228
+ print(ast.cond)
229
+ @printer.down
230
+ print(ast.body)
231
+ @printer.up
232
+ @printer << 'end'
233
+ else # :while_mod, :until_mod
234
+ print(ast.body)
235
+ @printer << ' ' << ast.real_operator << ' '
236
+ print(ast.cond)
237
+ end
238
+ end
239
+
240
+ rule(ForLoop) do
241
+ @printer << 'for '
242
+ print_each(ast.vars, true)
243
+ @printer << ' in '
244
+ print(ast.set)
245
+ @printer.down
246
+ print(ast.body)
247
+ @printer.up
248
+ @printer << 'end'
249
+ end
250
+
251
+ rule(Break) do
252
+ @printer << ast.op
253
+ first = true
254
+ ast.values.each do |v|
255
+ if first
256
+ @printer << ' '
257
+ first = false
258
+ else
259
+ @printer << ', '
260
+ end
261
+ print(v)
262
+ end
263
+ end
264
+
265
+ rule(Return) do
266
+ @printer << 'return'
267
+ first = true
268
+ ast.values.each do |v|
269
+ if first
270
+ @printer << ' '
271
+ first = false
272
+ else
273
+ @printer << ', '
274
+ end
275
+ print(v)
276
+ end
277
+ end
278
+
279
+ # @private
280
+ def print_parameters(params_ast)
281
+ is_first = true
282
+ is_first = print_each(params_ast.params, is_first)
283
+
284
+ is_first = print_list(params_ast.optionals, is_first) do |p|
285
+ print(p[0])
286
+ @printer << '='
287
+ print(p[1])
288
+ end
289
+
290
+ is_first = print_list([params_ast.rest_of_params], is_first) do |p|
291
+ @printer << '*'
292
+ print(p)
293
+ end
294
+
295
+ is_first = print_each(params_ast.params_after_rest, is_first)
296
+
297
+ is_first = print_list(params_ast.keywords, is_first) do |kv|
298
+ print(kv[0])
299
+ @printer << ': '
300
+ print(kv[1])
301
+ end
302
+
303
+ is_first = print_list([params_ast.rest_of_keywords], is_first) do |p|
304
+ @printer << '**'
305
+ print(p)
306
+ end
307
+
308
+ is_first = print_list([params_ast.block_param], is_first) do |p|
309
+ @printer << '&'
310
+ print(p)
311
+ end
312
+ end
313
+
314
+ # @param [Parameters] params_ast a parameter list.
315
+ # @return [Boolean] true if the given parameter list is empty.
316
+ def empty_params?(params_ast)
317
+ params_ast.params.empty? && params_ast.optionals.empty? &&
318
+ params_ast.rest_of_params.nil? &&
319
+ params_ast.params_after_rest.empty? && params_ast.keywords.empty? &&
320
+ params_ast.rest_of_keywords.nil? && params_ast.block_param.nil?
321
+ end
322
+
323
+ rule(Block) do
324
+ if ast.body.is_a?(Exprs)
325
+ @printer << 'do'
326
+ unless empty_params?(ast)
327
+ @printer << ' |'
328
+ print_parameters(ast)
329
+ @printer << '|'
330
+ end
331
+ @printer.down
332
+ print(ast.body)
333
+ @printer.up
334
+ @printer << 'end'
335
+ else
336
+ if empty_params?(ast)
337
+ @printer << '{ '
338
+ else
339
+ @printer << '{|'
340
+ print_parameters(ast)
341
+ @printer << '| '
342
+ end
343
+ print(ast.body)
344
+ @printer << ' }'
345
+ end
346
+ end
347
+
348
+ rule(Lambda) do
349
+ @printer << '-> ('
350
+ print_parameters(ast)
351
+ @printer << ') '
352
+ body = ast.body
353
+ if body.is_a?(Exprs) || body.is_a?(Conditional) || body.is_a?(Loop) ||
354
+ body.is_a?(ForLoop) || body.is_a?(BeginEnd) || body.is_a?(Def)
355
+ @printer << 'do'
356
+ @printer.down
357
+ print(body)
358
+ @printer.up
359
+ @printer << 'end'
360
+ else
361
+ @printer << '{ '
362
+ print(body)
363
+ @printer << ' }'
364
+ end
365
+ end
366
+
367
+ rule(Rescue) do
368
+ @printer << 'rescue '
369
+ print_each(ast.types, true)
370
+ if ast.parameter
371
+ @printer << ' => '
372
+ print(ast.parameter)
373
+ end
374
+ @printer.down
375
+ print(ast.body)
376
+ @printer.up
377
+ print(ast.nested_rescue)
378
+
379
+ if ast.else
380
+ @printer << 'else'
381
+ @printer.down
382
+ print(ast.else)
383
+ @printer.up
384
+ end
385
+
386
+ if ast.ensure
387
+ @printer << 'ensure'
388
+ @printer.down
389
+ print(ast.ensure)
390
+ @printer.up
391
+ end
392
+ end
393
+
394
+ rule(BeginEnd) do
395
+ @printer << 'begin'
396
+ @printer.down
397
+ print(ast.body)
398
+ @printer.up
399
+ print(ast.rescue)
400
+ @printer << 'end' << :nl
401
+ end
402
+
403
+ rule(Def) do
404
+ @printer << 'def '
405
+ if ast.singular
406
+ print(ast.singular)
407
+ @printer << '.'
408
+ end
409
+ @printer << ast.name.name
410
+ @printer << '('
411
+ print_parameters(ast)
412
+ @printer << ')' << :nl
413
+ @printer.down
414
+ print(ast.body)
415
+ @printer.up
416
+ print(ast.rescue)
417
+ @printer << 'end' << :nl
418
+ end
419
+
420
+ rule(ModuleDef) do
421
+ @printer << 'module '
422
+ print(ast.name)
423
+ @printer.down
424
+ print(ast.body)
425
+ @printer.up
426
+ print(ast.rescue)
427
+ @printer << 'end' << :nl
428
+ end
429
+
430
+ rule(ClassDef) do
431
+ @printer << 'class '
432
+ print(ast.name)
433
+ if ast.superclass
434
+ @printer << ' < '
435
+ print(ast.superclass)
436
+ end
437
+ @printer.down
438
+ print(ast.body)
439
+ @printer.up
440
+ print(ast.rescue)
441
+ @printer << 'end' << :nl
442
+ end
443
+
444
+ rule(SingularClassDef) do
445
+ @printer << 'class << '
446
+ print(ast.name)
447
+ @printer.down
448
+ print(ast.body)
449
+ @printer.up
450
+ print(ast.rescue)
451
+ @printer << 'end' << :nl
452
+ end
453
+
454
+ rule(Program) do
455
+ ast.elements.each do |e|
456
+ print(e)
457
+ @printer.nl
458
+ end
459
+ end
460
+
461
+ # @private
462
+ def print_each(array, first)
463
+ array.each do |e|
464
+ if e
465
+ if first
466
+ first = false
467
+ else
468
+ @printer << ', '
469
+ end
470
+ print(e)
471
+ end
472
+ end
473
+ first
474
+ end
475
+
476
+ # @private
477
+ def print_list(array, first)
478
+ array.each do |e|
479
+ if e
480
+ if first
481
+ first = false
482
+ else
483
+ @printer << ', '
484
+ end
485
+ yield e
486
+ end
487
+ end
488
+ first
489
+ end
490
+
491
+ end
492
+ end