qrb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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