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
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
|