alf 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. data/CHANGELOG.md +89 -0
  2. data/Gemfile.lock +6 -1
  3. data/README.md +35 -21
  4. data/TODO.md +0 -5
  5. data/alf.gemspec +2 -0
  6. data/alf.noespec +6 -4
  7. data/bin/alf +9 -13
  8. data/examples/{autonum.alf → operators/autonum.alf} +0 -0
  9. data/examples/{cities.rash → operators/cities.rash} +0 -0
  10. data/examples/{clip.alf → operators/clip.alf} +0 -0
  11. data/examples/{compact.alf → operators/compact.alf} +0 -0
  12. data/examples/{database.alf → operators/database.alf} +1 -1
  13. data/examples/{defaults.alf → operators/defaults.alf} +0 -0
  14. data/examples/{extend.alf → operators/extend.alf} +0 -0
  15. data/examples/{group.alf → operators/group.alf} +0 -0
  16. data/examples/{intersect.alf → operators/intersect.alf} +0 -0
  17. data/examples/{join.alf → operators/join.alf} +0 -0
  18. data/examples/operators/matching.alf +2 -0
  19. data/examples/{minus.alf → operators/minus.alf} +0 -0
  20. data/examples/operators/not_matching.alf +2 -0
  21. data/examples/{nulls.rash → operators/nulls.rash} +0 -0
  22. data/examples/{parts.rash → operators/parts.rash} +0 -0
  23. data/examples/{project.alf → operators/project.alf} +0 -0
  24. data/examples/{pseudo-with.alf → operators/pseudo-with.alf} +0 -0
  25. data/examples/{quota.alf → operators/quota.alf} +0 -0
  26. data/examples/operators/rank.alf +4 -0
  27. data/examples/{rename.alf → operators/rename.alf} +0 -0
  28. data/examples/{restrict.alf → operators/restrict.alf} +0 -0
  29. data/examples/{schema.yaml → operators/schema.yaml} +0 -0
  30. data/examples/{sort.alf → operators/sort.alf} +0 -0
  31. data/examples/{summarize.alf → operators/summarize.alf} +0 -0
  32. data/examples/{suppliers.rash → operators/suppliers.rash} +0 -0
  33. data/examples/{supplies.rash → operators/supplies.rash} +0 -0
  34. data/examples/{ungroup.alf → operators/ungroup.alf} +0 -0
  35. data/examples/{union.alf → operators/union.alf} +0 -0
  36. data/examples/{unwrap.alf → operators/unwrap.alf} +0 -0
  37. data/examples/{wrap.alf → operators/wrap.alf} +0 -0
  38. data/lib/alf.rb +837 -62
  39. data/lib/alf/loader.rb +2 -1
  40. data/lib/alf/text.rb +160 -0
  41. data/lib/alf/version.rb +1 -1
  42. data/lib/alf/yaml.rb +24 -0
  43. data/spec/integration/__database__/group.alf +3 -0
  44. data/spec/integration/__database__/parts.rash +6 -0
  45. data/spec/integration/__database__/suppliers.rash +5 -0
  46. data/spec/integration/__database__/supplies.rash +12 -0
  47. data/spec/integration/command/alf/alf_e.cmd +1 -0
  48. data/spec/integration/command/alf/alf_e.stdout +4 -0
  49. data/spec/integration/command/alf/alf_env.cmd +1 -0
  50. data/spec/integration/command/alf/alf_env.stdout +5 -0
  51. data/spec/integration/command/alf/alf_implicit.alf +1 -0
  52. data/spec/integration/command/alf/alf_implicit_exec.cmd +1 -0
  53. data/spec/integration/command/alf/alf_implicit_exec.stdout +4 -0
  54. data/spec/integration/command/alf/alf_r.cmd +1 -0
  55. data/spec/integration/command/alf/alf_r.stdout +5 -0
  56. data/spec/integration/command/alf/alf_version.cmd +1 -0
  57. data/spec/integration/command/alf/alf_version.stdout +2 -0
  58. data/spec/integration/command/alf/alf_yaml.cmd +1 -0
  59. data/spec/integration/command/alf/alf_yaml.stdout +22 -0
  60. data/spec/integration/command/alf/rel.rash +1 -0
  61. data/spec/integration/command/autonum/autonum_0.cmd +1 -0
  62. data/spec/integration/command/autonum/autonum_0.stdout +9 -0
  63. data/spec/integration/command/autonum/autonum_1.cmd +1 -0
  64. data/spec/integration/command/autonum/autonum_1.stdout +9 -0
  65. data/spec/integration/command/clip/clip_0.cmd +1 -0
  66. data/spec/integration/command/clip/clip_0.stdout +9 -0
  67. data/spec/integration/command/clip/clip_1.cmd +1 -0
  68. data/spec/integration/command/clip/clip_1.stdout +9 -0
  69. data/spec/integration/command/compact/compact_0.cmd +1 -0
  70. data/spec/integration/command/compact/compact_0.stdout +9 -0
  71. data/spec/integration/command/defaults/defaults_0.cmd +1 -0
  72. data/spec/integration/command/defaults/defaults_0.stdout +9 -0
  73. data/spec/integration/command/defaults/defaults_1.cmd +1 -0
  74. data/spec/integration/command/defaults/defaults_1.stdout +9 -0
  75. data/spec/integration/command/extend/extend_0.cmd +1 -0
  76. data/spec/integration/command/extend/extend_0.stdout +16 -0
  77. data/spec/integration/command/group/group_0.cmd +1 -0
  78. data/spec/integration/command/group/group_0.stdout +32 -0
  79. data/spec/integration/command/group/group_1.cmd +1 -0
  80. data/spec/integration/command/group/group_1.stdout +32 -0
  81. data/spec/integration/command/intersect/intersect_0.cmd +1 -0
  82. data/spec/integration/command/intersect/intersect_0.stdout +9 -0
  83. data/spec/integration/command/join/join_0.cmd +1 -0
  84. data/spec/integration/command/join/join_0.stdout +16 -0
  85. data/spec/integration/command/matching/matching_0.cmd +1 -0
  86. data/spec/integration/command/matching/matching_0.stdout +8 -0
  87. data/spec/integration/command/minus/minus_0.cmd +1 -0
  88. data/spec/integration/command/minus/minus_0.stdout +4 -0
  89. data/spec/integration/command/not-matching/not-matching_0.cmd +1 -0
  90. data/spec/integration/command/not-matching/not-matching_0.stdout +5 -0
  91. data/spec/integration/command/project/project_0.cmd +1 -0
  92. data/spec/integration/command/project/project_0.stdout +9 -0
  93. data/spec/integration/command/project/project_1.cmd +1 -0
  94. data/spec/integration/command/project/project_1.stdout +9 -0
  95. data/spec/integration/command/quota/quota_0.cmd +1 -0
  96. data/spec/integration/command/quota/quota_0.stdout +16 -0
  97. data/spec/integration/command/rank/rank_1.cmd +1 -0
  98. data/spec/integration/command/rank/rank_1.stdout +10 -0
  99. data/spec/integration/command/rank/rank_2.cmd +1 -0
  100. data/spec/integration/command/rank/rank_2.stdout +10 -0
  101. data/spec/integration/command/rank/rank_3.cmd +1 -0
  102. data/spec/integration/command/rank/rank_3.stdout +10 -0
  103. data/spec/integration/command/rank/rank_4.cmd +1 -0
  104. data/spec/integration/command/rank/rank_4.stdout +6 -0
  105. data/spec/integration/command/rank/rank_5.cmd +1 -0
  106. data/spec/integration/command/rank/rank_5.stdout +6 -0
  107. data/spec/integration/command/rename/rename_0.cmd +1 -0
  108. data/spec/integration/command/rename/rename_0.stdout +9 -0
  109. data/spec/integration/command/restrict/restrict_0.cmd +1 -0
  110. data/spec/integration/command/restrict/restrict_0.stdout +6 -0
  111. data/spec/integration/command/restrict/restrict_1.cmd +1 -0
  112. data/spec/integration/command/restrict/restrict_1.stdout +6 -0
  113. data/spec/integration/command/show/show_base.cmd +1 -0
  114. data/spec/integration/command/show/show_base.stdout +9 -0
  115. data/spec/integration/command/show/show_conflictual.cmd +1 -0
  116. data/spec/integration/command/show/show_conflictual.stdout +5 -0
  117. data/spec/integration/command/show/show_rash.cmd +1 -0
  118. data/spec/integration/command/show/show_rash.stdout +5 -0
  119. data/spec/integration/command/show/show_rash_2.cmd +1 -0
  120. data/spec/integration/command/show/show_rash_2.stdout +5 -0
  121. data/spec/integration/command/show/show_yaml.cmd +1 -0
  122. data/spec/integration/command/show/show_yaml.stdout +22 -0
  123. data/spec/integration/command/sort/sort_0.cmd +1 -0
  124. data/spec/integration/command/sort/sort_0.stdout +9 -0
  125. data/spec/integration/command/sort/sort_1.cmd +1 -0
  126. data/spec/integration/command/sort/sort_1.stdout +9 -0
  127. data/spec/integration/command/summarize/summarize_0.cmd +1 -0
  128. data/spec/integration/command/summarize/summarize_0.stdout +8 -0
  129. data/spec/integration/command/ungroup/ungroup_0.cmd +1 -0
  130. data/spec/integration/command/ungroup/ungroup_0.stdout +16 -0
  131. data/spec/integration/command/union/union_0.cmd +1 -0
  132. data/spec/integration/command/union/union_0.stdout +9 -0
  133. data/spec/integration/command/unwrap/unwrap_0.cmd +1 -0
  134. data/spec/integration/command/unwrap/unwrap_0.stdout +9 -0
  135. data/spec/integration/command/wrap/wrap_0.cmd +1 -0
  136. data/spec/integration/command/wrap/wrap_0.stdout +9 -0
  137. data/spec/integration/semantics/test_join.alf +9 -0
  138. data/spec/integration/{src → semantics}/test_minus.alf +0 -0
  139. data/spec/integration/{src → semantics}/test_project.alf +0 -0
  140. data/spec/integration/semantics/test_rank.alf +34 -0
  141. data/spec/integration/test_command.rb +36 -0
  142. data/spec/integration/test_examples.rb +11 -22
  143. data/spec/integration/test_semantics.rb +40 -0
  144. data/spec/regression/alf_file/__FILE__.alf +2 -0
  145. data/spec/regression/alf_file/suppliers.rash +5 -0
  146. data/spec/regression/alf_file/test___FILE__.rb +17 -0
  147. data/spec/regression/heading/test_heading_with_date.rb +12 -0
  148. data/spec/regression/lispy/test_compile.rb +14 -0
  149. data/spec/regression/relation/test_relation_with_date.rb +12 -0
  150. data/spec/regression/restrict/test_restrict_with_keywords.rb +17 -0
  151. data/spec/shared/a_value.rb +12 -0
  152. data/spec/shared/an_operator_class.rb +35 -0
  153. data/spec/spec_helper.rb +12 -34
  154. data/spec/unit/assumptions/test_file.rb +17 -0
  155. data/spec/unit/{test_assumptions.rb → assumptions/test_instance_eval.rb} +1 -1
  156. data/spec/unit/assumptions/test_scoping.rb +29 -0
  157. data/spec/unit/environment/test_folder.rb +6 -1
  158. data/spec/unit/operator/relational/matching/test_hash_based.rb +60 -0
  159. data/spec/unit/operator/relational/not_matching/test_hash_based.rb +37 -0
  160. data/spec/unit/operator/relational/test_rank.rb +50 -0
  161. data/spec/unit/operator/test_relational.rb +3 -0
  162. data/spec/unit/reader/test_alf_file.rb +7 -4
  163. data/spec/unit/reader/test_initialize.rb +60 -0
  164. data/spec/unit/relation/test_relops.rb +4 -0
  165. data/spec/unit/relation/test_to_a.rb +41 -0
  166. data/spec/unit/renderer/test_initialize.rb +60 -0
  167. data/spec/unit/test_environment.rb +38 -0
  168. data/spec/unit/test_heading.rb +38 -0
  169. data/spec/unit/test_reader.rb +5 -0
  170. data/spec/unit/test_relation.rb +31 -1
  171. data/spec/unit/test_renderer.rb +1 -1
  172. data/spec/unit/{renderer/text → text}/test_cell.rb +1 -1
  173. data/spec/unit/{renderer/text → text}/test_row.rb +1 -1
  174. data/spec/unit/{renderer/text → text}/test_table.rb +1 -1
  175. data/spec/unit/tools/test_ordering_key.rb +13 -0
  176. data/spec/unit/tools/test_parse_commandline_args.rb +47 -0
  177. data/spec/unit/tools/test_tuple_handle.rb +34 -2
  178. data/spec/unit/tools/test_varargs.rb +16 -0
  179. data/tasks/{spec_test.rake → integration_test.rake} +4 -32
  180. data/tasks/regression_test.rake +52 -0
  181. data/tasks/unit_test.rake +33 -58
  182. metadata +326 -66
  183. data/examples/runall.sh +0 -26
  184. data/lib/alf/relation.rb +0 -118
  185. data/lib/alf/renderer/text.rb +0 -153
  186. data/lib/alf/renderer/yaml.rb +0 -22
  187. data/spec/integration/test_alf_specs.rb +0 -37
