qrb 0.2.0 → 0.3.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.
- 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
|