qrb 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. data/CHANGELOG.md +7 -0
  2. data/Gemfile.lock +1 -1
  3. data/README.md +30 -1
  4. data/lib/qrb.rb +6 -0
  5. data/lib/qrb/data_type.rb +7 -1
  6. data/lib/qrb/support/dress_helper.rb +1 -1
  7. data/lib/qrb/support/type_factory.rb +6 -0
  8. data/lib/qrb/syntax.rb +7 -0
  9. data/lib/qrb/syntax/ad_type.rb +7 -0
  10. data/lib/qrb/syntax/any_type.rb +16 -0
  11. data/lib/qrb/syntax/attribute.rb +4 -0
  12. data/lib/qrb/syntax/builtin_type.rb +4 -0
  13. data/lib/qrb/syntax/constraint_def.rb +6 -0
  14. data/lib/qrb/syntax/constraints.rb +4 -0
  15. data/lib/qrb/syntax/contract.rb +21 -9
  16. data/lib/qrb/syntax/definitions.rb +4 -0
  17. data/lib/qrb/syntax/external_pair.rb +17 -0
  18. data/lib/qrb/syntax/heading.rb +4 -0
  19. data/lib/qrb/syntax/inline_pair.rb +16 -0
  20. data/lib/qrb/syntax/lambda_expr.rb +4 -0
  21. data/lib/qrb/syntax/named_constraint.rb +6 -0
  22. data/lib/qrb/syntax/q.citrus +29 -4
  23. data/lib/qrb/syntax/q.sexp +114 -0
  24. data/lib/qrb/syntax/relation_type.rb +4 -0
  25. data/lib/qrb/syntax/seq_type.rb +4 -0
  26. data/lib/qrb/syntax/set_type.rb +4 -0
  27. data/lib/qrb/syntax/sub_type.rb +4 -0
  28. data/lib/qrb/syntax/system.rb +6 -0
  29. data/lib/qrb/syntax/tuple_type.rb +4 -0
  30. data/lib/qrb/syntax/type_def.rb +4 -0
  31. data/lib/qrb/syntax/type_ref.rb +4 -0
  32. data/lib/qrb/syntax/union_type.rb +4 -0
  33. data/lib/qrb/syntax/unnamed_constraint.rb +6 -0
  34. data/lib/qrb/type.rb +1 -0
  35. data/lib/qrb/type/ad_type.rb +8 -7
  36. data/lib/qrb/type/any_type.rb +47 -0
  37. data/lib/qrb/version.rb +1 -1
  38. data/spec/spec_helper.rb +11 -0
  39. data/spec/unit/qrb/test_ast.rb +43 -0
  40. data/spec/unit/syntax/nodes/test_ad_type.rb +72 -0
  41. data/spec/unit/syntax/nodes/test_any_type.rb +30 -0
  42. data/spec/unit/syntax/nodes/test_attribute.rb +23 -10
  43. data/spec/unit/syntax/nodes/test_builtin_type.rb +25 -13
  44. data/spec/unit/syntax/nodes/test_constraint_def.rb +14 -0
  45. data/spec/unit/syntax/nodes/test_constraints.rb +35 -0
  46. data/spec/unit/syntax/nodes/test_contract.rb +76 -4
  47. data/spec/unit/syntax/nodes/test_heading.rb +37 -20
  48. data/spec/unit/syntax/nodes/test_named_constraint.rb +12 -0
  49. data/spec/unit/syntax/nodes/test_relation_type.rb +38 -20
  50. data/spec/unit/syntax/nodes/test_seq_type.rb +23 -9
  51. data/spec/unit/syntax/nodes/test_set_type.rb +23 -9
  52. data/spec/unit/syntax/nodes/test_sub_type.rb +29 -0
  53. data/spec/unit/syntax/nodes/test_system.rb +48 -0
  54. data/spec/unit/syntax/nodes/test_tuple_type.rb +38 -20
  55. data/spec/unit/syntax/nodes/test_type_def.rb +33 -0
  56. data/spec/unit/syntax/nodes/test_type_ref.rb +37 -0
  57. data/spec/unit/syntax/nodes/test_union_type.rb +23 -8
  58. data/spec/unit/syntax/nodes/test_unnamed_constraint.rb +12 -0
  59. data/spec/unit/type/ad_type/test_default_name.rb +2 -2
  60. data/spec/unit/type/ad_type/test_dress.rb +3 -3
  61. data/spec/unit/type/ad_type/test_initialize.rb +2 -2
  62. data/spec/unit/type/any_type/test_default_name.rb +12 -0
  63. data/spec/unit/type/any_type/test_dress.rb +22 -0
  64. data/spec/unit/type/any_type/test_equality.rb +26 -0
  65. data/spec/unit/type/any_type/test_include.rb +22 -0
  66. data/spec/unit/type/any_type/test_initialize.rb +10 -0
  67. data/spec/unit/type/any_type/test_name.rb +24 -0
  68. data/spec/unit/type_factory/dsl/test_adt.rb +2 -2
  69. data/spec/unit/type_factory/dsl/test_any.rb +28 -0
  70. metadata +33 -4
