unparser 0.0.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 (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,107 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for def node
4
+ class Def < self
5
+
6
+ private
7
+
8
+ # Emit name
9
+ #
10
+ # @return [undefined]
11
+ #
12
+ # @api private
13
+ #
14
+ abstract_method :emit_name
15
+ private :emit_name
16
+
17
+ # Return body node
18
+ #
19
+ # @return [Parser::AST::Node]
20
+ #
21
+ # @api private
22
+ #
23
+ abstract_method :body
24
+ private :body
25
+
26
+ # Perform dispatch
27
+ #
28
+ # @return [undefined]
29
+ #
30
+ # @api private
31
+ #
32
+ def dispatch
33
+ write(K_DEF, WS)
34
+ emit_name
35
+ emit_arguments
36
+ emit_body
37
+ k_end
38
+ end
39
+
40
+ # Emit body
41
+ #
42
+ # @return [undefined]
43
+ #
44
+ # @api private
45
+ #
46
+ def emit_body
47
+ indented { visit(body) }
48
+ end
49
+
50
+ # Emit arguments
51
+ #
52
+ # @return [undefined]
53
+ #
54
+ # @api private
55
+ #
56
+ def emit_arguments
57
+ return if arguments.children.empty?
58
+ parentheses do
59
+ visit(arguments)
60
+ end
61
+ end
62
+
63
+ # Instance def emitter
64
+ class Instance < self
65
+
66
+ handle :def
67
+
68
+ children :name, :arguments, :body
69
+
70
+ private
71
+
72
+ # Emit name
73
+ #
74
+ # @return [undefined]
75
+ #
76
+ # @api private
77
+ #
78
+ def emit_name
79
+ write(name.to_s)
80
+ end
81
+
82
+ end # Instance
83
+
84
+ # Emitter for defines on singleton
85
+ class Singleton < self
86
+
87
+ handle :defs
88
+
89
+ children :subject, :name, :arguments, :body
90
+
91
+ private
92
+
93
+ # Return mame
94
+ #
95
+ # @return [String]
96
+ #
97
+ # @api private
98
+ #
99
+ def emit_name
100
+ visit(subject)
101
+ write(O_DOT, name.to_s)
102
+ end
103
+
104
+ end # Singleton
105
+ end # Def
106
+ end # Emitter
107
+ end # Unparser
@@ -0,0 +1,27 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for defined? nodes
4
+ class Defined < self
5
+
6
+ handle :defined?
7
+
8
+ children :subject
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ write(K_DEFINED)
20
+ parentheses do
21
+ visit(subject)
22
+ end
23
+ end
24
+
25
+ end # Defined
26
+ end # Emitter
27
+ end # Unparser
@@ -0,0 +1,50 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter for for nodes
4
+ class For < self
5
+
6
+ handle :for
7
+
8
+ children :condition, :assignment, :body
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ write(K_FOR, WS)
20
+ emit_condition
21
+ emit_body
22
+ k_end
23
+ end
24
+
25
+ # Emit assignment
26
+ #
27
+ # @return [undefined]
28
+ #
29
+ # @api private
30
+ #
31
+ def emit_condition
32
+ visit(condition)
33
+ write(WS, K_IN, WS)
34
+ visit(assignment)
35
+ write(WS, K_DO)
36
+ end
37
+
38
+ # Emit body
39
+ #
40
+ # @return [undefined]
41
+ #
42
+ # @api private
43
+ #
44
+ def emit_body
45
+ indented { visit(body) }
46
+ end
47
+
48
+ end # For
49
+ end # Emitter
50
+ end # Unparser
@@ -0,0 +1,42 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Base class for pre and postexe emitters
4
+ class Hookexe < self
5
+
6
+ MAP = {
7
+ :preexe => K_PREEXE,
8
+ :postexe => K_POSTEXE
9
+ }.freeze
10
+
11
+ handle *MAP.keys
12
+
13
+ children :body
14
+
15
+ private
16
+
17
+ # Perfrom dispatch
18
+ #
19
+ # @return [undefined]
20
+ #
21
+ # @api private
22
+ #
23
+ def dispatch
24
+ write(MAP.fetch(node.type), WS)
25
+ parentheses(*CURLY_BRACKETS) do
26
+ emit_body
27
+ end
28
+ end
29
+
30
+ # Emit body
31
+ #
32
+ # @return [undefined]
33
+ #
34
+ # @api private
35
+ #
36
+ def emit_body
37
+ indented { visit(body) }
38
+ end
39
+
40
+ end # Hookexe
41
+ end # Emitter
42
+ end # Unparser
@@ -0,0 +1,85 @@
1
+ module Unparser
2
+ class Emitter
3
+ # Emitter if nodes
4
+ class If < self
5
+
6
+ handle :if
7
+
8
+ children :condition, :if_branch, :else_branch
9
+
10
+ private
11
+
12
+ # Perform dispatch
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ write(keyword, WS)
20
+ emit_condition
21
+ emit_if_branch
22
+ emit_else_branch
23
+ k_end
24
+ end
25
+
26
+ # Test for unless
27
+ #
28
+ # @return [true]
29
+ # if to emit as unless
30
+ #
31
+ # @return [false]
32
+ # otherwise
33
+ #
34
+ # @api private
35
+ #
36
+ def unless?
37
+ !if_branch
38
+ end
39
+
40
+ # Return keyword
41
+ #
42
+ # @return [String]
43
+ #
44
+ # @api private
45
+ #
46
+ def keyword
47
+ unless? ? K_UNLESS : K_IF
48
+ end
49
+
50
+ # Emit condition
51
+ #
52
+ # @return [undefined]
53
+ #
54
+ # @api private
55
+ #
56
+ def emit_condition
57
+ visit(condition)
58
+ end
59
+
60
+ # Emit if branch
61
+ #
62
+ # @return [undefined]
63
+ #
64
+ # @api private
65
+ #
66
+ def emit_if_branch
67
+ return unless if_branch
68
+ indented { visit(if_branch) }
69
+ end
70
+
71
+ # Emit else branch
72
+ #
73
+ # @return [undefined]
74
+ #
75
+ # @api private
76
+ #
77
+ def emit_else_branch
78
+ return unless else_branch
79
+ write(K_ELSE) unless unless?
80
+ indented { visit(else_branch) }
81
+ end
82
+
83
+ end # If
84
+ end # Emitter
85
+ end # Unparser
@@ -0,0 +1,64 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+
5
+ # Emitter for hash keyvalue pair
6
+ class HashPair < self
7
+ HASHROCKET = ' => '.freeze
8
+
9
+ handle :pair
10
+
11
+ private
12
+
13
+ # Perform dispatch
14
+ #
15
+ # @return [undefined]
16
+ #
17
+ # @api private
18
+ #
19
+ def dispatch
20
+ delimited(children, HASHROCKET)
21
+ end
22
+
23
+ end # HashPair
24
+
25
+ # Base class for compound literal emitters
26
+ class Compound < self
27
+
28
+ private
29
+
30
+ # Perform dispatch
31
+ #
32
+ # @return [undefined]
33
+ #
34
+ # @api private
35
+ #
36
+ def dispatch
37
+ util = self.class
38
+ parentheses(util::OPEN, util::CLOSE) do
39
+ delimited(children, util::DELIMITER)
40
+ end
41
+ end
42
+
43
+ # Hash literal emitter
44
+ class Hash < self
45
+ OPEN = '{'.freeze
46
+ CLOSE = '}'.freeze
47
+ DELIMITER = ', '.freeze
48
+
49
+ handle :hash
50
+ end # Hash
51
+
52
+ # Array literal emitter
53
+ class Array < self
54
+ OPEN = '['.freeze
55
+ CLOSE = ']'.freeze
56
+ DELIMITER = ', '.freeze
57
+
58
+ handle :array
59
+ end # Array
60
+
61
+ end # Compound
62
+ end # Literal
63
+ end # Emitter
64
+ end # Unparser
@@ -0,0 +1,54 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+
5
+ # Base class for dynamic literal emitters
6
+ class Dynamic < self
7
+
8
+ private
9
+
10
+ # Perform dispatch
11
+ #
12
+ # @return [undefined]
13
+ #
14
+ # @api private
15
+ #
16
+ def dispatch
17
+ util = self.class
18
+ parentheses(util::OPEN, util::CLOSE) do
19
+ visit(dynamic_body)
20
+ end
21
+ end
22
+
23
+ # Return dynamic body
24
+ #
25
+ # @return [Parser::AST::Node]
26
+ #
27
+ # @api private
28
+ #
29
+ def dynamic_body
30
+ Parser::AST::Node.new(:dyn_str_body, children)
31
+ end
32
+
33
+ # Dynamic string literal emitter
34
+ class String < self
35
+
36
+ OPEN = CLOSE = '"'.freeze
37
+ handle :dstr
38
+
39
+ end # String
40
+
41
+ # Dynamic symbol literal emitter
42
+ class Symbol < self
43
+
44
+ OPEN = ':"'.freeze
45
+ CLOSE = '"'.freeze
46
+
47
+ handle :dsym
48
+
49
+ end # Symbol
50
+
51
+ end
52
+ end # Literal
53
+ end # Emitter
54
+ end # Unparser
@@ -0,0 +1,109 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+
5
+ # Emitter for dynamic bodies
6
+ class DynamicBody < self
7
+
8
+ OPEN = '#{'.freeze
9
+ CLOSE = '}'.freeze
10
+
11
+ private
12
+
13
+ # Perform dispatch
14
+ #
15
+ # @return [undefined]
16
+ #
17
+ # @api private
18
+ #
19
+ def dispatch
20
+ children.each do |node|
21
+ emit_segment(node)
22
+ end
23
+ end
24
+
25
+ # Emit segment
26
+ #
27
+ # @param [Parser::Node] node
28
+ #
29
+ # @return [undefined]
30
+ #
31
+ # @api private
32
+ #
33
+ def emit_segment(node)
34
+ if node.type == :str
35
+ emit_str_segment(node)
36
+ return
37
+ end
38
+ emit_interpolated_segment(node)
39
+ end
40
+
41
+ ESCAPES = IceNine.deep_freeze(
42
+ "\n" => '\n'
43
+ )
44
+
45
+ REPLACEMENTS = ::Regexp.union(ESCAPES.keys)
46
+
47
+ # Emit str segment
48
+ #
49
+ # @param [Parser::Node] node
50
+ #
51
+ # @return [undefined]
52
+ #
53
+ # @api private
54
+ #
55
+ def emit_str_segment(node)
56
+ util = self.class
57
+ str = node.children.first
58
+ str = str.
59
+ gsub(util::DELIMITER, util::REPLACEMENT).
60
+ gsub(REPLACEMENTS, ESCAPES)
61
+ write(str)
62
+ end
63
+
64
+ # Emit interpolated segment
65
+ #
66
+ # @param [Parser::Node] node
67
+ #
68
+ # @return [undefined]
69
+ #
70
+ # @api private
71
+ #
72
+ def emit_interpolated_segment(node)
73
+ parentheses(OPEN, CLOSE) { visit(node) }
74
+ end
75
+
76
+ # Dynamic string body
77
+ class String < self
78
+
79
+ handle :dyn_str_body
80
+
81
+ DELIMITER = '"'.freeze
82
+ REPLACEMENT = '\"'.freeze
83
+
84
+ end # String
85
+
86
+ # Dynamic regexp body
87
+ class Regexp < self
88
+
89
+ handle :dyn_regexp_body
90
+
91
+ DELIMITER = '/'.freeze
92
+ REPLACEMENT = '/'.freeze
93
+
94
+ end # Regexp
95
+
96
+ # Dynamic regexp body
97
+ class ExecuteString < self
98
+
99
+ handle :dyn_xstr_body
100
+
101
+ DELIMITER = '`'.freeze
102
+ REPLACEMENT = '\`'.freeze
103
+
104
+ end # ExecuteString
105
+
106
+ end # DynamicBody
107
+ end # Literal
108
+ end # Emitter
109
+ end # Unparser
@@ -0,0 +1,38 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+ # Emitter for execute strings (xstr) nodes
5
+ class ExecuteString < self
6
+
7
+ OPEN = CLOSE = '`'.freeze
8
+
9
+ handle :xstr
10
+
11
+ private
12
+
13
+ # Perform dispatch
14
+ #
15
+ # @return [undefined]
16
+ #
17
+ # @api private
18
+ #
19
+ def dispatch
20
+ parentheses(OPEN, CLOSE) do
21
+ visit(dynamic_body)
22
+ end
23
+ end
24
+
25
+ # Return dynamic body
26
+ #
27
+ # @return [Parser::AST::Node]
28
+ #
29
+ # @api private
30
+ #
31
+ def dynamic_body
32
+ Parser::AST::Node.new(:dyn_xstr_body, children)
33
+ end
34
+
35
+ end # ExecuteString
36
+ end # Literal
37
+ end # Emitter
38
+ end # Unparser
@@ -0,0 +1,49 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+
5
+ # Base class for primitive emitters
6
+ class Primitive < self
7
+
8
+ children :value
9
+
10
+ private
11
+
12
+ # Dispatch node
13
+ #
14
+ # @return [undefined]
15
+ #
16
+ # @api private
17
+ #
18
+ def dispatch
19
+ if node.location
20
+ emit_source_map
21
+ else
22
+ dispatch_value
23
+ end
24
+ end
25
+
26
+ abstract_method :disaptch_value
27
+
28
+ # Emitter for primitives based on Object#inspect
29
+ class Inspect < self
30
+
31
+ handle :int, :str, :float, :sym
32
+
33
+ private
34
+
35
+ # Dispatch value
36
+ #
37
+ # @return [undefined]
38
+ #
39
+ # @api private
40
+ #
41
+ def dispatch_value
42
+ buffer.append(value.inspect)
43
+ end
44
+
45
+ end # Inspect
46
+ end # Primitive
47
+ end # Literal
48
+ end # Emitter
49
+ end # Unparser
@@ -0,0 +1,33 @@
1
+ module Unparser
2
+ class Emitter
3
+ class Literal
4
+ # Abstract base class for literal range emitter
5
+ class Range < self
6
+
7
+ TOKENS = IceNine.deep_freeze(
8
+ :irange => '..',
9
+ :erange => '...'
10
+ )
11
+
12
+ handle *TOKENS.keys
13
+
14
+ children :begin_node, :end_node
15
+
16
+ private
17
+
18
+ # Perform dispatch
19
+ #
20
+ # @return [undefined]
21
+ #
22
+ # @api private
23
+ #
24
+ def dispatch
25
+ visit(begin_node)
26
+ write(TOKENS.fetch(node.type))
27
+ visit(end_node)
28
+ end
29
+
30
+ end # Range
31
+ end # Literal
32
+ end # Emitter
33
+ end # Unparser