piggly 1.2.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +163 -0
  3. data/Rakefile +29 -15
  4. data/bin/piggly +4 -244
  5. data/lib/piggly.rb +19 -17
  6. data/lib/piggly/command.rb +9 -0
  7. data/lib/piggly/command/base.rb +148 -0
  8. data/lib/piggly/command/report.rb +162 -0
  9. data/lib/piggly/command/test.rb +157 -0
  10. data/lib/piggly/command/trace.rb +90 -0
  11. data/lib/piggly/command/untrace.rb +78 -0
  12. data/lib/piggly/compiler.rb +7 -5
  13. data/lib/piggly/compiler/cache_dir.rb +119 -0
  14. data/lib/piggly/compiler/coverage_report.rb +63 -0
  15. data/lib/piggly/compiler/trace_compiler.rb +105 -0
  16. data/lib/piggly/config.rb +47 -22
  17. data/lib/piggly/dumper.rb +9 -0
  18. data/lib/piggly/dumper/index.rb +121 -0
  19. data/lib/piggly/dumper/qualified_name.rb +36 -0
  20. data/lib/piggly/dumper/qualified_type.rb +81 -0
  21. data/lib/piggly/dumper/reified_procedure.rb +142 -0
  22. data/lib/piggly/dumper/skeleton_procedure.rb +102 -0
  23. data/lib/piggly/installer.rb +84 -42
  24. data/lib/piggly/parser.rb +43 -49
  25. data/lib/piggly/parser/grammar.tt +289 -313
  26. data/lib/piggly/parser/nodes.rb +270 -211
  27. data/lib/piggly/parser/traversal.rb +35 -33
  28. data/lib/piggly/parser/treetop_ruby19_patch.rb +1 -1
  29. data/lib/piggly/profile.rb +81 -60
  30. data/lib/piggly/reporter.rb +5 -18
  31. data/lib/piggly/reporter/base.rb +103 -0
  32. data/lib/piggly/reporter/html_dsl.rb +63 -0
  33. data/lib/piggly/reporter/index.rb +108 -0
  34. data/lib/piggly/reporter/procedure.rb +104 -0
  35. data/lib/piggly/reporter/resources/highlight.js +21 -0
  36. data/lib/piggly/reporter/{piggly.css → resources/piggly.css} +52 -12
  37. data/lib/piggly/reporter/{sortable.js → resources/sortable.js} +0 -0
  38. data/lib/piggly/tags.rb +280 -0
  39. data/lib/piggly/task.rb +191 -40
  40. data/lib/piggly/util.rb +8 -27
  41. data/lib/piggly/util/blankslate.rb +114 -0
  42. data/lib/piggly/util/cacheable.rb +19 -0
  43. data/lib/piggly/util/enumerable.rb +44 -0
  44. data/lib/piggly/util/file.rb +17 -0
  45. data/lib/piggly/util/process_queue.rb +96 -0
  46. data/lib/piggly/util/thunk.rb +39 -0
  47. data/lib/piggly/version.rb +8 -8
  48. data/spec/examples/compiler/cacheable_spec.rb +190 -0
  49. data/spec/examples/compiler/report_spec.rb +25 -0
  50. data/spec/{compiler → examples/compiler}/trace_spec.rb +7 -57
  51. data/spec/examples/config_spec.rb +61 -0
  52. data/spec/examples/dumper/index_spec.rb +197 -0
  53. data/spec/examples/dumper/procedure_spec.rb +116 -0
  54. data/spec/{grammar → examples/grammar}/expression_spec.rb +60 -60
  55. data/spec/{grammar → examples/grammar}/statements/assignment_spec.rb +15 -15
  56. data/spec/examples/grammar/statements/declaration_spec.rb +21 -0
  57. data/spec/{grammar → examples/grammar}/statements/exception_spec.rb +10 -10
  58. data/spec/{grammar → examples/grammar}/statements/if_spec.rb +47 -34
  59. data/spec/{grammar → examples/grammar}/statements/loop_spec.rb +5 -5
  60. data/spec/{grammar → examples/grammar}/statements/sql_spec.rb +11 -11
  61. data/spec/{grammar → examples/grammar}/tokens/comment_spec.rb +11 -11
  62. data/spec/{grammar → examples/grammar}/tokens/datatype_spec.rb +14 -8
  63. data/spec/{grammar → examples/grammar}/tokens/identifier_spec.rb +26 -10
  64. data/spec/{grammar → examples/grammar}/tokens/keyword_spec.rb +5 -5
  65. data/spec/{grammar → examples/grammar}/tokens/label_spec.rb +7 -7
  66. data/spec/{grammar → examples/grammar}/tokens/literal_spec.rb +1 -1
  67. data/spec/examples/grammar/tokens/lval_spec.rb +50 -0
  68. data/spec/{grammar → examples/grammar}/tokens/number_spec.rb +1 -1
  69. data/spec/{grammar → examples/grammar}/tokens/sqlkeywords_spec.rb +1 -1
  70. data/spec/{grammar → examples/grammar}/tokens/string_spec.rb +9 -9
  71. data/spec/{grammar → examples/grammar}/tokens/whitespace_spec.rb +1 -1
  72. data/spec/examples/installer_spec.rb +59 -0
  73. data/spec/examples/parser/nodes_spec.rb +73 -0
  74. data/spec/examples/parser/traversal_spec.rb +14 -0
  75. data/spec/examples/parser_spec.rb +115 -0
  76. data/spec/examples/profile_spec.rb +153 -0
  77. data/spec/{reporter/html_spec.rb → examples/reporter/html/dsl_spec.rb} +0 -0
  78. data/spec/examples/reporter/html/index_spec.rb +0 -0
  79. data/spec/examples/reporter/html_spec.rb +1 -0
  80. data/spec/examples/reporter_spec.rb +0 -0
  81. data/spec/{compiler → examples}/tags_spec.rb +10 -10
  82. data/spec/examples/task_spec.rb +0 -0
  83. data/spec/examples/util/cacheable_spec.rb +41 -0
  84. data/spec/examples/util/enumerable_spec.rb +64 -0
  85. data/spec/examples/util/file_spec.rb +40 -0
  86. data/spec/examples/util/process_queue_spec.rb +16 -0
  87. data/spec/examples/util/thunk_spec.rb +58 -0
  88. data/spec/examples/version_spec.rb +0 -0
  89. data/spec/issues/007_spec.rb +25 -0
  90. data/spec/issues/008_spec.rb +73 -0
  91. data/spec/issues/018_spec.rb +25 -0
  92. data/spec/spec_helper.rb +253 -9
  93. metadata +136 -93
  94. data/README.markdown +0 -116
  95. data/lib/piggly/compiler/cache.rb +0 -151
  96. data/lib/piggly/compiler/pretty.rb +0 -67
  97. data/lib/piggly/compiler/queue.rb +0 -46
  98. data/lib/piggly/compiler/tags.rb +0 -244
  99. data/lib/piggly/compiler/trace.rb +0 -91
  100. data/lib/piggly/filecache.rb +0 -40
  101. data/lib/piggly/parser/parser.rb +0 -11794
  102. data/lib/piggly/reporter/html.rb +0 -207
  103. data/spec/compiler/cache_spec.rb +0 -9
  104. data/spec/compiler/pretty_spec.rb +0 -9
  105. data/spec/compiler/queue_spec.rb +0 -3
  106. data/spec/compiler/rewrite_spec.rb +0 -3
  107. data/spec/config_spec.rb +0 -58
  108. data/spec/filecache_spec.rb +0 -70
  109. data/spec/fixtures/snippets.sql +0 -158
  110. data/spec/grammar/tokens/lval_spec.rb +0 -50
  111. data/spec/parser_spec.rb +0 -8
  112. data/spec/profile_spec.rb +0 -5