data/examples/runall.sh DELETED
@@ -1,26 +0,0 @@
1
- alf --text autonum suppliers
2
- alf --text autonum suppliers -- unique_id
3
- alf --text defaults suppliers -- country "'Belgium'"
4
- alf --text defaults --strict suppliers -- country "'Belgium'"
5
- alf --text compact suppliers
6
- alf --text sort suppliers -- name asc
7
- alf --text sort suppliers -- city desc name asc
8
- alf --text clip suppliers -- name city
9
- alf --text clip suppliers --allbut -- name city
10
- alf --text project suppliers -- name city
11
- alf --text project --allbut suppliers -- name city
12
- alf --text extend supplies -- sp 'sid + "/" + pid' big "qty > 100 ? true : false"
13
- alf --text rename suppliers -- name supplier_name city supplier_city
14
- alf --text restrict suppliers -- "status > 20"
15
- alf --text restrict suppliers -- city "'London'"
16
- alf --text wrap suppliers -- city status loc_and_status
17
- alf --text unwrap suppliers -- loc_and_status
18
- alf --text group supplies -- pid qty supplying
19
- alf --text group --allbut supplies -- sid supplying
20
- alf --text ungroup group -- supplying
21
- alf --text summarize supplies -- --by=sid total_qty "sum(:qty)"
22
- alf --text quota supplies -- --by=sid --order=qty position count sum_qty "sum(:qty)"
23
- alf --text join suppliers supplies
24
- alf --text union suppliers suppliers
25
- alf --text intersect suppliers suppliers
26
- alf --text minus suppliers suppliers
data/lib/alf/relation.rb DELETED
@@ -1,118 +0,0 @@
1
- module Alf
2
- #
3
- # Defines an in-memory relation
4
- #
5
- class Relation
6
- include Iterator
7
-
8
- protected
9
-
10
- # @return [Set] the set of tuples
11
- attr_reader :tuples
12
-
13
- public
14
-
15
- #
16
- # Creates a Relation instance.
17
- #
18
- # @param [Set] tuples a set of tuples
19
- #
20
- def initialize(tuples)
21
- raise ArgumentError unless tuples.is_a?(Set)
22
- @tuples = tuples
23
- end
24
-
25
- #
26
- # Coerces `val` to a relation
27
- #
28
- def self.coerce(val)
29
- case val
30
- when Relation
31
- val
32
- when Set
33
- Relation.new(val)
34
- when Array
35
- Relation.new val.to_set
36
- when Iterator
37
- Relation.new val.to_set
38
- else
39
- raise ArgumentError, "Unable to coerce #{val} to a Relation"
40
- end
41
- end
42
-
43
- # (see Relation.coerce)
44
- def self.[](*tuples)
45
- coerce(tuples)
46
- end
47
-
48
- #
49
- # (see Iterator#each)
50
- #
51
- def each(&block)
52
- tuples.each(&block)
53
- end
54
-
55
- #
56
- # Returns relation's cardinality (number of tuples)
57
- #
58
- def cardinality
59
- tuples.size
60
- end
61
- alias :size :cardinality
62
- alias :count :cardinality
63
-
64
- #
65
- # Install the DSL through iteration over defined operators
66
- #
67
- Operator::each do |op_class|
68
- meth_name = Tools.ruby_case(Tools.class_name(op_class)).to_sym
69
- if op_class.unary?
70
- define_method(meth_name) do |*args|
71
- op = op_class.new(*args).pipe(self)
72
- Relation.coerce(op)
73
- end
74
- elsif op_class.binary?
75
- define_method(meth_name) do |right, *args|
76
- op = op_class.new(*args).pipe([self, Iterator.coerce(right)])
77
- Relation.coerce(op)
78
- end
79
- else
80
- raise "Unexpected operator #{op_class}"
81
- end
82
- end # Operators::each
83
-
84
- alias :+ :union
85
- alias :- :minus
86
-
87
- #
88
- # (see Object#hash)
89
- #
90
- def hash
91
- @tuples.hash
92
- end
93
-
94
- #
95
- # (see Object#==)
96
- #
97
- def ==(other)
98
- return nil unless other.is_a?(Relation)
99
- other.tuples == self.tuples
100
- end
101
- alias :eql? :==
102
-
103
- #
104
- # Returns a textual representation of this relation
105
- #
106
- def to_s
107
- Alf::Renderer.text(self).execute("")
108
- end
109
-
110
- #
111
- # Returns a literal representation of this relation
112
- #
113
- def inspect
114
- "Alf::Relation[" << @tuples.collect{|t| t.inspect}.join(',') << "]"
115
- end
116
-
117
- end # class Relation
118
- end # module Alf
@@ -1,153 +0,0 @@
1
- class Alf::Renderer
2
- class Text < Alf::Renderer
3
-
4
- module Utils
5
-
6
- def looks_a_relation?(value)
7
- value.is_a?(Alf::Iterator) or
8
- (value.is_a?(Array) && !value.empty? && value.all?{|v| v.is_a?(Hash)})
9
- end
10
-
11
- def max(x, y)
12
- return y if x.nil?
13
- return x if y.nil?
14
- x > y ? x : y
15
- end
16
-
17
- end
18
- include Utils
19
-
20
- class Cell
21
- include Utils
22
-
23
- def initialize(value)
24
- @value = value
25
- end
26
-
27
- def min_width
28
- @min_width ||= rendering_lines.inject(0) do |maxl,line|
29
- max(maxl,line.size)
30
- end
31
- end
32
-
33
- def rendering_lines(size = nil)
34
- if size.nil?
35
- text_rendering.split(/\n/)
36
- elsif @value.is_a?(Numeric)
37
- rendering_lines(nil).collect{|l| "%#{size}s" % l}
38
- else
39
- rendering_lines(nil).collect{|l| "%-#{size}s" % l}
40
- end
41
- end
42
-
43
- def text_rendering
44
- @text_rendering ||= case (value = @value)
45
- when NilClass
46
- "[nil]"
47
- when Symbol
48
- value.inspect
49
- when Float
50
- "%.7f" % value
51
- when Hash
52
- value.inspect
53
- when Alf::Iterator
54
- Text.render(value, "")
55
- when Array
56
- array_rendering(value)
57
- else
58
- value.to_s
59
- end
60
- end
61
-
62
- def array_rendering(value)
63
- if looks_a_relation?(value)
64
- Text.render(value, "")
65
- elsif value.empty?
66
- "[]"
67
- else
68
- values = value.collect{|x| Cell.new(x).text_rendering}
69
- if values.inject(0){|memo,s| memo + s.size} < 20
70
- "[" + values.join(", ") + "]"
71
- else
72
- "[" + values.join(",\n ") + "]"
73
- end
74
- end
75
- end
76
-
77
- end # class Cell
78
-
79
- class Row
80
- include Utils
81
-
82
- def initialize(values)
83
- @cells = values.collect{|v| Cell.new(v)}
84
- end
85
-
86
- def min_widths
87
- @cells.collect{|cell| cell.min_width}
88
- end
89
-
90
- def rendering_lines(sizes = min_widths)
91
- nb_lines = 0
92
- by_cell = @cells.zip(sizes).collect do |cell,size|
93
- lines = cell.rendering_lines(size)
94
- nb_lines = max(nb_lines, lines.size)
95
- lines
96
- end
97
- grid = (0...nb_lines).collect do |line_i|
98
- "| " + by_cell.zip(sizes).collect{|cell_lines, size|
99
- cell_lines[line_i] || " "*size
100
- }.join(" | ") + " |"
101
- end
102
- grid.empty? ? ["| |"] : grid
103
- end
104
-
105
- end # class Row
106
-
107
- class Table
108
- include Utils
109
-
110
- def initialize(records, attributes)
111
- @header = Row.new(attributes)
112
- @rows = records.collect{|r| Row.new(r)}
113
- end
114
-
115
- def render(buffer = "")
116
- sizes = @rows.inject(@header.min_widths) do |memo,row|
117
- memo.zip(row.min_widths).collect{|x,y| max(x,y)}
118
- end
119
- sep = '+-' << sizes.collect{|s| '-' * s}.join('-+-') << '-+'
120
- buffer << sep << "\n"
121
- buffer << @header.rendering_lines(sizes).first << "\n"
122
- buffer << sep << "\n"
123
- @rows.each do |row|
124
- row.rendering_lines(sizes).each do |line|
125
- buffer << line << "\n"
126
- end
127
- end
128
- buffer << sep << "\n"
129
- buffer
130
- end
131
-
132
- end # class Table
133
-
134
- protected
135
-
136
- def render(input, output)
137
- relation = input.to_a
138
- attrs = relation.inject([]){|memo,t|
139
- memo | t.keys
140
- }
141
- records = relation.collect{|t|
142
- attrs.collect{|a| t[a]}
143
- }
144
- Table.new(records, attrs).render(output)
145
- end
146
-
147
- def self.render(input, output)
148
- new(input).execute(output)
149
- end
150
-
151
- Alf::Renderer.register(:text, "as a text table", self)
152
- end # class Text
153
- end # class Alf
@@ -1,22 +0,0 @@
1
- require "yaml"
2
- module Alf
3
- module Iterator
4
-
5
- def to_yaml(*args, &block)
6
- to_a.to_yaml(*args, &block)
7
- end
8
-
9
- end
10
- class Renderer::YAML < Renderer
11
-
12
- protected
13
-
14
- # (see Alf::Renderer#render)
15
- def render(input, output)
16
- output << input.to_a.to_yaml << "\n"
17
- output
18
- end
19
-
20
- Renderer.register(:yaml, "as a yaml output", self)
21
- end # class YAML
22
- end # module Alf
@@ -1,37 +0,0 @@
1
- require 'spec_helper'
2
- describe "Alf's integration tests" do
3
-
4
- module Helpers
5
-
6
- def rel_equal(x, y)
7
- x.to_rel == y.to_rel
8
- end
9
-
10
- def specify(message, x)
11
- raise message unless x
12
- end
13
-
14
- end
15
-
16
- shared_examples_for "An integration file" do
17
-
18
- let(:lispy){
19
- lispy = Alf.lispy(Alf::Environment.examples)
20
- lispy.ruby_extend(Helpers)
21
- }
22
-
23
- it "should work when executed with a Alf" do
24
- lispy.compile(File.read(subject))
25
- end
26
-
27
- end # An example
28
-
29
-
30
- Dir["#{File.expand_path('../src', __FILE__)}/**/*.alf"].each do |file|
31
- describe file do
32
- subject{ file }
33
- it_should_behave_like "An integration file"
34
- end
35
- end
36
-
37
- end