@@ -6,19 +6,33 @@ module Qrb
6
6
  Syntax.parse(input, root: "seq_type")
7
7
  }
8
8
 
9
- let(:compiled){
10
- subject.compile(type_factory)
11
- }
9
+ describe "compilation result" do
10
+ let(:compiled){
11
+ subject.compile(type_factory)
12
+ }
12
13
 
13
- context '[.Integer]' do
14
- let(:input){ '[.Integer]' }
14
+ context '[.Integer]' do
15
+ let(:input){ '[.Integer]' }
15
16
 
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)
17
+ it 'compiles to a SeqType' do
18
+ compiled.should be_a(SeqType)
19
+ compiled.elm_type.should be_a(BuiltinType)
20
+ compiled.elm_type.ruby_type.should be(Integer)
21
+ end
20
22
  end
21
23
  end
22
24
 
25
+ describe "AST" do
26
+ let(:input){ '[.Integer]' }
27
+
28
+ let(:ast){ subject.to_ast }
29
+
30
+ it{ ast.should eq([
31
+ :seq_type,
32
+ [:builtin_type, "Integer"]
33
+ ])
34
+ }
35
+ end
36
+
23
37
  end
24
38
  end
@@ -6,19 +6,33 @@ module Qrb
6
6
  Syntax.parse(input, root: "set_type")
7
7
  }
8
8
 
9
- let(:compiled){
10
- subject.compile(type_factory)
11
- }
9
+ describe "compilation result" do
10
+ let(:compiled){
11
+ subject.compile(type_factory)
12
+ }
12
13
 
13
- context '{.Integer}' do
14
- let(:input){ '{.Integer}' }
14
+ context '{.Integer}' do
15
+ let(:input){ '{.Integer}' }
15
16
 
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)
17
+ it 'compiles to a SeqType' do
18
+ compiled.should be_a(SetType)
19
+ compiled.elm_type.should be_a(BuiltinType)
20
+ compiled.elm_type.ruby_type.should be(Integer)
21
+ end
20
22
  end
21
23
  end
22
24
 
25
+ describe "AST" do
26
+ let(:input){ '{.Integer}' }
27
+
28
+ let(:ast){ subject.to_ast }
29
+
30
+ it{ ast.should eq([
31
+ :set_type,
32
+ [:builtin_type, "Integer"]
33
+ ])
34
+ }
35
+ end
36
+
23
37
  end
24
38
  end
@@ -10,6 +10,10 @@ module Qrb
10
10
  subject.compile(type_factory)
11
11
  }
12
12
 
13
+ let(:ast){
14
+ subject.to_ast
15
+ }
16
+
13
17
  context '.Integer( i | i >= 0 )' do
