unparser 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.circle.yml +4 -0
  3. data/.gitignore +2 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +16 -0
  6. data/Changelog.md +3 -0
  7. data/Gemfile +6 -0
  8. data/Gemfile.devtools +60 -0
  9. data/Guardfile +18 -0
  10. data/README.md +41 -0
  11. data/Rakefile +24 -0
  12. data/TODO +1 -0
  13. data/config/devtools.yml +2 -0
  14. data/config/flay.yml +3 -0
  15. data/config/flog.yml +2 -0
  16. data/config/mutant.yml +3 -0
  17. data/config/reek.yml +107 -0
  18. data/config/yardstick.yml +2 -0
  19. data/lib/unparser/buffer.rb +93 -0
  20. data/lib/unparser/constants.rb +87 -0
  21. data/lib/unparser/emitter/alias.rb +27 -0
  22. data/lib/unparser/emitter/argument.rb +154 -0
  23. data/lib/unparser/emitter/assignment.rb +140 -0
  24. data/lib/unparser/emitter/begin.rb +179 -0
  25. data/lib/unparser/emitter/binary.rb +52 -0
  26. data/lib/unparser/emitter/block.rb +53 -0
  27. data/lib/unparser/emitter/break.rb +28 -0
  28. data/lib/unparser/emitter/case.rb +97 -0
  29. data/lib/unparser/emitter/cbase.rb +22 -0
  30. data/lib/unparser/emitter/class.rb +72 -0
  31. data/lib/unparser/emitter/def.rb +107 -0
  32. data/lib/unparser/emitter/defined.rb +27 -0
  33. data/lib/unparser/emitter/for.rb +50 -0
  34. data/lib/unparser/emitter/hookexe.rb +42 -0
  35. data/lib/unparser/emitter/if.rb +85 -0
  36. data/lib/unparser/emitter/literal/composed.rb +64 -0
  37. data/lib/unparser/emitter/literal/dynamic.rb +54 -0
  38. data/lib/unparser/emitter/literal/dynamic_body.rb +109 -0
  39. data/lib/unparser/emitter/literal/execute_string.rb +38 -0
  40. data/lib/unparser/emitter/literal/primitive.rb +49 -0
  41. data/lib/unparser/emitter/literal/range.rb +33 -0
  42. data/lib/unparser/emitter/literal/regexp.rb +96 -0
  43. data/lib/unparser/emitter/literal/singleton.rb +24 -0
  44. data/lib/unparser/emitter/literal.rb +7 -0
  45. data/lib/unparser/emitter/module.rb +37 -0
  46. data/lib/unparser/emitter/next.rb +22 -0
  47. data/lib/unparser/emitter/not.rb +25 -0
  48. data/lib/unparser/emitter/op_assign.rb +63 -0
  49. data/lib/unparser/emitter/redo.rb +22 -0
  50. data/lib/unparser/emitter/repetition.rb +33 -0
  51. data/lib/unparser/emitter/retry.rb +22 -0
  52. data/lib/unparser/emitter/return.rb +38 -0
  53. data/lib/unparser/emitter/root.rb +7 -0
  54. data/lib/unparser/emitter/send/binary.rb +100 -0
  55. data/lib/unparser/emitter/send/index.rb +82 -0
  56. data/lib/unparser/emitter/send/unary.rb +29 -0
  57. data/lib/unparser/emitter/send.rb +273 -0
  58. data/lib/unparser/emitter/splat.rb +24 -0
  59. data/lib/unparser/emitter/super.rb +46 -0
  60. data/lib/unparser/emitter/undef.rb +25 -0
  61. data/lib/unparser/emitter/variable.rb +83 -0
  62. data/lib/unparser/emitter/yield.rb +28 -0
  63. data/lib/unparser/emitter.rb +308 -0
  64. data/lib/unparser.rb +87 -0
  65. data/spec/integration/unparser/spike_spec.rb +914 -0
  66. data/spec/spec_helper.rb +13 -0
  67. data/spec/unit/unparser/buffer/append_spec.rb +23 -0
  68. data/spec/unit/unparser/buffer/content_spec.rb +38 -0
  69. data/spec/unit/unparser/buffer/indent_spec.rb +18 -0
  70. data/spec/unit/unparser/buffer/nl_spec.rb +16 -0
  71. data/spec/unit/unparser/buffer/unindent_spec.rb +18 -0
  72. data/spec/unit/unparser/class_methods/unparse_spec.rb +16 -0
  73. data/spec/unit/unparser/emitter/class_methods/handle_spec.rb +17 -0
  74. data/spec/unit/unparser/emitter/class_methods/visit_spec.rb +37 -0
  75. data/spec/unit/unparser/emitter/source_map/class_methods/emit_spec.rb +20 -0
  76. data/unparser.gemspec +24 -0
  77. metadata +201 -0