@@ -1,9 +1,7 @@
1
- require File.join(File.dirname(__FILE__), 'traversal')
2
-
3
1
  NodeClass = Treetop::Runtime::SyntaxNode
4
2
 
5
3
  class NodeClass
6
- include Piggly::NodeTraversal
4
+ include Piggly::Parser::Traversal
7
5
 
8
6
  # The 'text_value' method can be used to read the parse tree as Treetop
9
7
  # originally read it. The 'source_text' method returns redefined value or falls
@@ -11,11 +9,6 @@ class NodeClass
11
9
 
12
10
  attr_accessor :source_text
13
11
 
14
- def value
15
- puts "NodeClass#value is deprecated: #{caller.first}"
16
- text_value
17
- end
18
-
19
12
  def source_text
20
13
  @source_text || text_value
21
14
  end
@@ -29,9 +22,9 @@ class NodeClass
29
22
  def tag(prefix = nil, id = nil)
30
23
  unless defined? @tag_id
31
24
  if named?(:body)
32
- Piggly::BlockTag.new(prefix, id)
25
+ Piggly::Tags::BlockTag.new(prefix, id)
33
26
  else
34
- Piggly::EvaluationTag.new(prefix, id)
27
+ Piggly::Tags::EvaluationTag.new(prefix, id)
35
28
  end.tap{|tag| @tag_id = tag.id }
