qrb 0.1.0

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 (159) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/Gemfile +12 -0
  3. data/Gemfile.lock +58 -0
  4. data/LICENCE.md +22 -0
  5. data/Manifest.txt +11 -0
  6. data/README.md +118 -0
  7. data/Rakefile +11 -0
  8. data/lib/qrb/Q/default.q +29 -0
  9. data/lib/qrb/data_type.rb +23 -0
  10. data/lib/qrb/errors.rb +23 -0
  11. data/lib/qrb/support/attribute.rb +53 -0
  12. data/lib/qrb/support/collection_type.rb +25 -0
  13. data/lib/qrb/support/dress_helper.rb +68 -0
  14. data/lib/qrb/support/heading.rb +57 -0
  15. data/lib/qrb/support/type_factory.rb +178 -0
  16. data/lib/qrb/support.rb +5 -0
  17. data/lib/qrb/syntax/ad_type.rb +25 -0
  18. data/lib/qrb/syntax/attribute.rb +11 -0
  19. data/lib/qrb/syntax/builtin_type.rb +13 -0
  20. data/lib/qrb/syntax/constraint_def.rb +11 -0
  21. data/lib/qrb/syntax/constraints.rb +18 -0
  22. data/lib/qrb/syntax/contract.rb +25 -0
  23. data/lib/qrb/syntax/definitions.rb +14 -0
  24. data/lib/qrb/syntax/expression.rb +12 -0
  25. data/lib/qrb/syntax/heading.rb +15 -0
  26. data/lib/qrb/syntax/lambda_expr.rb +11 -0
  27. data/lib/qrb/syntax/named_constraint.rb +11 -0
  28. data/lib/qrb/syntax/q.citrus +195 -0
  29. data/lib/qrb/syntax/relation_type.rb +11 -0
  30. data/lib/qrb/syntax/seq_type.rb +12 -0
  31. data/lib/qrb/syntax/set_type.rb +12 -0
  32. data/lib/qrb/syntax/sub_type.rb +13 -0
  33. data/lib/qrb/syntax/support.rb +13 -0
  34. data/lib/qrb/syntax/system.rb +15 -0
  35. data/lib/qrb/syntax/tuple_type.rb +11 -0
  36. data/lib/qrb/syntax/type_def.rb +14 -0
  37. data/lib/qrb/syntax/type_ref.rb +13 -0
  38. data/lib/qrb/syntax/union_type.rb +12 -0
  39. data/lib/qrb/syntax/unnamed_constraint.rb +11 -0
  40. data/lib/qrb/syntax.rb +42 -0
  41. data/lib/qrb/system.rb +63 -0
  42. data/lib/qrb/type/ad_type.rb +111 -0
  43. data/lib/qrb/type/builtin_type.rb +56 -0
  44. data/lib/qrb/type/relation_type.rb +81 -0
  45. data/lib/qrb/type/seq_type.rb +51 -0
  46. data/lib/qrb/type/set_type.rb +52 -0
  47. data/lib/qrb/type/sub_type.rb +94 -0
  48. data/lib/qrb/type/tuple_type.rb +99 -0
  49. data/lib/qrb/type/union_type.rb +78 -0
  50. data/lib/qrb/type.rb +63 -0
  51. data/lib/qrb/version.rb +14 -0
  52. data/lib/qrb.rb +63 -0
  53. data/qrb.gemspec +186 -0
  54. data/spec/acceptance/Q/test_default.rb +96 -0
  55. data/spec/acceptance/Q/test_parsing.rb +15 -0
  56. data/spec/acceptance/ad_type/test_in_q.rb +82 -0
  57. data/spec/acceptance/ad_type/test_in_ruby.rb +60 -0
  58. data/spec/spec_helper.rb +68 -0
  59. data/spec/unit/attribute/test_equality.rb +26 -0
  60. data/spec/unit/attribute/test_fetch_on.rb +50 -0
  61. data/spec/unit/attribute/test_initialize.rb +13 -0
  62. data/spec/unit/attribute/test_to_name.rb +10 -0
  63. data/spec/unit/heading/test_each.rb +28 -0
  64. data/spec/unit/heading/test_equality.rb +28 -0
  65. data/spec/unit/heading/test_initialize.rb +36 -0
  66. data/spec/unit/heading/test_size.rb +30 -0
  67. data/spec/unit/heading/test_to_name.rb +32 -0
  68. data/spec/unit/qrb/test_parse.rb +18 -0
  69. data/spec/unit/syntax/nodes/test_ad_type.rb +94 -0
  70. data/spec/unit/syntax/nodes/test_attribute.rb +25 -0
  71. data/spec/unit/syntax/nodes/test_builtin_type.rb +32 -0
  72. data/spec/unit/syntax/nodes/test_comment.rb +26 -0
  73. data/spec/unit/syntax/nodes/test_constraint_def.rb +27 -0
  74. data/spec/unit/syntax/nodes/test_constraints.rb +51 -0
  75. data/spec/unit/syntax/nodes/test_contract.rb +62 -0
  76. data/spec/unit/syntax/nodes/test_expression.rb +43 -0
  77. data/spec/unit/syntax/nodes/test_heading.rb +41 -0
  78. data/spec/unit/syntax/nodes/test_named_constraint.rb +31 -0
  79. data/spec/unit/syntax/nodes/test_relation_type.rb +41 -0
  80. data/spec/unit/syntax/nodes/test_seq_type.rb +24 -0
  81. data/spec/unit/syntax/nodes/test_set_type.rb +24 -0
  82. data/spec/unit/syntax/nodes/test_spacing.rb +25 -0
  83. data/spec/unit/syntax/nodes/test_sub_type.rb +52 -0
  84. data/spec/unit/syntax/nodes/test_tuple_type.rb +41 -0
  85. data/spec/unit/syntax/nodes/test_union_type.rb +23 -0
  86. data/spec/unit/syntax/nodes/test_unnamed_constraint.rb +31 -0
  87. data/spec/unit/syntax/test_compile_type.rb +22 -0
  88. data/spec/unit/system/test_add_type.rb +47 -0
  89. data/spec/unit/system/test_dsl.rb +30 -0
  90. data/spec/unit/system/test_dup.rb +30 -0
  91. data/spec/unit/system/test_fetch.rb +42 -0
  92. data/spec/unit/system/test_get_type.rb +30 -0
  93. data/spec/unit/system/test_initialize.rb +10 -0
  94. data/spec/unit/test_qrb.rb +15 -0
  95. data/spec/unit/type/ad_type/test_default_name.rb +15 -0
  96. data/spec/unit/type/ad_type/test_dress.rb +55 -0
  97. data/spec/unit/type/ad_type/test_include.rb +22 -0
  98. data/spec/unit/type/ad_type/test_initialize.rb +40 -0
  99. data/spec/unit/type/ad_type/test_name.rb +20 -0
  100. data/spec/unit/type/builtin_type/test_default_name.rb +12 -0
  101. data/spec/unit/type/builtin_type/test_dress.rb +33 -0
  102. data/spec/unit/type/builtin_type/test_equality.rb +26 -0
  103. data/spec/unit/type/builtin_type/test_include.rb +22 -0
  104. data/spec/unit/type/builtin_type/test_initialize.rb +12 -0
  105. data/spec/unit/type/builtin_type/test_name.rb +24 -0
  106. data/spec/unit/type/relation_type/test_default_name.rb +16 -0
  107. data/spec/unit/type/relation_type/test_dress.rb +164 -0
  108. data/spec/unit/type/relation_type/test_equality.rb +32 -0
  109. data/spec/unit/type/relation_type/test_include.rb +46 -0
  110. data/spec/unit/type/relation_type/test_initialize.rb +26 -0
  111. data/spec/unit/type/relation_type/test_name.rb +24 -0
  112. data/spec/unit/type/seq_type/test_default_name.rb +14 -0
  113. data/spec/unit/type/seq_type/test_dress.rb +49 -0
  114. data/spec/unit/type/seq_type/test_equality.rb +26 -0
  115. data/spec/unit/type/seq_type/test_include.rb +43 -0
  116. data/spec/unit/type/seq_type/test_initialize.rb +28 -0
  117. data/spec/unit/type/seq_type/test_name.rb +24 -0
  118. data/spec/unit/type/set_type/test_default_name.rb +14 -0
  119. data/spec/unit/type/set_type/test_dress.rb +66 -0
  120. data/spec/unit/type/set_type/test_equality.rb +26 -0
  121. data/spec/unit/type/set_type/test_include.rb +43 -0
  122. data/spec/unit/type/set_type/test_initialize.rb +28 -0
  123. data/spec/unit/type/set_type/test_name.rb +24 -0
  124. data/spec/unit/type/sub_type/test_default_name.rb +14 -0
  125. data/spec/unit/type/sub_type/test_dress.rb +75 -0
  126. data/spec/unit/type/sub_type/test_equality.rb +34 -0
  127. data/spec/unit/type/sub_type/test_include.rb +34 -0
  128. data/spec/unit/type/sub_type/test_initialize.rb +16 -0
  129. data/spec/unit/type/sub_type/test_name.rb +24 -0
  130. data/spec/unit/type/tuple_type/test_default_name.rb +14 -0
  131. data/spec/unit/type/tuple_type/test_dress.rb +112 -0
  132. data/spec/unit/type/tuple_type/test_equality.rb +32 -0
  133. data/spec/unit/type/tuple_type/test_include.rb +38 -0
  134. data/spec/unit/type/tuple_type/test_initialize.rb +30 -0
  135. data/spec/unit/type/tuple_type/test_name.rb +24 -0
  136. data/spec/unit/type/union_type/test_default_name.rb +12 -0
  137. data/spec/unit/type/union_type/test_dress.rb +43 -0
  138. data/spec/unit/type/union_type/test_equality.rb +30 -0
  139. data/spec/unit/type/union_type/test_include.rb +28 -0
  140. data/spec/unit/type/union_type/test_initialize.rb +24 -0
  141. data/spec/unit/type/union_type/test_name.rb +20 -0
  142. data/spec/unit/type_factory/dsl/test_adt.rb +54 -0
  143. data/spec/unit/type_factory/dsl/test_attribute.rb +37 -0
  144. data/spec/unit/type_factory/dsl/test_attributes.rb +41 -0
  145. data/spec/unit/type_factory/dsl/test_builtin.rb +45 -0
  146. data/spec/unit/type_factory/dsl/test_relation.rb +85 -0
  147. data/spec/unit/type_factory/dsl/test_seq.rb +57 -0
  148. data/spec/unit/type_factory/dsl/test_set.rb +57 -0
  149. data/spec/unit/type_factory/dsl/test_subtype.rb +91 -0
  150. data/spec/unit/type_factory/dsl/test_tuple.rb +73 -0
  151. data/spec/unit/type_factory/dsl/test_union.rb +81 -0
  152. data/spec/unit/type_factory/factory/test_builtin.rb +24 -0
  153. data/spec/unit/type_factory/factory/test_seq_type.rb +44 -0
  154. data/spec/unit/type_factory/factory/test_set_type.rb +44 -0
  155. data/spec/unit/type_factory/factory/test_sub_type.rb +53 -0
  156. data/spec/unit/type_factory/factory/test_tuple_type.rb +43 -0
  157. data/tasks/gem.rake +73 -0
  158. data/tasks/test.rake +31 -0
  159. metadata +344 -0
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Heading, "equality" do
4
+
5
+ let(:h1){ Heading.new([Attribute.new(:r, intType), Attribute.new(:b, intType)]) }
6
+ let(:h2){ Heading.new([Attribute.new(:b, intType), Attribute.new(:r, intType)]) }
7
+ let(:h3){ Heading.new([Attribute.new(:b, intType)]) }
8
+
9
+ it 'should apply structural equality' do
10
+ (h1 == h2).should be_true
11
+ (h2 == h1).should be_true
12
+ end
13
+
14
+ it 'should apply distinguish different types' do
15
+ (h1 == h3).should be_false
16
+ (h2 == h3).should be_false
17
+ end
18
+
19
+ it 'should be a total function, with nil for non types' do
20
+ (h1 == 12).should be_nil
21
+ end
22
+
23
+ it 'should implement hash accordingly' do
24
+ [h1, h2].map(&:hash).uniq.size.should eq(1)
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Heading, "initialize" do
4
+
5
+ subject{ Heading.new(attributes) }
6
+
7
+ context 'with no attribute' do
8
+ let(:attributes){
9
+ [ ]
10
+ }
11
+
12
+ it{ should be_a(Heading) }
13
+ end
14
+
15
+ context 'with valid attributes' do
16
+ let(:attributes){
17
+ [ Attribute.new(:red, intType) ]
18
+ }
19
+
20
+ it{ should be_a(Heading) }
21
+ end
22
+
23
+ context 'with invalid attributes' do
24
+ let(:attributes){
25
+ [ Attribute.new(:red, intType), Attribute.new(:red, intType) ]
26
+ }
27
+
28
+ it 'should raise an error' do
29
+ ->{
30
+ subject
31
+ }.should raise_error(ArgumentError, "Attribute names must be unique")
32
+ end
33
+ end
34
+
35
+ end
36
+ end
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Heading, "size" do
4
+
5
+ let(:r){ Attribute.new(:red, intType) }
6
+ let(:g){ Attribute.new(:green, intType) }
7
+ let(:b){ Attribute.new(:blue, intType) }
8
+
9
+ subject{ heading.size }
10
+
11
+ context 'on an empty heading' do
12
+ let(:heading){ Heading.new([]) }
13
+
14
+ it{ should eq(0) }
15
+ end
16
+
17
+ context 'on an singleton heading' do
18
+ let(:heading){ Heading.new([r]) }
19
+
20
+ it{ should eq(1) }
21
+ end
22
+
23
+ context 'on an big heading' do
24
+ let(:heading){ Heading.new([r, g, b]) }
25
+
26
+ it{ should eq(3) }
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Heading, "to_name" do
4
+
5
+ subject{ Heading.new(attributes).to_name }
6
+
7
+ context 'with no attribute' do
8
+ let(:attributes){
9
+ [ ]
10
+ }
11
+
12
+ it{ should eq('') }
13
+ end
14
+
15
+ context 'with one attribute' do
16
+ let(:attributes){
17
+ [ Attribute.new(:red, intType) ]
18
+ }
19
+
20
+ it{ should eq('red: intType') }
21
+ end
22
+
23
+ context 'with multiple attributes' do
24
+ let(:attributes){
25
+ [ Attribute.new(:red, intType), Attribute.new(:blue, floatType) ]
26
+ }
27
+
28
+ it{ should eq('red: intType, blue: floatType') }
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ describe Qrb, "parse" do
3
+
4
+ subject{
5
+ Qrb.parse <<-EOF
6
+ Posint = .Fixnum( i | i>=0 )
7
+ Point = { x: Posint, y: Posint }
8
+ EOF
9
+ }
10
+
11
+ it{ should be_a(Qrb::System) }
12
+
13
+ it 'should have the expected types' do
14
+ subject["Posint"].should be_a(Qrb::SubType)
15
+ subject["Point"].should be_a(Qrb::TupleType)
16
+ end
17
+
18
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "ad_type" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "ad_type")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context 'One contract' do
14
+ let(:input){ '.Color <rgb> {r: .Integer, g: .Integer, b: .Integer}' }
15
+
16
+ it 'compiles to an AdType' do
17
+ compiled.should be_a(AdType)
18
+ compiled.ruby_type.should be(Color)
19
+ compiled.contract_names.should eq([:rgb])
20
+ end
21
+
22
+ it 'should behave as expected' do
23
+ compiled.dress(r: 138, g: 43, b: 226).should eq(blueviolet)
24
+ end
25
+ end
26
+
27
+ context 'Two contracts' do
28
+ let(:input){
29
+ <<-TYPE.strip
30
+ .Color <rgb> {r: .Integer, g: .Integer, b: .Integer},
31
+ <hex> .String
32
+ TYPE
33
+ }
34
+
35
+ it 'compiles to an AdType' do
36
+ compiled.should be_a(AdType)
37
+ compiled.ruby_type.should be(Color)
38
+ compiled.contract_names.should eq([:rgb, :hex])
39
+ end
40
+
41
+ it 'should behave as expected' do
42
+ compiled.dress("#8A2BE2").should eq(blueviolet)
43
+ end
44
+ end
45
+
46
+ context 'No ruby class' do
47
+ let(:input){ '<as> {r: .Integer}' }
48
+
49
+ it 'compiles to an AdType' do
50
+ compiled.should be_a(AdType)
51
+ compiled.ruby_type.should be_nil
52
+ compiled.contract_names.should eq([:as])
53
+ end
54
+
55
+ it 'should behave as expected' do
56
+ compiled.dress(r: 12).should eq(r: 12)
57
+ ->{
58
+ compiled.dress("foo")
59
+ }.should raise_error(TypeError)
60
+ end
61
+ end
62
+
63
+ context 'Duplicate contract name' do
64
+ let(:input){ '.Color <rgb> {r: .Integer}, <rgb> .String' }
65
+
66
+ it 'raises an error' do
67
+ ->{
68
+ compiled
69
+ }.should raise_error(Error, "Duplicate contract name `rgb`")
70
+ end
71
+ end
72
+
73
+ context 'A contract with explicit converters' do
74
+ let(:input){ '.DateTime <iso> .String \( s | DateTime.parse(s) ) \( d | d.to_s )' }
75
+
76
+ it 'compiles to an AdType' do
77
+ compiled.should be_a(AdType)
78
+ compiled.ruby_type.should be(DateTime)
79
+ compiled.contract_names.should eq([:iso])
80
+ end
81
+
82
+ it 'should behave as expected' do
83
+ compiled.dress("2014-01-19T12:00").should be_a(DateTime)
84
+ end
85
+
86
+ it 'should hide errors' do
87
+ err = compiled.dress("foo") rescue $!
88
+ err.should be_a(TypeError)
89
+ err.message.should eq("Invalid value `foo` for DateTime")
90
+ end
91
+ end
92
+
93
+ end
94
+ end
@@ -0,0 +1,25 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "attribute" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "attribute")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context 'a: .Integer' do
14
+ let(:input){ 'a: .Integer' }
15
+
16
+ it 'compiles to an Attribute' do
17
+ compiled.should be_a(Attribute)
18
+ compiled.name.should eq(:a)
19
+ compiled.type.should be_a(BuiltinType)
20
+ compiled.type.ruby_type.should be(Integer)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "builtin_type" do
4
+
5
+ subject{
6
+ Syntax.parse(source, root: "builtin_type")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context 'when an unqualified class name' do
14
+ let(:source){ ".Integer" }
15
+
16
+ it 'compiles to a BuiltinType' do
17
+ compiled.should be_a(BuiltinType)
18
+ compiled.ruby_type.should be(Integer)
19
+ end
20
+ end
21
+
22
+ context 'when a qualified class name' do
23
+ let(:source){ ".Qrb::Type" }
24
+
25
+ it 'compiles to a BuiltinType' do
26
+ compiled.should be_a(BuiltinType)
27
+ compiled.ruby_type.should be(::Qrb::Type)
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "comment" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "comment")
7
+ }
8
+
9
+ [
10
+ '#',
11
+ "#\n",
12
+ "# \n",
13
+ '# foo bar',
14
+ "# foo bar\n",
15
+ ].each do |source|
16
+ context "when `#{source}`" do
17
+ let(:input){ source }
18
+
19
+ it 'should parse' do
20
+ subject.should eq(source)
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "constraint_def" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "constraint_def")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context '(i | i >= 0)' do
14
+ let(:input){ '(i | i >= 0)' }
15
+
16
+ it 'compiles to an Hash' do
17
+ compiled.should be_a(Hash)
18
+ end
19
+
20
+ it 'compiled to the correct proc' do
21
+ compiled[:predicate].call(12).should be_true
22
+ compiled[:predicate].call(-12).should be_false
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "constraints" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "constraints")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile("a")
11
+ }
12
+
13
+ context 'a >= 10' do
14
+ let(:input){ 'a >= 10' }
15
+
16
+ it 'compiles to an Hash' do
17
+ compiled.should be_a(Hash)
18
+ compiled.keys.should eq([:predicate])
19
+ end
20
+ end
21
+
22
+ context 'foo: a >= 10' do
23
+ let(:input){ 'foo: a >= 10' }
24
+
25
+ it 'compiles to an Hash' do
26
+ compiled.should be_a(Hash)
27
+ compiled.keys.should eq([:foo])
28
+ end
29
+ end
30
+
31
+ context 'foo: a >= 10, bar: a <= 255' do
32
+ let(:input){ 'foo: a >= 10, bar: a <= 255' }
33
+
34
+ it 'compiles to an Hash' do
35
+ compiled.should be_a(Hash)
36
+ compiled.keys.should eq([:foo, :bar])
37
+ end
38
+ end
39
+
40
+ context 'foo: a >= 10, foo: a <= 255' do
41
+ let(:input){ 'foo: a >= 10, foo: a <= 255' }
42
+
43
+ it 'compiles to an Hash' do
44
+ ->{
45
+ compiled
46
+ }.should raise_error("Duplicate constraint name `foo`")
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "contract" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "contract")
7
+ }
8
+
9
+ let(:contract){
10
+ compiled.values.first
11
+ }
12
+
13
+ context 'No converter and a class' do
14
+ let(:input){ '<rgb> {r: .Integer, g: .Integer, b: .Integer}' }
15
+
16
+ let(:compiled){
17
+ subject.compile(type_factory, Color)
18
+ }
19
+
20
+ it 'compiles to the expected Hash' do
21
+ compiled.should be_a(Hash)
22
+ compiled.keys.should eq([:rgb])
23
+ contract.should be_a(Array)
24
+ contract.first.should be_a(TupleType)
25
+ contract.last.should be_a(Method)
26
+ end
27
+ end
28
+
29
+ context 'No converter and no class' do
30
+ let(:input){ '<rgb> {r: .Integer, g: .Integer, b: .Integer}' }
31
+
32
+ let(:compiled){
33
+ subject.compile(type_factory, nil)
34
+ }
35
+
36
+ it 'compiles to the expected Hash' do
37
+ compiled.should be_a(Hash)
38
+ compiled.keys.should eq([:rgb])
39
+ contract.should be_a(Array)
40
+ contract.first.should be_a(TupleType)
41
+ contract.last.should be(Qrb::IDENTITY)
42
+ end
43
+ end
44
+
45
+ context 'A contract with explicit converters' do
46
+ let(:input){ '<iso> .String \( s | DateTime.parse(s) ) \( d | d.to_s )' }
47
+
48
+ let(:compiled){
49
+ subject.compile(type_factory, nil)
50
+ }
51
+
52
+ it 'compiles to the expected Hash' do
53
+ compiled.should be_a(Hash)
54
+ compiled.keys.should eq([:iso])
55
+ contract.should be_a(Array)
56
+ contract.first.should be_a(BuiltinType)
57
+ contract.last.should be_a(Proc)
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "expression" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "expression")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile("a")
11
+ }
12
+
13
+ context 'a >= 10' do
14
+ let(:input){ 'a >= 10' }
15
+
16
+ it 'compiles to an Proc' do
17
+ compiled.should be_a(Proc)
18
+ end
19
+
20
+ it 'should be the correct Proc' do
21
+ compiled.call(12).should be_true
22
+ compiled.call(9).should be_false
23
+ end
24
+ end
25
+
26
+ context '(a >= 10)' do
27
+ let(:input){ '(a >= 10)' }
28
+
29
+ it 'compiles to an Proc' do
30
+ compiled.should be_a(Proc)
31
+ end
32
+ end
33
+
34
+ context 'acall(a)' do
35
+ let(:input){ 'acall(a)' }
36
+
37
+ it 'compiles to an Proc' do
38
+ compiled.should be_a(Proc)
39
+ end
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "heading" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "heading")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context 'empty heading' do
14
+ let(:input){ ' ' }
15
+
16
+ it 'compiles to a Heading' do
17
+ compiled.should be_a(Heading)
18
+ compiled.to_name.should eq('')
19
+ end
20
+ end
21
+
22
+ context 'a: .Integer' do
23
+ let(:input){ 'a: .Integer' }
24
+
25
+ it 'compiles to a Heading' do
26
+ compiled.should be_a(Heading)
27
+ compiled.to_name.should eq('a: Integer')
28
+ end
29
+ end
30
+
31
+ context 'a: .Integer, b: .Float' do
32
+ let(:input){ 'a: .Integer, b: .Float' }
33
+
34
+ it 'compiles to a Heading' do
35
+ compiled.should be_a(Heading)
36
+ compiled.to_name.should eq('a: Integer, b: Float')
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "named_constraint" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "named_constraint")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile("a")
11
+ }
12
+
13
+ context 'a >= 10' do
14
+ let(:input){ 'foo: a >= 10' }
15
+
16
+ it 'compiles to an Hash' do
17
+ compiled.should be_a(Hash)
18
+ end
19
+
20
+ it 'has expected keys' do
21
+ compiled.keys.should eq([:foo])
22
+ end
23
+
24
+ it 'should be the correct Proc' do
25
+ compiled[:foo].call(12).should be_true
26
+ compiled[:foo].call(9).should be_false
27
+ end
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "relation_type" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "relation_type")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context 'empty heading' do
14
+ let(:input){ '{{ }}' }
15
+
16
+ it 'compiles to a RelationType' do
17
+ compiled.should be_a(RelationType)
18
+ compiled.heading.should be_empty
19
+ end
20
+ end
21
+
22
+ context '{{a: .Integer}}' do
23
+ let(:input){ '{{a: .Integer}}' }
24
+
25
+ it 'compiles to a RelationType' do
26
+ compiled.should be_a(RelationType)
27
+ compiled.heading.size.should eq(1)
28
+ end
29
+ end
30
+
31
+ context '{{a: .Integer, b: .Float}}' do
32
+ let(:input){ '{{a: .Integer, b: .Float}}' }
33
+
34
+ it 'compiles to a RelationType' do
35
+ compiled.should be_a(RelationType)
36
+ compiled.heading.size.should eq(2)
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "seq_type" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "seq_type")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context '[.Integer]' do
14
+ let(:input){ '[.Integer]' }
15
+
16
+ it 'compiles to a SeqType' do
17
+ compiled.should be_a(SeqType)
18
+ compiled.elm_type.should be_a(BuiltinType)
19
+ compiled.elm_type.ruby_type.should be(Integer)
20
+ end
21
+ end
22
+
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "set_type" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "set_type")
7
+ }
8
+
9
+ let(:compiled){
10
+ subject.compile(type_factory)
11
+ }
12
+
13
+ context '{.Integer}' do
14
+ let(:input){ '{.Integer}' }
15
+
16
+ it 'compiles to a SeqType' do
17
+ compiled.should be_a(SetType)
18
+ compiled.elm_type.should be_a(BuiltinType)
19
+ compiled.elm_type.ruby_type.should be(Integer)
20
+ end
21
+ end
22
+
23
+ end
24
+ end