14
18
  let(:input){ '.Integer( i | i >= 0 )' }
15
19
 
@@ -18,6 +22,14 @@ module Qrb
18
22
  compiled.super_type.should be_a(BuiltinType)
19
23
  compiled.super_type.ruby_type.should be(Integer)
20
24
  end
25
+
26
+ it 'has the expected AST' do
27
+ ast.should eq([
28
+ :sub_type,
29
+ [:builtin_type, "Integer"],
30
+ [:constraint, "default", [:fn, [:parameters, "i"], [:source, "i >= 0"]]]
31
+ ])
32
+ end
21
33
  end
22
34
 
23
35
  context '.Integer( i | positive: i >= 0 )' do
@@ -32,6 +44,14 @@ module Qrb
32
44
  it 'has the correct constraints' do
33
45
  compiled.constraints.keys.should eq([:positive])
34
46
  end
47
+
48
+ it 'has the expected AST' do
49
+ ast.should eq([
50
+ :sub_type,
51
+ [:builtin_type, "Integer"],
52
+ [:constraint, "positive", [:fn, [:parameters, "i"], [:source, "i >= 0"]]]
53
+ ])
54
+ end
35
55
  end
36
56
 
37
57
  context '.Integer( i | positive: i >= 0, ... )' do
@@ -46,6 +66,15 @@ module Qrb
46
66
  it 'has the correct constraints' do
47
67
  compiled.constraints.keys.should eq([:positive, :small])
48
68
  end
69
+
70
+ it 'has the expected AST' do
71
+ ast.should eq([
72
+ :sub_type,
73
+ [:builtin_type, "Integer"],
74
+ [:constraint, "positive", [:fn, [:parameters, "i"], [:source, "i >= 0"]]],
75
+ [:constraint, "small", [:fn, [:parameters, "i"], [:source, "i <= 255"]]]
76
+ ])
77
+ end
49
78
  end
50
79
 
51
80
  end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "system" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "system")
7
+ }
8
+
9
+ let(:ast){
10
+ subject.to_ast
11
+ }
12
+
13
+ context 'with definitions and a type' do
14
+ let(:input){ "Int = .Integer\n{r: Int}" }
15
+
16
+ it 'has the expected AST' do
17
+ ast.should eq([
18
+ :system,
19
+ [:type_def, "Int", [:builtin_type, "Integer"]],
20
+ [:tuple_type, [:heading, [:attribute, "r", [:type_ref, "Int"]]]]
21
+ ])
22
+ end
23
+ end
24
+
25
+ context 'with definitions only' do
26
+ let(:input){ "Int = .Integer" }
27
+
28
+ it 'has the expected AST' do
29
+ ast.should eq([
30
+ :system,
31
+ [:type_def, "Int", [:builtin_type, "Integer"]]
32
+ ])
33
+ end
34
+ end
35
+
36
+ context 'with a type only' do
37
+ let(:input){ "{r: .Integer}" }
38
+
39
+ it 'has the expected AST' do
40
+ ast.should eq([
41
+ :system,
42
+ [:tuple_type, [:heading, [:attribute, "r", [:builtin_type, "Integer"]]]]
43
+ ])
44
+ end
45
+ end
46
+
47
+ end
48
+ end
@@ -6,35 +6,53 @@ module Qrb
6
6
  Syntax.parse(input, root: "tuple_type")
7
7
  }
8
8
 
9
- let(:compiled){
10
- subject.compile(type_factory)
11
- }
9
+ describe "compilation result" do
10
+ let(:compiled){
11
+ subject.compile(type_factory)
12
+ }
13
+
14
+ context 'empty heading' do
15
+ let(:input){ '{ }' }
16
+
17
+ it 'compiles to a TupleType' do
18
+ compiled.should be_a(TupleType)
19
+ compiled.heading.should be_empty
20
+ end
21
+ end
12
22
 