@@ -0,0 +1,96 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+
5
+ # Emitter for regexp literals
6
+ class Regexp < self
7
+ DELIMITER = '/'.freeze
8
+
9
+ handle :regexp
10
+
11
+ private
12
+
13
+ # Perform dispatch
14
+ #
15
+ # @return [undefined]
16
+ #
17
+ # @api private
18
+ #
19
+ def dispatch
20
+ parentheses(DELIMITER, DELIMITER) do
21
+ visit(dynamic_body)
22
+ end
23
+ visit(children.last)
24
+ end
25
+
26
+ # Return dynamic body
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ # @api private
31
+ #
32
+ def dynamic_body
33
+ Parser::AST::Node.new(:dyn_regexp_body, dynamic_body_children)
34
+ end
35
+
36
+ # Return dynamic body children
37
+ #
38
+ # @return [Enumerable<Parser::AST::Node>]
39
+ #
40
+ # @api private
41
+ #
42
+ def dynamic_body_children
43
+ children[0..-2].map do |child|
44
+ escape(child)
45
+ end
46
+ end
47
+
48
+ # Return escaped child
49
+ #
50
+ # @return [Parser::AST::Node]
51
+ #
52
+ # @api private
53
+ #
54
+ def escape(child)
55
+ return child unless child.type == :str
56
+ source = child.children.first
57
+ Parser::AST::Node.new(:str, [Unparser.transquote(source, delimiter, DELIMITER)])
58
+ end
59
+
60
+ # Return closing delimiter
61
+ #
62
+ # @return [String]
63
+ #
64
+ # @api private
65
+ #
66
+ def delimiter
67
+ location = node.location
68
+ return DELIMITER unless location
69
+ location.expression.source[-1]
70
+ end
71
+ memoize :delimiter
72
+
73
+ end # Regexp
74
+
75
+ # Emitter for regexp options
76
+ class Regopt < self
77
+
78
+ handle :regopt
79
+
80
+ private
81
+
82
+ # Perform dispatch
83
+ #
84
+ # @return [undefined]
85
+ #
86
+ # @api private
87
+ #
88
+ def dispatch
89
+ write(children.map(&:to_s).join)
90
+ end
91
+
92
+ end # Regopt
93
+
94
+ end # Literal
95
+ end # Emitter
96
+ end # Unparser
@@ -0,0 +1,24 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+ # Emiter for literal singletons
5
+ class Singleton < self
6
+
7
+ handle :self, :true, :false, :nil
8
+
9
+ private
10
+
11
+ # Perform dispatco
12
+ #
13
+ # @return [undefined]
14
+ #
15
+ # @api private
16
+ #
17
+ def dispatch
18
+ buffer.append(node.type.to_s)
19
+ end
20
+
21
+ end # Singleton
22
+ end # Literal
23
+ end # Emitter
24
+ end # Unparser
@@ -0,0 +1,7 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Namespace class for literal emiters
4
+ class Literal < self
5
+ end # Literal
6
+ end # Emitter
7
+ end # Unparser
@@ -0,0 +1,37 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for module nodes
4
+ class Module < self
5
+
6
+ handle :module
7
+
8
+ children :name, :body
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ write(K_MODULE, WS)
20
+ visit(name)
21
+ emit_body
22
+ k_end
23
+ end
24
+
25
+ # Emit body
26
+ #
27
+ # @return [undefined]
28
+ #
29
+ # @api private
30
+ #
31
+ def emit_body
32
+ emit_non_nil_body(body)
33
+ end
34
+
35
+ end # Module
36
+ end # Emitter
37
+ end # Unparser
@@ -0,0 +1,22 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for next nodes
4
+ class Next < self
5
+
6
+ handle :next
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ write(K_NEXT)
18
+ end
19
+
20
+ end # Next
21
+ end # Emitter
22
+ end # Unparser
@@ -0,0 +1,25 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for 1.8 only not node
4
+ class Not < self
5
+
6
+ handle :not
7
+
8
+ children :body
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ write(O_NEG)
20
+ visit(body)
21
+ end
22
+
23
+ end # Not
24
+ end # Emitter
25
+ end # Unparser
@@ -0,0 +1,63 @@
1
+ module Unparser
2
+ class Emitter
3
+
4
+ # Base class for and and or op-assign
5
+ class BinaryAssign < self
6
+
7
+ children :target, :expression
8
+
9
+ MAP = IceNine.deep_freeze(
10
+ :and_asgn => '&&=',
11
+ :or_asgn => '||='
12
+ )
13
+
14
+ handle *MAP.keys
15
+
16
+ private
17
+
18
+ # Perform dispatch
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ #
24
+ def dispatch
25
+ visit(target)
26
+ write(WS, MAP.fetch(node.type), WS)
27
+ visit(expression)
28
+ end
29
+
30
+ end # BinaryAssign
31
+
32
+ # Emitter for op assign
33
+ class OpAssign < self
34
+
35
+ handle :op_asgn
36
+
37
+ private
38
+
39
+ # Perform dispatch
40
+ #
41
+ # @return [undefined]
42
+ #
43
+ # @api private
44
+ #
45
+ def dispatch
46
+ visit(first_child)
47
+ emit_operator
48
+ visit(children[2])
49
+ end
50
+
51
+ # Emit operator
52
+ #
53
+ # @return [undefined]
54
+ #
55
+ # @api private
56
+ #
57
+ def emit_operator
58
+ write(WS, children[1].to_s, O_ASN, WS)
59
+ end
60
+
61
+ end # OpAssign
62
+ end # Emitte
63
+ end # Unparser
@@ -0,0 +1,22 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for redo nodes
4
+ class Redo < self
5
+
6
+ handle :redo
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ write(K_REDO)
18
+ end
19
+
20
+ end # Redo
21
+ end # Emitter
22
+ end # Unparser
@@ -0,0 +1,33 @@
1
+ module Unparser
2
+ class Emitter
3
+
4
+ # Base class for while and until emitters
5
+ class Repetition < self
6
+
7
+ MAP = {
8
+ :while => K_WHILE,
9
+ :until => K_UNTIL
10
+ }.freeze
11
+
12
+ handle *MAP.keys
13
+
14
+ children :condition, :body
15
+
16
+ private
17
+
18
+ # Perform dispatch
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ #
24
+ def dispatch
25
+ write(MAP.fetch(node.type), WS)
26
+ visit(condition)
27
+ indented { visit(body) }
28
+ k_end
29
+ end
30
+
31
+ end # Repetition
32
+ end # Emitter
33
+ end # Unparser
@@ -0,0 +1,22 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for retry nodes
4
+ class Retry < self
5
+
6
+ handle :retry
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ write(K_RETRY)
18
+ end
19
+
20
+ end # Break
21
+ end # Emitter
22
+ end # Unparser
@@ -0,0 +1,38 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for return nodes
4
+ class Return < self
5
+
6
+ handle :return
7
+
8
+ children :argument
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ write(K_RETURN)
20
+ emit_argument
21
+ end
22
+
23
+ # Emit argument
24
+ #
25
+ # @return [undefined]
26
+ #
27
+ # @api private
28
+ #
29
+ def emit_argument
30
+ return unless argument
31
+ parentheses do
32
+ visit(argument)
33
+ end
34
+ end
35
+
36
+ end # Return
37
+ end # Emitter
38
+ end # Unparser
@@ -0,0 +1,7 @@
1
+ module Unparser
2
+ class Emitter
3
+ Root = ::Class.new(self) do
4
+ def initialize(); end
5
+ end.send(:new)
6
+ end
7
+ end
@@ -0,0 +1,100 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Send
4
+ # Emitter for binary sends
5
+ class Binary < self
6
+
7
+ private
8
+
9
+ # Return undefined
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ # @api private
14
+ #
15
+ def dispatch
16
+ emit_receiver
17
+ emit_operator
18
+ emit_right
19
+ end
20
+
21
+ # Emit receiver
22
+ #
23
+ # @return [undefined]
24
+ #
25
+ # @api private
26
+ #
27
+ def emit_receiver
28
+ emit_unambiguous_receiver
29
+ write(O_DOT) if parentheses?
30
+ end
31
+
32
+ # Emit operator
33
+ #
34
+ # @return [undefined]
35
+ #
36
+ # @api private
37
+ #
38
+ def emit_operator
39
+ parens = parentheses? ? EMPTY_STRING : WS
40
+ parentheses(parens, parens) { write(selector) }
41
+ end
42
+
43
+ # Return right node
44
+ #
45
+ # @return [Parser::AST::Node]
46
+ #
47
+ # @api private
48
+ #
49
+ def right_node
50
+ children[2]
51
+ end
52
+
53
+ # Test for splat argument
54
+ #
55
+ # @return [true]
56
+ # if first argument is a splat
57
+ #
58
+ # @return [false]
59
+ # otherwise
60
+ #
61
+ # @api private
62
+ #
63
+ def splat?
64
+ right_node.type == :splat
65
+ end
66
+
67
+ # Test if parentheses are needed
68
+ #
69
+ # @return [true]
70
+ # if parenthes are needed
71
+ #
72
+ # @return [false]
73
+ # otherwise
74
+ #
75
+ # @api private
76
+ #
77
+ def parentheses?
78
+ splat? || children.length >= 4
79
+ end
80
+ memoize :parentheses?
81
+
82
+ # Emit right
83
+ #
84
+ # @return [undefined]
85
+ #
86
+ # @api private
87
+ #
88
+ def emit_right
89
+ node = right_node
90
+ if parentheses?
91
+ parentheses { delimited(children[2..-1]) }
92
+ return
93
+ end
94
+ visit(node)
95
+ end
96
+
97
+ end # Binary
98
+ end # Send
99
+ end # Emitter
100
+ end # Unparser
@@ -0,0 +1,82 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Send
4
+ # Emitter for send to index references
5
+ class Index < self
6
+
7
+ private
8
+
9
+ # Perform dispatch
10
+ #
11
+ # @return [undefined]
12
+ #
13
+ # @api private
14
+ #
15
+ def dispatch
16
+ emit_receiver
17
+ emit_arguments
18
+ end
19
+
20
+ # Emit block within parentheses
21
+ #
22
+ # @return [undefined]
23
+ #
24
+ # @api private
25
+ #
26
+ def parentheses(&block)
27
+ super(*INDEX_PARENS, &block)
28
+ end
29
+
30
+ # Emit receiver
31
+ #
32
+ # @return [undefined]
33
+ #
34
+ # @api private
35
+ #
36
+ def emit_receiver
37
+ visit(first_child)
38
+ end
39
+
40
+ # Emitter for index reference nodes
41
+ class Reference < self
42
+
43
+ private
44
+
45
+ # Emit arguments
46
+ #
47
+ # @return [undefined]
48
+ #
49
+ # @api private
50
+ #
51
+ def emit_arguments
52
+ parentheses do
53
+ delimited(arguments)
54
+ end
55
+ end
56
+ end # Reference
57
+
58
+ # Emitter for assign to index nodes
59
+ class Assign < self
60
+
61
+ # Emit arguments
62
+ #
63
+ # @return [undefined]
64
+ #
65
+ # @api private
66
+ #
67
+ def emit_arguments
68
+ index, *assignment = arguments
69
+ parentheses do
70
+ delimited([index])
71
+ end
72
+ return if assignment.empty? # mlhs
73
+ write(WS, O_ASN, WS)
74
+ delimited(assignment)
75
+ end
76
+
77
+ end # Assign
78
+
79
+ end # Index
80
+ end # Send
81
+ end # Emitter
82
+ end # Unparser
@@ -0,0 +1,29 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Send
4
+ # Emitter for unary sends
5
+ class Unary < self
6
+
7
+ private
8
+
9
+ MAP = IceNine.deep_freeze(
10
+ '-@' => '-',
11
+ '+@' => '+'
12
+ )
13
+
14
+ # Perform dispatch
15
+ #
16
+ # @return [undefined]
17
+ #
18
+ # @api private
19
+ #
20
+ def dispatch
21
+ name = selector
22
+ write(MAP.fetch(name, name))
23
+ emit_unambiguous_receiver
24
+ end
25
+
26
+ end # Unary
27
+ end # Send
28
+ end # Emitter
29
+ end # Unparser