qrb 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +7 -0
- data/Gemfile.lock +1 -1
- data/README.md +30 -1
- data/lib/qrb.rb +6 -0
- data/lib/qrb/data_type.rb +7 -1
- data/lib/qrb/support/dress_helper.rb +1 -1
- data/lib/qrb/support/type_factory.rb +6 -0
- data/lib/qrb/syntax.rb +7 -0
- data/lib/qrb/syntax/ad_type.rb +7 -0
- data/lib/qrb/syntax/any_type.rb +16 -0
- data/lib/qrb/syntax/attribute.rb +4 -0
- data/lib/qrb/syntax/builtin_type.rb +4 -0
- data/lib/qrb/syntax/constraint_def.rb +6 -0
- data/lib/qrb/syntax/constraints.rb +4 -0
- data/lib/qrb/syntax/contract.rb +21 -9
- data/lib/qrb/syntax/definitions.rb +4 -0
- data/lib/qrb/syntax/external_pair.rb +17 -0
- data/lib/qrb/syntax/heading.rb +4 -0
- data/lib/qrb/syntax/inline_pair.rb +16 -0
- data/lib/qrb/syntax/lambda_expr.rb +4 -0
- data/lib/qrb/syntax/named_constraint.rb +6 -0
- data/lib/qrb/syntax/q.citrus +29 -4
- data/lib/qrb/syntax/q.sexp +114 -0
- data/lib/qrb/syntax/relation_type.rb +4 -0
- data/lib/qrb/syntax/seq_type.rb +4 -0
- data/lib/qrb/syntax/set_type.rb +4 -0
- data/lib/qrb/syntax/sub_type.rb +4 -0
- data/lib/qrb/syntax/system.rb +6 -0
- data/lib/qrb/syntax/tuple_type.rb +4 -0
- data/lib/qrb/syntax/type_def.rb +4 -0
- data/lib/qrb/syntax/type_ref.rb +4 -0
- data/lib/qrb/syntax/union_type.rb +4 -0
- data/lib/qrb/syntax/unnamed_constraint.rb +6 -0
- data/lib/qrb/type.rb +1 -0
- data/lib/qrb/type/ad_type.rb +8 -7
- data/lib/qrb/type/any_type.rb +47 -0
- data/lib/qrb/version.rb +1 -1
- data/spec/spec_helper.rb +11 -0
- data/spec/unit/qrb/test_ast.rb +43 -0
- data/spec/unit/syntax/nodes/test_ad_type.rb +72 -0
- data/spec/unit/syntax/nodes/test_any_type.rb +30 -0
- data/spec/unit/syntax/nodes/test_attribute.rb +23 -10
- data/spec/unit/syntax/nodes/test_builtin_type.rb +25 -13
- data/spec/unit/syntax/nodes/test_constraint_def.rb +14 -0
- data/spec/unit/syntax/nodes/test_constraints.rb +35 -0
- data/spec/unit/syntax/nodes/test_contract.rb +76 -4
- data/spec/unit/syntax/nodes/test_heading.rb +37 -20
- data/spec/unit/syntax/nodes/test_named_constraint.rb +12 -0
- data/spec/unit/syntax/nodes/test_relation_type.rb +38 -20
- data/spec/unit/syntax/nodes/test_seq_type.rb +23 -9
- data/spec/unit/syntax/nodes/test_set_type.rb +23 -9
- data/spec/unit/syntax/nodes/test_sub_type.rb +29 -0
- data/spec/unit/syntax/nodes/test_system.rb +48 -0
- data/spec/unit/syntax/nodes/test_tuple_type.rb +38 -20
- data/spec/unit/syntax/nodes/test_type_def.rb +33 -0
- data/spec/unit/syntax/nodes/test_type_ref.rb +37 -0
- data/spec/unit/syntax/nodes/test_union_type.rb +23 -8
- data/spec/unit/syntax/nodes/test_unnamed_constraint.rb +12 -0
- data/spec/unit/type/ad_type/test_default_name.rb +2 -2
- data/spec/unit/type/ad_type/test_dress.rb +3 -3
- data/spec/unit/type/ad_type/test_initialize.rb +2 -2
- data/spec/unit/type/any_type/test_default_name.rb +12 -0
- data/spec/unit/type/any_type/test_dress.rb +22 -0
- data/spec/unit/type/any_type/test_equality.rb +26 -0
- data/spec/unit/type/any_type/test_include.rb +22 -0
- data/spec/unit/type/any_type/test_initialize.rb +10 -0
- data/spec/unit/type/any_type/test_name.rb +24 -0
- data/spec/unit/type_factory/dsl/test_adt.rb +2 -2
- data/spec/unit/type_factory/dsl/test_any.rb +28 -0
- metadata +33 -4
@@ -6,19 +6,33 @@ module Qrb
|
|
6
6
|
Syntax.parse(input, root: "seq_type")
|
7
7
|
}
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
describe "compilation result" do
|
10
|
+
let(:compiled){
|
11
|
+
subject.compile(type_factory)
|
12
|
+
}
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
context '[.Integer]' do
|
15
|
+
let(:input){ '[.Integer]' }
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
9
|
+
describe "compilation result" do
|
10
|
+
let(:compiled){
|
11
|
+
subject.compile(type_factory)
|
12
|
+
}
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
context '{.Integer}' do
|
15
|
+
let(:input){ '{.Integer}' }
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
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
|
-
|
10
|
-
|
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
|
-
|
14
|
-
|
23
|
+
context '{a: .Integer}' do
|
24
|
+
let(:input){ '{a: .Integer}' }
|
15
25
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
23
|
-
|
32
|
+
context '{a: .Integer, b: .Float}' do
|
33
|
+
let(:input){ '{a: .Integer, b: .Float}' }
|
24
34
|
|
25
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
32
|
-
let(:input){ '{a: .Integer
|
42
|
+
describe "AST" do
|
43
|
+
let(:input){ '{a: .Integer}' }
|
33
44
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
-
|
10
|
-
|
11
|
-
|
9
|
+
describe "compilation result" do
|
10
|
+
let(:compiled){
|
11
|
+
subject.compile(type_factory)
|
12
|
+
}
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
context '.Integer|.Float' do
|
15
|
+
let(:input){ '.Integer|.Float' }
|
15
16
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|