13
- context 'empty heading' do
14
- let(:input){ '{ }' }
23
+ context '{a: .Integer}' do
24
+ let(:input){ '{a: .Integer}' }
15
25
 
16
- it 'compiles to a TupleType' do
17
- compiled.should be_a(TupleType)
18
- compiled.heading.should be_empty
26
+ it 'compiles to a TupleType' do
27
+ compiled.should be_a(TupleType)
28
+ compiled.heading.size.should eq(1)
29
+ end
19
30
  end
20
- end
21
31
 
22
- context '{a: .Integer}' do
23
- let(:input){ '{a: .Integer}' }
32
+ context '{a: .Integer, b: .Float}' do
33
+ let(:input){ '{a: .Integer, b: .Float}' }
24
34
 
25
- it 'compiles to a TupleType' do
26
- compiled.should be_a(TupleType)
27
- compiled.heading.size.should eq(1)
35
+ it 'compiles to a TupleType' do
36
+ compiled.should be_a(TupleType)
37
+ compiled.heading.size.should eq(2)
38
+ end
28
39
  end
29
40
  end
30
41
 
31
- context '{a: .Integer, b: .Float}' do
32
- let(:input){ '{a: .Integer, b: .Float}' }
42
+ describe "AST" do
43
+ let(:input){ '{a: .Integer}' }
33
44
 
34
- it 'compiles to a TupleType' do
35
- compiled.should be_a(TupleType)
36
- compiled.heading.size.should eq(2)
37
- end
45
+ let(:ast){ subject.to_ast }
46
+
47
+ it{
48
+ ast.should eq([
49
+ :tuple_type,
50
+ [
51
+ :heading,
52
+ [ :attribute, "a", [:builtin_type, "Integer" ]]
53
+ ]
54
+ ])
55
+ }
38
56
  end
39
57
 
40
58
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "type_def" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "type_def")
7
+ }
8
+
9
+ let(:sys){
10
+ system
11
+ }
12
+
13
+ let(:compiled){
14
+ subject.compile(sys)
15
+ }
16
+
17
+ let(:ast){
18
+ subject.to_ast
19
+ }
20
+
21
+ let(:input){ 'Int = .Integer' }
22
+
23
+ it 'add the type to the system' do
24
+ compiled
25
+ sys["Int"].should be_a(BuiltinType)
26
+ end
27
+
28
+ it 'has the expected AST' do
29
+ ast.should eq([:type_def, "Int", [:builtin_type, "Integer"]])
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+ module Qrb
3
+ describe Syntax, "type_ref" do
4
+
5
+ subject{
6
+ Syntax.parse(input, root: "type_ref")
7
+ }
8
+
9
+ let(:sys){
10
+ system
11
+ }
12
+
13
+ let(:compiled){
14
+ subject.compile(sys)
15
+ }
16
+
17
+ let(:ast){
18
+ subject.to_ast
19
+ }
20
+
21
+ before do
22
+ sys.add_type(BuiltinType.new(Integer, "Int"))
23
+ end
24
+
25
+ let(:input){ 'Int' }
26
+
27
+ it 'compiles to a the BuiltinType' do
28
+ compiled.should be_a(BuiltinType)
29
+ compiled.name.should eq("Int")
30
+ end
31
+
32
+ it 'has the expected AST' do
33
+ ast.should eq([:type_ref, "Int"])
34
+ end
35
+
36
+ end
37
+ end
@@ -6,18 +6,33 @@ module Qrb
6
6
  Syntax.parse(input, root: "union_type")
7
7
  }
8
8
 
9
- let(:compiled){
10
- subject.compile(type_factory)
11
- }
9
+ describe "compilation result" do
10
+ let(:compiled){
11
+ subject.compile(type_factory)
12
+ }
12
13
 
