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
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
# 0.3.0 / 2014-03-09
|
2
|
+
|
3
|
+
* Added AnyType abstraction, aka '.'
|
4
|
+
* Added support for external contracts in ADTs
|
5
|
+
* Added support for extracting an Abstract Syntax Tree from parsing result
|
6
|
+
* Allows camelCasing in constraint names
|
7
|
+
|
1
8
|
# 0.2.0 / 2014-03-04
|
2
9
|
|
3
10
|
* Fix dependencies in gemspec (judofyr)
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -34,7 +34,7 @@ JSON
|
|
34
34
|
puts schema.dress(data)
|
35
35
|
```
|
36
36
|
|
37
|
-
##
|
37
|
+
## ADTs with internal contracts
|
38
38
|
|
39
39
|
Qrb tries to provide an idiomatic binding for ruby developers. In particular,
|
40
40
|
it uses a simple convention-over-configuration protocol for information
|
@@ -71,12 +71,41 @@ class Color
|
|
71
71
|
end
|
72
72
|
```
|
73
73
|
|
74
|
+
## ADTs with external contracts
|
75
|
+
|
76
|
+
When the scenario above is not possible or not wanted (would require core
|
77
|
+
extensions for instance), Qrb allows defining ADTs with external contracts.
|
78
|
+
The following ADT definition:
|
79
|
+
|
80
|
+
```ruby
|
81
|
+
Color = .Color <rgb> {r: Byte, g: Byte, b: Byte} ColorContract
|
82
|
+
```
|
83
|
+
|
84
|
+
expected the following ruby module:
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
module ColorContract
|
88
|
+
|
89
|
+
def self.dress(tuple)
|
90
|
+
Color.new(tuple[:r], tuple[:g], tuple[:b])
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.undress(color)
|
94
|
+
{ r: color.r, g: color.g, b: color.b }
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
```
|
99
|
+
|
74
100
|
## About representations
|
75
101
|
|
76
102
|
The `Rep` representation function mapping Q types to ruby classes is as
|
77
103
|
follows:
|
78
104
|
|
79
105
|
```ruby
|
106
|
+
# Any type is represented by Ruby's Object class
|
107
|
+
Rep(.) = Object
|
108
|
+
|
80
109
|
# Builtins are represented by the corresponding ruby class
|
81
110
|
Rep(.Builtin) = Builtin
|
82
111
|
|
data/lib/qrb.rb
CHANGED
@@ -10,6 +10,7 @@ module Qrb
|
|
10
10
|
:attribute,
|
11
11
|
:heading,
|
12
12
|
:constraints,
|
13
|
+
:any,
|
13
14
|
:builtin,
|
14
15
|
:adt,
|
15
16
|
:subtype,
|
@@ -43,6 +44,11 @@ module Qrb
|
|
43
44
|
Syntax.compile(source)
|
44
45
|
end
|
45
46
|
|
47
|
+
def ast(source)
|
48
|
+
require "qrb/syntax"
|
49
|
+
Syntax.ast(source)
|
50
|
+
end
|
51
|
+
|
46
52
|
def system(identifier)
|
47
53
|
f = File.expand_path("../qrb/#{identifier}.q", __FILE__)
|
48
54
|
if File.exists?(f)
|
data/lib/qrb/data_type.rb
CHANGED
@@ -6,7 +6,13 @@ module Qrb
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def contract(name, infotype)
|
9
|
-
|
9
|
+
dresser = method(name)
|
10
|
+
undresser = instance_method(:"to_#{name}")
|
11
|
+
ad_contracts[name] = [
|
12
|
+
Qrb.type(infotype),
|
13
|
+
dresser,
|
14
|
+
->(d){ undresser.bind(d).call }
|
15
|
+
]
|
10
16
|
end
|
11
17
|
|
12
18
|
private
|
@@ -97,6 +97,12 @@ module Qrb
|
|
97
97
|
|
98
98
|
########################################################## Type generators
|
99
99
|
|
100
|
+
def any(name = nil)
|
101
|
+
name = name(name)
|
102
|
+
|
103
|
+
AnyType.new(name)
|
104
|
+
end
|
105
|
+
|
100
106
|
def builtin(ruby_type, name = nil)
|
101
107
|
ruby_type = ruby_type(ruby_type)
|
102
108
|
name = name(name)
|
data/lib/qrb/syntax.rb
CHANGED
@@ -6,6 +6,7 @@ require_relative 'syntax/type_def'
|
|
6
6
|
require_relative 'syntax/expression'
|
7
7
|
require_relative 'syntax/attribute'
|
8
8
|
require_relative 'syntax/heading'
|
9
|
+
require_relative 'syntax/any_type'
|
9
10
|
require_relative 'syntax/builtin_type'
|
10
11
|
require_relative 'syntax/sub_type'
|
11
12
|
require_relative 'syntax/constraint_def'
|
@@ -20,6 +21,8 @@ require_relative 'syntax/union_type'
|
|
20
21
|
require_relative 'syntax/type_ref'
|
21
22
|
require_relative 'syntax/ad_type'
|
22
23
|
require_relative 'syntax/contract'
|
24
|
+
require_relative 'syntax/inline_pair'
|
25
|
+
require_relative 'syntax/external_pair'
|
23
26
|
require_relative 'syntax/lambda_expr'
|
24
27
|
module Qrb
|
25
28
|
module Syntax
|
@@ -30,6 +33,10 @@ module Qrb
|
|
30
33
|
Parser.parse(*args, &bl)
|
31
34
|
end
|
32
35
|
|
36
|
+
def self.ast(source)
|
37
|
+
Parser.parse(source, root: "system").to_ast
|
38
|
+
end
|
39
|
+
|
33
40
|
def self.compile(source, system = Qrb::System.new)
|
34
41
|
Parser.parse(source, root: "system").compile(system)
|
35
42
|
end
|
data/lib/qrb/syntax/ad_type.rb
CHANGED
data/lib/qrb/syntax/attribute.rb
CHANGED
data/lib/qrb/syntax/contract.rb
CHANGED
@@ -3,23 +3,35 @@ module Qrb
|
|
3
3
|
module Contract
|
4
4
|
|
5
5
|
def compile(factory, clazz)
|
6
|
-
contract = [
|
7
|
-
type.compile(factory),
|
8
|
-
compile_upper(factory, clazz)
|
9
|
-
]
|
6
|
+
contract = [ type.compile(factory) ] + compile_pair(factory, clazz)
|
10
7
|
{ contract_name.to_sym => contract }
|
11
8
|
end
|
12
9
|
|
13
|
-
def
|
14
|
-
if
|
15
|
-
|
10
|
+
def compile_pair(factory, clazz)
|
11
|
+
if pair
|
12
|
+
pair.compile(factory)
|
16
13
|
elsif clazz
|
17
|
-
clazz.method(contract_name.to_sym)
|
14
|
+
dresser = clazz.method(contract_name.to_sym)
|
15
|
+
undresser = clazz.instance_method(:"to_#{contract_name}")
|
16
|
+
[
|
17
|
+
dresser,
|
18
|
+
->(d){ undresser.bind(d).call }
|
19
|
+
]
|
18
20
|
else
|
19
|
-
Qrb::IDENTITY
|
21
|
+
[ Qrb::IDENTITY, Qrb::IDENTITY ]
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
def to_ast
|
26
|
+
ast = [
|
27
|
+
:contract,
|
28
|
+
contract_name.to_s,
|
29
|
+
(type && type.to_ast)
|
30
|
+
]
|
31
|
+
ast << pair.to_ast if pair
|
32
|
+
ast
|
33
|
+
end
|
34
|
+
|
23
35
|
end # module Contract
|
24
36
|
end # module Syntax
|
25
37
|
end # module Qrb
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Qrb
|
2
|
+
module Syntax
|
3
|
+
module ExternalPair
|
4
|
+
include Support
|
5
|
+
|
6
|
+
def compile(factory)
|
7
|
+
clazz = resolve_ruby_const(builtin_type_name.to_s)
|
8
|
+
[ clazz.method(:dress), clazz.method(:undress) ]
|
9
|
+
end
|
10
|
+
|
11
|
+
def to_ast
|
12
|
+
[ :external_pair, builtin_type_name.to_s ]
|
13
|
+
end
|
14
|
+
|
15
|
+
end # module ExternalPair
|
16
|
+
end # module Syntax
|
17
|
+
end # module Qrb
|
data/lib/qrb/syntax/heading.rb
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Qrb
|
2
|
+
module Syntax
|
3
|
+
module InlinePair
|
4
|
+
include Support
|
5
|
+
|
6
|
+
def compile(factory)
|
7
|
+
[ dress.compile(factory), undress.compile(factory) ]
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_ast
|
11
|
+
[ :inline_pair, dress.to_ast, undress.to_ast ]
|
12
|
+
end
|
13
|
+
|
14
|
+
end # module InlinePair
|
15
|
+
end # module Syntax
|
16
|
+
end # module Qrb
|
@@ -6,6 +6,12 @@ module Qrb
|
|
6
6
|
{ constraint_name.to_sym => expression.compile(var_name) }
|
7
7
|
end
|
8
8
|
|
9
|
+
def to_ast(var_name)
|
10
|
+
[ :constraint,
|
11
|
+
constraint_name.to_s,
|
12
|
+
[:fn, [:parameters, var_name], [:source, expression.to_s.strip]] ]
|
13
|
+
end
|
14
|
+
|
9
15
|
end # module NamedConstraint
|
10
16
|
end # module Syntax
|
11
17
|
end # module Qrb
|
data/lib/qrb/syntax/q.citrus
CHANGED
@@ -108,6 +108,7 @@ grammar Qrb::Syntax::Parser
|
|
108
108
|
rule term_type
|
109
109
|
ad_type
|
110
110
|
| builtin_type
|
111
|
+
| any_type
|
111
112
|
| type_ref
|
112
113
|
end
|
113
114
|
|
@@ -119,10 +120,32 @@ grammar Qrb::Syntax::Parser
|
|
119
120
|
end
|
120
121
|
|
121
122
|
rule contract
|
122
|
-
('<' contract_name '>' spacing type
|
123
|
+
('<' contract_name '>' spacing type spacing pair?)
|
123
124
|
<Qrb::Syntax::Contract>
|
124
125
|
end
|
125
126
|
|
127
|
+
rule pair
|
128
|
+
inline_pair
|
129
|
+
| external_pair
|
130
|
+
end
|
131
|
+
|
132
|
+
rule inline_pair
|
133
|
+
('\\' dress:lambda_expr spacing '\\' undress:lambda_expr)
|
134
|
+
<Qrb::Syntax::InlinePair>
|
135
|
+
end
|
136
|
+
|
137
|
+
rule external_pair
|
138
|
+
('.' builtin_type_name)
|
139
|
+
<Qrb::Syntax::ExternalPair>
|
140
|
+
end
|
141
|
+
|
142
|
+
# any
|
143
|
+
|
144
|
+
rule any_type
|
145
|
+
'.'
|
146
|
+
<Qrb::Syntax::AnyType>
|
147
|
+
end
|
148
|
+
|
126
149
|
# builtin and refs
|
127
150
|
|
128
151
|
rule builtin_type
|
@@ -150,7 +173,7 @@ grammar Qrb::Syntax::Parser
|
|
150
173
|
<Qrb::Syntax::Expression>
|
151
174
|
end
|
152
175
|
|
153
|
-
#
|
176
|
+
# LEXER (names)
|
154
177
|
|
155
178
|
rule var_name
|
156
179
|
/[a-z]+/
|
@@ -161,7 +184,7 @@ grammar Qrb::Syntax::Parser
|
|
161
184
|
end
|
162
185
|
|
163
186
|
rule constraint_name
|
164
|
-
/[a-z][a-
|
187
|
+
/[a-z][a-zA-Z_]*/
|
165
188
|
end
|
166
189
|
|
167
190
|
rule attribute_name
|
@@ -173,9 +196,11 @@ grammar Qrb::Syntax::Parser
|
|
173
196
|
end
|
174
197
|
|
175
198
|
rule builtin_type_name
|
176
|
-
/[a-zA-Z0-9:]
|
199
|
+
/[a-zA-Z0-9:]+/
|
177
200
|
end
|
178
201
|
|
202
|
+
# LEXER (spacing & comments)
|
203
|
+
|
179
204
|
rule spacing
|
180
205
|
(spaces | comment)*
|
181
206
|
end
|