36
29
  end
37
30
  end
@@ -41,7 +34,7 @@ class NodeClass
41
34
  end
42
35
 
43
36
  def tagged?
44
- not @tag_id.nil?
37
+ defined? @tag_id
45
38
  end
46
39
 
47
40
  # overridden in subclasses
@@ -51,38 +44,31 @@ class NodeClass
51
44
  def stub?; false end
52
45
  def loop?; false end
53
46
  def for?; false end
47
+ def while?; false end
54
48
  def style; nil end
49
+ def comment?; false end
50
+ def whitespace?; false end
51
+ def token?; false end
52
+ def string?; false end
53
+ def datatype?; false end
54
+ def identifier?; false end
55
+ def assignment?; false end
56
+ def sql?; false end
57
+ def statement?; false; end
58
+ def if?; false; end
59
+ def else?; false; end
60
+ def label?; false; end
61
+ def keyword?; false; end
55
62
 
56
63
  def indent(method = nil)
57
64
  if method and respond_to?(method)
58
65
  send(method).text_value[/\n[\t ]*\z/]
59
66
  else
60
67
  text_value[/\n[\t ]*\z/]
61
- end
68
+ end || ""
62
69
  end
63
70
 
64
- alias o_inspect inspect
65
-
66
- def inspect(indent = '')
67
- if terminal?
68
- em = extension_modules
69
- interesting_methods = methods-[em.last ? em.last.methods : nil]-self.class.instance_methods
70
- im = interesting_methods.size > 0 ? " (#{interesting_methods.join(",")})" : ""
71
- tv = text_value
72
- tv = "...#{tv[-20..-1]}" if tv.size > 20
73
-
74
- indent +
75
- self.class.to_s.sub(/.*:/,'') +
76
- em.map{|m| "+"+m.to_s.sub(/.*:/,'')}*"" +
77
- " offset=#{interval.first}" +
78
- ", #{tv.inspect}" +
79
- im
80
- else
81
- o_inspect(indent)
82
- end
83
- end
84
-
85
- # true if node is called 'label' in parent node
71
+ # True if node is called `label` by the parent node
86
72
  def named?(label)
87
73
  if p = parent
88
74
  p.respond_to?(label) and p.send(label).equal?(self)
@@ -91,229 +77,302 @@ class NodeClass
91
77
  end
92
78
 
93
79
  module Piggly
80
+ module Parser
81
+ module Nodes
82
+
83
+ # ...;
84
+ class Statement < NodeClass
85
+ def statement?
86
+ true
87
+ end
88
+
89
+ def terminal?
90
+ false
91
+ end
92
+ end
94
93
 
95
- # CREATE OR REPLACE ...
96
- class Procedure < NodeClass
97
- end
94
+ class Expression < NodeClass
95
+ def expression?
96
+ true
97
+ end
98
+
99
+ def tag(prefix = nil, id = nil)
100
+ unless defined? @tag_id
101
+ if named?(:cond)
102
+ if parent.while?
103
+ # This node is the conditional in a WHILE loop
104
+ Tags::ConditionalLoopTag.new(prefix, id)
105
+ elsif parent.loop?
106
+ # This node is the conditional in a loop
107
+ Tags::UnconditionalLoopTag.new(prefix, id)
108
+ elsif parent.branch?
109
+ # This node is a conditional in a branch
110
+ Tags::ConditionalBranchTag.new(prefix, id)
111
+ else
112
+ Tags::EvaluationTag.new(prefix, id)
113
+ end
114
+ else
115
+ Tags::EvaluationTag.new(prefix, id)
116
+ end.tap{|tag| @tag_id = tag.id }
117
+ end
118
+ end
98
119
 
