alf 0.9.2 → 0.9.3

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 (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