sorcerer 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +33 -7
- data/lib/sorcerer/resource.rb +18 -4
- data/lib/sorcerer/version.rb +1 -1
- data/test/sorcerer/resource_test.rb +134 -116
- data/test/sorcerer/subexpression_test.rb +4 -4
- metadata +1 -1
data/README.textile
CHANGED
@@ -46,15 +46,14 @@ Ripper may be used to produce the s-expressions used by Sorcerer. The following
|
|
46
46
|
|
47
47
|
h2. Options
|
48
48
|
|
49
|
-
h3.
|
49
|
+
h3. No Options
|
50
50
|
|
51
|
-
|
52
|
-
the source command.
|
51
|
+
By default, sorcerer will output its source in single line mode.
|
53
52
|
|
54
53
|
For example, given:
|
55
54
|
|
56
55
|
<pre style="background: LightGrey">
|
57
|
-
sexp = Ripper::SexpBuilder.new("def foo; end").parse
|
56
|
+
sexp = Ripper::SexpBuilder.new("def foo; bar; end").parse
|
58
57
|
</pre>
|
59
58
|
|
60
59
|
Then the following
|
@@ -66,10 +65,15 @@ Then the following
|
|
66
65
|
generates single line output (the default):
|
67
66
|
|
68
67
|
<pre style="background: LightBlue">
|
69
|
-
def foo; end
|
68
|
+
def foo; bar; end
|
70
69
|
</pre>
|
71
70
|
|
72
|
-
|
71
|
+
h3. Multi-Line Output
|
72
|
+
|
73
|
+
If you want multi-line output of source, add the multiline option to
|
74
|
+
the source command.
|
75
|
+
|
76
|
+
For example, given the sexp generated above, then this
|
73
77
|
|
74
78
|
<pre style="background: LightGrey">
|
75
79
|
puts Sorcerer.source(sexp, multiline: true)
|
@@ -79,6 +83,28 @@ generates multi-line output
|
|
79
83
|
|
80
84
|
<pre style="background: LightBlue">
|
81
85
|
def foo
|
86
|
+
bar
|
87
|
+
end
|
88
|
+
</pre>
|
89
|
+
|
90
|
+
(Note that all multi-line output will have a final newline.)
|
91
|
+
|
92
|
+
h3. Indentation
|
93
|
+
|
94
|
+
By default, sorcerer does not indent its multiline output. Adding the
|
95
|
+
"indent" option will cause the output to be indented.
|
96
|
+
|
97
|
+
For example, given the sexp generated above, then the following
|
98
|
+
|
99
|
+
<pre style="background: LightGrey">
|
100
|
+
puts Sorcerer.source(sexp, indent: true)
|
101
|
+
</pre>
|
102
|
+
|
103
|
+
generates indented output:
|
104
|
+
|
105
|
+
<pre style="background: LightBlue">
|
106
|
+
def foo
|
107
|
+
bar
|
82
108
|
end
|
83
109
|
</pre>
|
84
110
|
|
@@ -96,6 +122,6 @@ h2. History
|
|
96
122
|
* 0.0.7 - Basic single line version
|
97
123
|
* 0.1.0 - Added support for multi-line output. Improved rendering of a
|
98
124
|
number of constructs
|
99
|
-
|
125
|
+
* 0.2.0 - Added support for indented output.
|
100
126
|
|
101
127
|
|
data/lib/sorcerer/resource.rb
CHANGED
@@ -33,6 +33,9 @@ module Sorcerer
|
|
33
33
|
def source
|
34
34
|
@stack.clear
|
35
35
|
resource(@sexp)
|
36
|
+
if multiline?
|
37
|
+
@source << "\n" unless @source =~ /\n\z/m
|
38
|
+
end
|
36
39
|
@source
|
37
40
|
end
|
38
41
|
|
@@ -203,6 +206,10 @@ module Sorcerer
|
|
203
206
|
sexp == VOID_BODY2
|
204
207
|
end
|
205
208
|
|
209
|
+
def label?(sexp)
|
210
|
+
sexp?(sexp) && sexp.first == :@label
|
211
|
+
end
|
212
|
+
|
206
213
|
def last_handler
|
207
214
|
@stack.last
|
208
215
|
end
|
@@ -350,7 +357,11 @@ module Sorcerer
|
|
350
357
|
:assign_error => NYI,
|
351
358
|
:assoc_new => lambda { |sexp|
|
352
359
|
resource(sexp[1])
|
353
|
-
|
360
|
+
if label?(sexp[1])
|
361
|
+
emit(" ")
|
362
|
+
else
|
363
|
+
emit(" => ")
|
364
|
+
end
|
354
365
|
resource(sexp[2])
|
355
366
|
},
|
356
367
|
:assoclist_from_args => lambda { |sexp|
|
@@ -536,8 +547,11 @@ module Sorcerer
|
|
536
547
|
},
|
537
548
|
:hash => lambda { |sexp|
|
538
549
|
emit("{")
|
539
|
-
|
540
|
-
|
550
|
+
if sexp[1]
|
551
|
+
emit(" ")
|
552
|
+
resource(sexp[1])
|
553
|
+
end
|
554
|
+
emit(" }")
|
541
555
|
},
|
542
556
|
:if => lambda { |sexp|
|
543
557
|
emit("if ")
|
@@ -862,7 +876,7 @@ module Sorcerer
|
|
862
876
|
:@int => EMIT1,
|
863
877
|
:@ivar => EMIT1,
|
864
878
|
:@kw => EMIT1,
|
865
|
-
:@label =>
|
879
|
+
:@label => EMIT1,
|
866
880
|
:@lbrace => NYI,
|
867
881
|
:@lbracket => NYI,
|
868
882
|
:@lparen => NYI,
|
data/lib/sorcerer/version.rb
CHANGED
@@ -32,7 +32,7 @@ class SourcerTest < Test::Unit::TestCase
|
|
32
32
|
# * "#" is expected to be a tabbed indent in indent mode and a null
|
33
33
|
# string in single line and multi-line modes.
|
34
34
|
#
|
35
|
-
def
|
35
|
+
def assert_resource_lines(string)
|
36
36
|
assert_resource_for_mode(string, multiline: false) { |s| for_single_line(s) }
|
37
37
|
assert_resource_for_mode(string, multiline: true) { |s| for_multi_line(s) }
|
38
38
|
assert_resource_for_mode(string, indent: true) { |s| for_indented(s) }
|
@@ -46,15 +46,26 @@ class SourcerTest < Test::Unit::TestCase
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def for_single_line(string)
|
49
|
-
string.
|
49
|
+
string.
|
50
|
+
gsub(/\bTHEN~/, "then ").
|
51
|
+
gsub(/~/, " ").
|
52
|
+
gsub(/#/,'')
|
50
53
|
end
|
51
54
|
|
52
55
|
def for_multi_line(string)
|
53
|
-
string.
|
56
|
+
string.
|
57
|
+
gsub(/\b THEN~/, "; ").
|
58
|
+
gsub(/~/, "\n").
|
59
|
+
gsub(/; /, "\n").
|
60
|
+
gsub(/#/,'') + "\n"
|
54
61
|
end
|
55
62
|
|
56
63
|
def for_indented(string)
|
57
|
-
string.
|
64
|
+
string.
|
65
|
+
gsub(/\b THEN~/, "; ").
|
66
|
+
gsub(/~/, "\n").
|
67
|
+
gsub(/; /, "\n").
|
68
|
+
gsub(/#/,' ') + "\n"
|
58
69
|
end
|
59
70
|
|
60
71
|
def source(string, options={})
|
@@ -63,6 +74,7 @@ class SourcerTest < Test::Unit::TestCase
|
|
63
74
|
puts "***************************** options: #{options.inspect}"
|
64
75
|
end
|
65
76
|
sexp = Ripper::SexpBuilder.new(string).parse
|
77
|
+
fail "Failed to parts '#{string}'" if sexp.nil?
|
66
78
|
Sorcerer.source(sexp, options)
|
67
79
|
end
|
68
80
|
|
@@ -149,42 +161,50 @@ class SourcerTest < Test::Unit::TestCase
|
|
149
161
|
assert_resource "meth(a, :x => 1, :y => 2)"
|
150
162
|
end
|
151
163
|
|
164
|
+
def test_can_source_method_with_new_hash_syntax
|
165
|
+
assert_resource "meth(x: 1)"
|
166
|
+
assert_resource "meth(x: 1, y: 2)"
|
167
|
+
assert_resource "meth(a, x: 1)"
|
168
|
+
assert_resource "meth(a, x: 1, y: 2)"
|
169
|
+
assert_resource "meth(a, :x => 1, y: 2)"
|
170
|
+
end
|
171
|
+
|
152
172
|
def test_can_source_method_with_do_block
|
153
|
-
|
154
|
-
|
155
|
-
|
173
|
+
assert_resource_lines "meth do end"
|
174
|
+
assert_resource_lines "meth do |a| end"
|
175
|
+
assert_resource_lines "meth(x, y, *rest, &code) do |a, b=1, c=x, *args, &block|~#one; #two; #three~end"
|
156
176
|
end
|
157
177
|
|
158
178
|
def test_can_source_method_with_block
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
179
|
+
assert_resource_lines "meth { }"
|
180
|
+
assert_resource_lines "meth { |a| }"
|
181
|
+
assert_resource_lines "meth { |a, b| }"
|
182
|
+
assert_resource_lines "meth { |*args| }"
|
183
|
+
assert_resource_lines "meth { |a, *args| }"
|
184
|
+
assert_resource_lines "meth { |&block| }"
|
185
|
+
assert_resource_lines "meth { |*args, &block| }"
|
186
|
+
assert_resource_lines "meth { |a, b, *args, &block| }"
|
187
|
+
assert_resource_lines "meth { |a, b=1, *args, &block| }"
|
188
|
+
assert_resource_lines "meth { |a, b=1, c=x, *args, &block| }"
|
169
189
|
end
|
170
190
|
|
171
191
|
def test_can_source_method_with_block_contents
|
172
|
-
|
173
|
-
|
192
|
+
assert_resource_lines "meth { |a|~#a.x~}"
|
193
|
+
assert_resource_lines "meth { |a|~#a.x; #b.z~}"
|
174
194
|
end
|
175
195
|
|
176
196
|
def test_can_source_method_with_complex_args_and_block
|
177
|
-
|
197
|
+
assert_resource_lines "meth(x, y, *rest, &code) { |a, b=1, c=x, *args, &block|~#one; #two; #three~}"
|
178
198
|
end
|
179
199
|
|
180
200
|
def test_can_source_stabby_procs
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
201
|
+
assert_resource_lines "-> { }"
|
202
|
+
assert_resource_lines "->() { }"
|
203
|
+
assert_resource_lines "->(a) { }"
|
204
|
+
assert_resource_lines "->(a, b) { }"
|
205
|
+
assert_resource_lines "->(a, *args) { }"
|
206
|
+
assert_resource_lines "->(a, b=12, *args, &block) { }"
|
207
|
+
assert_resource_lines "->(a) {~b~}"
|
188
208
|
end
|
189
209
|
|
190
210
|
def test_can_source_dot_calls
|
@@ -295,9 +315,19 @@ class SourcerTest < Test::Unit::TestCase
|
|
295
315
|
end
|
296
316
|
|
297
317
|
def test_can_source_hash_literals
|
298
|
-
assert_resource "{}"
|
299
|
-
assert_resource "{:a => 1}"
|
300
|
-
assert_resource "{:a => 1, :b => 2}"
|
318
|
+
assert_resource "{ }"
|
319
|
+
assert_resource "{ :a => 1 }"
|
320
|
+
assert_resource "{ :a => 1, :b => 2 }"
|
321
|
+
end
|
322
|
+
|
323
|
+
def test_can_source_new_hash_literals
|
324
|
+
assert_resource "{ }"
|
325
|
+
assert_resource "{ a: 1 }"
|
326
|
+
assert_resource "{ a: 1, b: 2 }"
|
327
|
+
end
|
328
|
+
|
329
|
+
def test_can_source_mixed_hash_literals
|
330
|
+
assert_resource "{ a: 1, :b => 2, c: 3, :d => 4 }"
|
301
331
|
end
|
302
332
|
|
303
333
|
def test_can_source_unary_expression
|
@@ -376,41 +406,41 @@ class SourcerTest < Test::Unit::TestCase
|
|
376
406
|
end
|
377
407
|
|
378
408
|
def test_can_source_statement_sequences
|
379
|
-
|
380
|
-
|
381
|
-
|
409
|
+
assert_resource_lines "a"
|
410
|
+
assert_resource_lines "a; b"
|
411
|
+
assert_resource_lines "a; b; c"
|
382
412
|
end
|
383
413
|
|
384
414
|
def test_can_source_begin_end
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
415
|
+
assert_resource_lines "begin end"
|
416
|
+
assert_resource_lines "begin~#a; end"
|
417
|
+
assert_resource_lines "begin~#a(); end"
|
418
|
+
assert_resource_lines "begin~#a; #b; #c; end"
|
389
419
|
end
|
390
420
|
|
391
421
|
def test_can_source_begin_rescue_end
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
422
|
+
assert_resource_lines "begin~rescue; end"
|
423
|
+
assert_resource_lines "begin~rescue E => ex; #b; end"
|
424
|
+
assert_resource_lines "begin~#a; rescue E => ex; #b; end"
|
425
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; end"
|
426
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; #c; end"
|
427
|
+
assert_resource_lines "begin~rescue E, F => ex; #b; #c; end"
|
398
428
|
end
|
399
429
|
|
400
430
|
def test_can_source_begin_ensure_end
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
431
|
+
assert_resource_lines "begin~ensure~end"
|
432
|
+
assert_resource_lines "begin~ensure~#b; end"
|
433
|
+
assert_resource_lines "begin~#a; ensure~#b; end"
|
434
|
+
assert_resource_lines "begin~#a; ensure~#b; end"
|
405
435
|
end
|
406
436
|
|
407
437
|
def test_can_source_begin_rescue_ensure_end
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
438
|
+
assert_resource_lines "begin~rescue; end"
|
439
|
+
assert_resource_lines "begin~rescue E => ex; #b; ensure~#c; end"
|
440
|
+
assert_resource_lines "begin~#a; rescue E => ex; #b; ensure~#c; end"
|
441
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; ensure~#c; end"
|
442
|
+
assert_resource_lines "begin~#a; rescue E, F => ex; #b; #c; ensure~#d; end"
|
443
|
+
assert_resource_lines "begin~rescue E, F => ex; #b; #c; ensure~#d; end"
|
414
444
|
end
|
415
445
|
|
416
446
|
def test_can_source_rescue_modifier
|
@@ -418,69 +448,57 @@ class SourcerTest < Test::Unit::TestCase
|
|
418
448
|
end
|
419
449
|
|
420
450
|
def test_can_source_if
|
421
|
-
|
422
|
-
assert_resource "if a\nb\nend", multiline: true
|
423
|
-
assert_resource "if a\n b\nend", indent: 2
|
451
|
+
assert_resource_lines "if a THEN~#b~end"
|
424
452
|
end
|
425
453
|
|
426
454
|
def test_can_source_if_else
|
427
|
-
|
428
|
-
assert_resource "if a\nb\nelse\nc\nend", multiline: true
|
429
|
-
assert_resource "if a\n b\nelse\n c\nend", indent: 2
|
455
|
+
assert_resource_lines "if a THEN~#b~else~#c~end"
|
430
456
|
end
|
431
457
|
|
432
458
|
def test_can_source_if_elsif
|
433
|
-
|
434
|
-
assert_resource "if a\nb\nelsif c\nd\nend", multiline: true
|
435
|
-
assert_resource "if a\n b\nelsif c\n d\nend", indent: 2
|
459
|
+
assert_resource_lines "if a THEN~#b~elsif c THEN~#d~end"
|
436
460
|
end
|
437
461
|
|
438
462
|
def test_can_source_if_elsif_else
|
439
|
-
|
440
|
-
assert_resource "if a\nb\nelsif c\nd\nelse\ne\nend", multiline: true
|
441
|
-
assert_resource "if a\n b\nelsif c\n d\nelse\n e\nend", indent: 2
|
463
|
+
assert_resource_lines "if a THEN~#b~elsif c THEN~#d~else~#e~end"
|
442
464
|
end
|
443
465
|
|
444
466
|
def test_can_source_unless
|
445
|
-
|
446
|
-
assert_resource "unless a\nb\nend", multiline: true
|
447
|
-
assert_resource "unless a\n b\nend", indent: 2
|
467
|
+
assert_resource_lines "unless a THEN~#b~end"
|
448
468
|
end
|
449
469
|
|
450
470
|
def test_can_source_unless_else
|
451
|
-
|
452
|
-
assert_resource "unless a\nb\nelse\nc\nend", multiline: true
|
453
|
-
assert_resource "unless a\n b\nelse\n c\nend", indent: 2
|
471
|
+
assert_resource_lines "unless a THEN~#b~else~#c~end"
|
454
472
|
end
|
455
473
|
|
456
474
|
def test_can_source_while
|
457
|
-
|
458
|
-
|
475
|
+
assert_resource_lines "while c; end"
|
476
|
+
assert_resource_lines "while c; #body; end"
|
459
477
|
end
|
460
478
|
|
461
479
|
def test_can_source_until
|
462
|
-
|
480
|
+
assert_resource_lines "until c; #body end"
|
463
481
|
end
|
464
482
|
|
465
483
|
def test_can_source_for
|
466
|
-
|
467
|
-
|
484
|
+
assert_resource_lines "for a in list; end"
|
485
|
+
assert_resource_lines "for a in list; #c~end"
|
468
486
|
end
|
469
487
|
|
470
488
|
def test_can_source_break
|
471
|
-
|
472
|
-
|
489
|
+
assert_resource_lines "while c; #a; #break if b; #c; end"
|
490
|
+
assert_resource_lines "while c; #a; #break value if b; #c; end"
|
473
491
|
end
|
474
492
|
|
475
493
|
def test_can_source_next
|
476
|
-
|
477
|
-
|
494
|
+
assert_resource_lines "while c; #a; #next if b; #c; end"
|
495
|
+
assert_resource_lines "while c; #a; #next if b; #c; end"
|
478
496
|
end
|
479
497
|
|
480
498
|
def test_can_source_case
|
481
|
-
|
482
|
-
|
483
|
-
|
499
|
+
assert_resource_lines "case a~when b; #c; end"
|
500
|
+
assert_resource_lines "case a~when b; #c when d; #e; end"
|
501
|
+
assert_resource_lines "case a~when b; #c when d; #e~else~#f; end"
|
484
502
|
end
|
485
503
|
|
486
504
|
def test_can_source_if_modifier
|
@@ -545,63 +563,63 @@ class SourcerTest < Test::Unit::TestCase
|
|
545
563
|
end
|
546
564
|
|
547
565
|
def test_can_source_def
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
566
|
+
assert_resource_lines "def f; end"
|
567
|
+
assert_resource_lines "def f; #x; end"
|
568
|
+
assert_resource_lines "def f a; end"
|
569
|
+
assert_resource_lines "def f(); end"
|
570
|
+
assert_resource_lines "def f(a); end"
|
571
|
+
assert_resource_lines "def f(a, b); end"
|
572
|
+
assert_resource_lines "def f(a, *args); end"
|
573
|
+
assert_resource_lines "def f(a, *args, &block); end"
|
574
|
+
assert_resource_lines "def f(a); #x; end"
|
575
|
+
assert_resource_lines "def f(a); #x; #y; end"
|
558
576
|
end
|
559
577
|
|
560
578
|
def test_can_source_class_without_parent
|
561
|
-
|
562
|
-
|
563
|
-
|
579
|
+
assert_resource_lines "class X; end"
|
580
|
+
assert_resource_lines "class X; #x; end"
|
581
|
+
assert_resource_lines "class X; #def f(); #end; end"
|
564
582
|
end
|
565
583
|
|
566
584
|
def test_can_source_class_with_parent
|
567
|
-
|
568
|
-
|
585
|
+
assert_resource_lines "class X < Y; end"
|
586
|
+
assert_resource_lines "class X < Y; #x; end"
|
569
587
|
end
|
570
588
|
|
571
589
|
def test_can_source_class_with_self_parent
|
572
|
-
|
590
|
+
assert_resource_lines "class X < self; end"
|
573
591
|
end
|
574
592
|
|
575
593
|
def test_can_source_private_etc_in_class
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
594
|
+
assert_resource_lines "class X; #public; #def f(); #end; end"
|
595
|
+
assert_resource_lines "class X; #protected; #def f(); #end; end"
|
596
|
+
assert_resource_lines "class X; #private; #def f(); #end; end"
|
597
|
+
assert_resource_lines "class X; #def f(); #end; #public :f; end"
|
598
|
+
assert_resource_lines "class X; #def f(); #end; #protected :f; end"
|
599
|
+
assert_resource_lines "class X; #def f(); #end; #private :f; end"
|
582
600
|
end
|
583
601
|
|
584
602
|
def test_can_source_module
|
585
|
-
|
586
|
-
|
587
|
-
|
603
|
+
assert_resource_lines "module X; end"
|
604
|
+
assert_resource_lines "module X; #x; end"
|
605
|
+
assert_resource_lines "module X; #def f(); #end; end"
|
588
606
|
end
|
589
607
|
|
590
608
|
def test_can_source_BEGIN
|
591
|
-
|
592
|
-
|
593
|
-
|
609
|
+
assert_resource_lines "BEGIN { }"
|
610
|
+
assert_resource_lines "BEGIN {~#x~}"
|
611
|
+
assert_resource_lines "BEGIN {~#x; #y~}"
|
594
612
|
end
|
595
613
|
|
596
614
|
def test_can_source_END
|
597
|
-
|
598
|
-
|
599
|
-
|
615
|
+
assert_resource_lines "END { }"
|
616
|
+
assert_resource_lines "END {~#x~}"
|
617
|
+
assert_resource_lines "END {~#x; #y~}"
|
600
618
|
end
|
601
619
|
|
602
620
|
def test_can_source_then
|
603
|
-
|
604
|
-
|
621
|
+
assert_resource_lines "Then {~#a == b~}"
|
622
|
+
assert_resource_lines "Then {~#a == b; #x~}"
|
605
623
|
end
|
606
624
|
|
607
625
|
def test_can_use_ripper_sexp_output
|
@@ -20,7 +20,7 @@ class SubexpressionTest < Test::Unit::TestCase
|
|
20
20
|
|
21
21
|
def test_unary_expressions
|
22
22
|
assert_subexpressions "-(a+b)", [
|
23
|
-
"-(a + b)", "a + b", "a", "b",
|
23
|
+
"-(a + b)", "a + b", "a", "b",
|
24
24
|
]
|
25
25
|
end
|
26
26
|
|
@@ -61,8 +61,8 @@ class SubexpressionTest < Test::Unit::TestCase
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def test_hash_literal
|
64
|
-
assert_subexpressions "{:a => aa, :b => bb}", [
|
65
|
-
"{:a => aa, :b => bb}", "aa", "bb"
|
64
|
+
assert_subexpressions "{ :a => aa, :b => bb }", [
|
65
|
+
"{ :a => aa, :b => bb }", "aa", "bb"
|
66
66
|
]
|
67
67
|
end
|
68
68
|
|
@@ -74,7 +74,7 @@ class SubexpressionTest < Test::Unit::TestCase
|
|
74
74
|
assert_subexpressions "o.f(a+b, c*d, x.y, z(k, 2, 3)) { xx }", [
|
75
75
|
"o.f(a + b, c * d, x.y, z(k, 2, 3)) { xx }",
|
76
76
|
"a + b", "a", "b",
|
77
|
-
"c * d", "c", "d",
|
77
|
+
"c * d", "c", "d",
|
78
78
|
"x.y", "x",
|
79
79
|
"z(k, 2, 3)", "k",
|
80
80
|
"o",
|