99
- # ...;
100
- class Statement < NodeClass
101
- end
120
+ def terminal?
121
+ false
122
+ end
123
+ end
102
124
 
103
- class Expression < NodeClass
104
- def expression?
105
- true
106
- end
125
+ # DECLARE declaration BEGIN body END;
126
+ class Block < Statement
127
+ def block?
128
+ true
129
+ end
130
+ end
107
131
 
108
- def tag(prefix = nil, id = nil)
109
- unless defined? @tag_id
110
- if named?(:cond)
111
- if parent.for?
112
- # this object is the conditional statement in a FOR loop
113
- Piggly::ForCollectionTag.new(prefix, id)
114
- elsif parent.loop?
115
- # this object is the conditional statement in a WHILE loop
116
- Piggly::LoopConditionTag.new(prefix, id)
117
- elsif parent.branch?
118
- Piggly::BranchConditionTag.new(prefix, id)
119
- end
120
- else
121
- Piggly::Evaluation.new(prefix, id)
122
- end.tap{|tag| @tag_id = tag.id }
132
+ # Branches with child 'cond' (Expression) will get a ConditionalBranchTag
133
+ class Branch < Statement
134
+ def branch?
135
+ true
136
+ end
123
137
  end
124
- end
125
- end
126
138
 
127
- # DECLARE declaration BEGIN body END;
128
- class Block < Statement
129
- def block?
130
- true
131
- end
132
- end
139
+ # IF boolean-cond THEN body
140
+ class If < Branch
141
+ def if?
142
+ true
143
+ end
133
144
 
134
- # Branches with child 'cond' (Expression) will get a BranchCondTag
135
- class Branch < Statement
136
- def branch?
137
- true
138
- end
139
- end
145
+ def terminal?
146
+ false
147
+ end
148
+ end
140
149
 
141
- # IF boolean-cond THEN body
142
- class If < Branch
143
- end
150
+ # ELSE body END
151
+ class Else < NodeClass
152
+ def else?
153
+ true
154
+ end
144
155
 
145
- # ELSE body END
146
- class Else < NodeClass
147
- end
156
+ def terminal?
157
+ false
158
+ end
159
+ end
148
160
 
149
- # EXCEPTION WHEN boolean-cond THEN body
150
- class Catch < Branch
151
- end
161
+ # EXCEPTION WHEN boolean-cond THEN body
162
+ class Catch < Branch
163
+ end
152
164
 
153
- # WHEN match-expr THEN body
154
- class CaseWhen < Branch
155
- end
165
+ # WHEN match-expr THEN body
166
+ class CaseWhen < Branch
167
+ end
156
168
 
157
- # WHEN boolean-cond THEN body
158
- class CondWhen < Branch
159
- end
169
+ # WHEN boolean-cond THEN body
170
+ class CondWhen < Branch
171
+ end
160
172
 
161
- # CONTINUE label WHEN boolean-cond;
162
- class ContinueWhen < Branch
163
- end
173
+ # CONTINUE label WHEN boolean-cond;
174
+ class ContinueWhen < Branch
175
+ end
164
176
 
165
- # EXIT label WHEN boolean-cond;
166
- class ExitWhen < Branch
167
- end
177
+ # EXIT label WHEN boolean-cond;
178
+ class ExitWhen < Branch
179
+ end
168
180
 
169
- class UnconditionalBranch < Statement
170
- end
181
+ class UnconditionalBranch < Statement
182
+ end
171
183
 
172
- # RETURN expr
173
- class Return < UnconditionalBranch
174
- end
184
+ # RETURN expr
185
+ class Return < UnconditionalBranch
186
+ end
175
187
 
176
- # EXIT label
177
- class Exit < UnconditionalBranch
178
- end
188
+ # EXIT label
189
+ class Exit < UnconditionalBranch
190
+ end
179
191
 