13
- context '.Integer|.Float' do
14
- let(:input){ '.Integer|.Float' }
14
+ context '.Integer|.Float' do
15
+ let(:input){ '.Integer|.Float' }
15
16
 
16
- it 'compiles to a UnionType' do
17
- compiled.should be_a(UnionType)
18
- compiled.should eq(UnionType.new([intType, floatType]))
17
+ it 'compiles to a UnionType' do
18
+ compiled.should be_a(UnionType)
19
+ compiled.should eq(UnionType.new([intType, floatType]))
20
+ end
19
21
  end
20
22
  end
21
23
 
24
+ describe "AST" do
25
+ let(:input){ '.Integer|.Float' }
26
+
27
+ let(:ast){ subject.to_ast }
28
+
29
+ it{ ast.should eq([
30
+ :union_type,
31
+ [:builtin_type, "Integer"],
32
+ [:builtin_type, "Float"]
33
+ ])
34
+ }
35
+ end
36
+
22
37
  end
23
38
  end
@@ -10,6 +10,10 @@ module Qrb
10
10
  subject.compile("a")
11
11
  }
12
12
 
13
+ let(:ast){
14
+ subject.to_ast("a")
15
+ }
16
+
13
17
  context 'a >= 10' do
14
18
  let(:input){ 'a >= 10' }
15
19
 
@@ -25,6 +29,14 @@ module Qrb
25
29
  compiled[:predicate].call(12).should be_true
26
30
  compiled[:predicate].call(9).should be_false
27
31
  end
32
+
33
+ it 'has the expected AST' do
34
+ ast.should eq([
35
+ :constraint,
36
+ "default",
37
+ [:fn, [:parameters, "a"], [:source, "a >= 10"]]
38
+ ])
39
+ end
28
40
  end
29
41
 
30
42
  end
@@ -5,8 +5,8 @@ module Qrb
5
5
  subject{ type.default_name }
6
6
 
7
7
  let(:type){
8
- AdType.new(Color, rgb: [intType, Color.method(:rgb) ],
9
- hex: [floatType, Color.method(:hex) ])
8
+ AdType.new(Color, rgb: [intType, Color.method(:rgb), Qrb::IDENTITY ],
9
+ hex: [floatType, Color.method(:hex), Qrb::IDENTITY ])
10
10
  }
11
11
 
12
12
  it{ should eq('Color') }
@@ -3,8 +3,8 @@ module Qrb
3
3
  describe AdType, 'dress' do
4
4
 
5
5
  let(:type){
6
- AdType.new(Color, rgb: [intType, ->(i){ i*2 } ],
7
- hex: [floatType, ->(f){ f*3 } ])
6
+ AdType.new(Color, rgb: [intType, ->(i){ i*2 }, Qrb::IDENTITY ],
7
+ hex: [floatType, ->(f){ f*3 }, Qrb::IDENTITY ])
8
8
  }
9
9
 
10
10
  subject{
@@ -41,7 +41,7 @@ module Qrb
41
41
 
42
42
  context 'when the upper raises an error' do
43
43
  let(:type){
44
- AdType.new(Color, rgb: [ intType, ->(t){ raise ArgumentError } ])
44
+ AdType.new(Color, rgb: [ intType, ->(t){ raise ArgumentError }, Qrb::IDENTITY ])
45
45
  }
46
46
 
47
47
  it 'should hide the error' do
@@ -3,8 +3,8 @@ module Qrb
3
3
  describe AdType, 'initialize' do
4
4
 
5
5
  subject{
6
- AdType.new(Color, rgb: [intType, Color.method(:rgb) ],
7
- hex: [floatType, Color.method(:hex) ])
6
+ AdType.new(Color, rgb: [intType, Color.method(:rgb), Qrb::IDENTITY ],
7
+ hex: [floatType, Color.method(:hex), Qrb::IDENTITY ])
8
8
  }
9
9
 
10
10
  context 'with valid arguments' do