180
- # CONTINUE label
181
- class Continue < UnconditionalBranch
182
- end
192
+ # CONTINUE label
193
+ class Continue < UnconditionalBranch
194
+ end
183
195
 
184
- # RAISE EXCEPTION expr
185
- class Throw < UnconditionalBranch
186
- end
196
+ # RAISE EXCEPTION expr
197
+ class Throw < UnconditionalBranch
198
+ end
187
199
 
188
- # Loops with child 'cond' (Expression/Sql) will get a LoopCondTag
189
- class Loop < Statement
190
- def loop?
191
- true
192
- end
193
- end
200
+ # Loops that have a child named :cond (which should be either an Expression
201
+ # or Sql node) will get a LoopCondTag from the #tag method
202
+ class Loop < Statement
203
+ def loop?
204
+ true
205
+ end
206
+ end
194
207
 
195
- # FOR boolean-cond LOOP body END
196
- class ForLoop < Loop
197
- def for?; true end
198
- end
208
+ # FOR var IN expr LOOP body END
209
+ class ForLoop < Loop
210
+ def for?
211
+ true
212
+ end
213
+ end
199
214
 
200
- # WHILE boolean-cond LOOP body END
201
- class WhileLoop < Loop
202
- end
215
+ # FOREACH var IN ARRAY expr LOOP body END
216
+ class ForEachLoop < Loop
217
+ def for?
218
+ true
219
+ end
220
+ end
203
221
 
222
+ # WHILE boolean-cond LOOP body END
223
+ class WhileLoop < Loop
224
+ def while?
225
+ true
226
+ end
227
+ end
204
228
 
205
- # RAISE NOTICE expr
206
- class Raise < Statement
207
- end
208
229
 
209
- # CASE search-expr WHEN ...
210
- class Case < Statement
211
- end
230
+ # RAISE NOTICE expr
231
+ class Raise < Statement
232
+ end
212
233
 
213
- # CASE WHEN ...
214
- class Cond < Statement
215
- end
234
+ # CASE search-expr WHEN ...
235
+ class Case < Statement
236
+ end
216
237
 
217
- # lval := rval
218
- class Assignment < Statement
219
- end
238
+ # CASE WHEN ...
239
+ class Cond < Statement
240
+ end
220
241
 
221
- # Lval of assignment (rval is an Expression)
222
- class Assignable < NodeClass
223
- end
242
+ # lval := rval
243
+ class Assignment < Statement
244
+ def assignment?
245
+ true
246
+ end
247
+ end
224
248
 
225
- class Sql < Statement
226
- def style; 'tQ'; end
249
+ # Lval of assignment (rval is an Expression)
250
+ class Assignable < NodeClass
251
+ end
227
252
 
228
- def tag(prefix = nil, id = nil)
229
- unless defined? @tag_id
230
- if named?(:cond) and parent.for?
231
- # this object is the conditional statement in a FOR loop
232
- Piggly::ForCollectionTag.new(prefix, id)
233
- else
234
- Piggly::EvaluationTag.new(prefix, id)
235
- end.tap{|tag| @tag_id = tag.id }
253
+ class Sql < Expression
254
+ def style; "tQ"; end
255
+
256
+ def sql?
257
+ true
258
+ end
259
+
260
+ def tag(prefix = nil, id = nil)
261
+ unless defined? @tag_id
262
+ if named?(:cond) and parent.for?
263
+ # This node is the conditional in a FOR loop
264
+ Tags::UnconditionalLoopTag.new(prefix, id)
265
+ else
266
+ Tags::EvaluationTag.new(prefix, id)
267
+ end.tap{|tag| @tag_id = tag.id }
268
+ end
269
+ end
236
270
  end
237
- end
238
- end
239
271
 
240
- # Tokens have no children
241
- class Token < NodeClass
242
- def initialize(input, interval, elements = nil)
243
- # prevent children from being assigned
244
- super(input, interval, nil)
245
- end
272
+ # Terminals have no children
273
+ class Terminal < NodeClass
274
+ def initialize(input, interval, elements = nil)
275
+ # Third argument nil prevents children from being assigned
276
+ super(input, interval, nil)
277
+ end
246
278
 
247
- def terminal?
248
- true
249
- end
250
- end
279
+ def terminal?
280
+ true
281
+ end
282
+ end
251
283
 
252
- # This seems like it should be a Token, but it may contain TComment children
253
- # that should be highlighted differently than the enclosing whitespace
254
- class TWhitespace < NodeClass
255
- end
284
+ # This seems like it should be a Token, but it may contain TComment children
285
+ # that should be highlighted differently than the enclosing whitespace
286
+ class TWhitespace < NodeClass
287
+ def terminal?
288
+ false
289
+ end
256
290
 
257
- class TKeyword < Token
258
- def style; 'tK'; end
259
- end
291
+ def whitespace?
292
+ true
293
+ end
294
+ end
260
295
 
261
- class TIdentifier < Token
262
- def style; 'tI'; end
263
- end
296
+ class Token < Terminal
297
+ def token?
298
+ true
299
+ end
300
+ end
264
301
 
265
- class TDatatype < Token
266
- def style; 'tD'; end
267
- end
302
+ class TKeyword < Token
303
+ def style; "tK"; end
304
+
305
+ def keyword?
306
+ true
307
+ end
308
+
309
+ def tag(prefix = nil, id = nil)
310
+ unless defined? @tag_id
311
+ if named?(:cond) and parent.loop?
312
+ Tags::UnconditionalLoopTag.new(prefix, id)
313
+ else
314
+ Tags::EvaluationTag.new(prefix, id)
315
+ end
316
+ end.tap{|tag| @tag_id = tag.id }
317
+ end
318
+ end
268
319
 
269
- class TString < Token
270
- def style; 'tS'; end
271
- end
320
+ class TIdentifier < Token
321
+ def style; "tI"; end
322
+ def identifier?
323
+ true
324
+ end
325
+ end
272
326
 
273
- class TDollarQuoteMarker < Token
274
- def style; 'tM'; end
275
- end
327
+ class TDatatype < Token
328
+ def style; "tD"; end
329
+ def datatype?
330
+ true
331
+ end
332
+ end
276
333
 
277
- class TComment < Token
278
- def style; 'tC'; end
279
- end
334
+ class TString < Token
335
+ def style; "tS"; end
336
+ def string?
337
+ true
338
+ end
339
+ end
280
340
 
281
- class TLabel < Token
282
- def style; 'tL'; end
283
- end
341
+ class TDollarQuoteMarker < Token
342
+ def style; "tM"; end
343
+ end
284
344
 
285
- # Text nodes have no children
286
- class TextNode < NodeClass
287
- def initialize(input, interval, elements = nil)
288
- # prevent children from being assigned
289
- super(input, interval, nil)
290
- end
345
+ class TComment < Token
346
+ def style; "tC"; end
347
+ def comment?
348
+ true
349
+ end
350
+ end
291
351
 
292
- def terminal?
293
- true
294
- end
295
- end
296
-
297
- # Stub nodes have no children, or content
298
- class StubNode < NodeClass
299
- def initialize(input, interval, elements = nil)
300
- # prevent children from being assigned
301
- super(input, interval, nil)
302
- end
352
+ class TLabel < Token
353
+ def style; "tL"; end
354
+ def label?
355
+ true
356
+ end
357
+ end
303
358
 
304
- def terminal?
305
- true
306
- end
359
+ class TextNode < Terminal
360
+ end
361
+
362
+ # Stub nodes have no children, or content
363
+ class StubNode < Terminal
364
+ def stub?
365
+ true
366
+ end
367
+ end
307
368
 
308
- def stub?
309
- true
310
- end
311
- end
369
+ class NotImplemented < NodeClass
370
+ def parent=(object)
371
+ # this would go in the constructor, but parent is set from outside
372
+ raise Failure, "Grammar does not implement #{object.source_text} at line #{input.line_of(object.interval.first)}"
373
+ end
374
+ end
312
375
 
313
- class NotImplemented < NodeClass
314
- def parent=(object)
315
- # this would go in the constructor, but parent is set from outside
316
- raise Piggly::Parser::Failure, "Grammar does not implement #{object.source_text} at line #{input.line_of(object.interval.first)}"
317
376
  end
318
377
  end
319
378
  end