msgpack-idl 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +4 -0
- data/lib/msgpack/idl/ast.rb +164 -3
- data/lib/msgpack/idl/command/example.rb +64 -4
- data/lib/msgpack/idl/command/idl.rb +75 -42
- data/lib/msgpack/idl/command/vimcolor.rb +254 -0
- data/lib/msgpack/idl/command/vimcolor/mark.vim +67 -0
- data/lib/msgpack/idl/command/vimcolor/msgspec.vim +68 -0
- data/lib/msgpack/idl/error.rb +1 -1
- data/lib/msgpack/idl/evaluator.rb +283 -138
- data/lib/msgpack/idl/ir.rb +31 -6
- data/lib/msgpack/idl/parser/rule.rb +20 -3
- data/lib/msgpack/idl/parser/transform.rb +15 -18
- data/lib/msgpack/idl/version.rb +1 -1
- metadata +7 -4
data/ChangeLog
CHANGED
data/lib/msgpack/idl/ast.rb
CHANGED
@@ -20,7 +20,21 @@ module IDL
|
|
20
20
|
|
21
21
|
|
22
22
|
module AST
|
23
|
+
SUMMARY_LINES = 6
|
24
|
+
|
23
25
|
class Element
|
26
|
+
alias text to_s
|
27
|
+
|
28
|
+
def summary
|
29
|
+
t = text
|
30
|
+
lines = t.split("\n")
|
31
|
+
return t if lines.size <= SUMMARY_LINES
|
32
|
+
if lines.last == "}"
|
33
|
+
(lines[0,SUMMARY_LINES-2] + [" ...", "}"]).join("\n")
|
34
|
+
else
|
35
|
+
(lines[0,SUMMARY_LINES-1] + [" ..."]).join("\n")
|
36
|
+
end
|
37
|
+
end
|
24
38
|
end
|
25
39
|
|
26
40
|
class Document < Array
|
@@ -31,6 +45,10 @@ module AST
|
|
31
45
|
@path = path
|
32
46
|
end
|
33
47
|
attr_reader :path
|
48
|
+
|
49
|
+
def text
|
50
|
+
"include #{@path}"
|
51
|
+
end
|
34
52
|
end
|
35
53
|
|
36
54
|
|
@@ -40,6 +58,14 @@ module AST
|
|
40
58
|
@lang = lang
|
41
59
|
end
|
42
60
|
attr_reader :scopes, :lang
|
61
|
+
|
62
|
+
def text
|
63
|
+
if @lang
|
64
|
+
"namespace #{@lang} #{@scopes.join('.')}"
|
65
|
+
else
|
66
|
+
"namespace #{@scopes.join('.')}"
|
67
|
+
end
|
68
|
+
end
|
43
69
|
end
|
44
70
|
|
45
71
|
|
@@ -50,6 +76,15 @@ module AST
|
|
50
76
|
@fields = fields
|
51
77
|
end
|
52
78
|
attr_reader :name, :super_class, :fields
|
79
|
+
|
80
|
+
def text
|
81
|
+
t = "message #{@name}"
|
82
|
+
t << " < #{@super_class.text}" if @super_class
|
83
|
+
t << " {\n"
|
84
|
+
t << @fields.map {|f| " #{f.text}\n" }.join
|
85
|
+
t << "}"
|
86
|
+
t
|
87
|
+
end
|
53
88
|
end
|
54
89
|
|
55
90
|
|
@@ -65,6 +100,14 @@ module AST
|
|
65
100
|
@modifier = modifier
|
66
101
|
end
|
67
102
|
attr_reader :id, :type, :name, :modifier
|
103
|
+
|
104
|
+
def text
|
105
|
+
if @modifier == FIELD_OPTIONAL
|
106
|
+
"#{@id}: optional #{@type.text} #{@name}"
|
107
|
+
else
|
108
|
+
"#{@id}: #{@type.text} #{@name}"
|
109
|
+
end
|
110
|
+
end
|
68
111
|
end
|
69
112
|
|
70
113
|
class ValueAssignedField < Field
|
@@ -73,6 +116,10 @@ module AST
|
|
73
116
|
@value = value
|
74
117
|
end
|
75
118
|
attr_reader :value
|
119
|
+
|
120
|
+
def text
|
121
|
+
"#{super} = #{@value.text}"
|
122
|
+
end
|
76
123
|
end
|
77
124
|
|
78
125
|
|
@@ -82,6 +129,13 @@ module AST
|
|
82
129
|
@fields = fields
|
83
130
|
end
|
84
131
|
attr_reader :name, :fields
|
132
|
+
|
133
|
+
def text
|
134
|
+
t = "enum #{@name} {\n"
|
135
|
+
t << @fields.map {|f| " #{f.text}\n" }.join
|
136
|
+
t << "}"
|
137
|
+
t
|
138
|
+
end
|
85
139
|
end
|
86
140
|
|
87
141
|
class EnumField < Element
|
@@ -90,16 +144,65 @@ module AST
|
|
90
144
|
@name = name
|
91
145
|
end
|
92
146
|
attr_reader :id, :name
|
147
|
+
|
148
|
+
def text
|
149
|
+
"#{@id}: #{@name}"
|
150
|
+
end
|
93
151
|
end
|
94
152
|
|
95
153
|
|
96
154
|
class Service < Element
|
97
|
-
def initialize(name, version,
|
155
|
+
def initialize(name, version, functions)
|
98
156
|
@name = name
|
99
157
|
@version = version
|
100
|
-
@
|
158
|
+
@functions = functions
|
159
|
+
end
|
160
|
+
attr_reader :name, :version, :functions
|
161
|
+
|
162
|
+
def text
|
163
|
+
t = "service #{@name}"
|
164
|
+
t << ":#{@version}" if @version
|
165
|
+
t << " {\n"
|
166
|
+
t << @functions.map {|f| " #{f.text}\n" }.join
|
167
|
+
t << "}"
|
168
|
+
t
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
class Inherit < Element
|
173
|
+
end
|
174
|
+
|
175
|
+
class InheritAll < Inherit
|
176
|
+
def text
|
177
|
+
"inherit *"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
class InheritName < Inherit
|
182
|
+
def initialize(name)
|
183
|
+
@name = name
|
184
|
+
end
|
185
|
+
attr_reader :name
|
186
|
+
|
187
|
+
def text
|
188
|
+
"inherit #{@name}"
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
class InheritFunc < Inherit
|
193
|
+
def initialize(name, return_type, args, exceptions)
|
194
|
+
@name = name
|
195
|
+
@return_type = return_type
|
196
|
+
@args = args
|
197
|
+
@exceptions = exceptions
|
198
|
+
end
|
199
|
+
attr_reader :name, :return_type, :args, :exceptions
|
200
|
+
|
201
|
+
def text
|
202
|
+
t = "inherit #{@return_type.text} #{@name}(#{@args.map {|a| a.text }.join(', ') })"
|
203
|
+
t << " throws #{@exceptions.map {|ex| ex.text }.join(', ')}" if @exceptions && !@exceptions.empty?
|
204
|
+
t
|
101
205
|
end
|
102
|
-
attr_reader :name, :version, :funcs
|
103
206
|
end
|
104
207
|
|
105
208
|
class Func < Element
|
@@ -110,6 +213,12 @@ module AST
|
|
110
213
|
@exceptions = exceptions
|
111
214
|
end
|
112
215
|
attr_reader :name, :return_type, :args, :exceptions
|
216
|
+
|
217
|
+
def text
|
218
|
+
t = "#{@return_type.text} #{@name}(#{@args.map {|a| a.text }.join(', ')})"
|
219
|
+
t << " throws #{@exceptions.map {|ex| ex.text }.join(', ')}" if @exceptions && !@exceptions.empty?
|
220
|
+
t
|
221
|
+
end
|
113
222
|
end
|
114
223
|
|
115
224
|
|
@@ -121,6 +230,13 @@ module AST
|
|
121
230
|
|
122
231
|
attr_reader :name
|
123
232
|
attr_reader :scopes
|
233
|
+
|
234
|
+
def text
|
235
|
+
t = "application #{@name} {\n"
|
236
|
+
t << @scopes.map {|sc| " #{sc.text}\n" }.join
|
237
|
+
t << "}"
|
238
|
+
t
|
239
|
+
end
|
124
240
|
end
|
125
241
|
|
126
242
|
class Scope < Element
|
@@ -135,6 +251,12 @@ module AST
|
|
135
251
|
def default?
|
136
252
|
@default
|
137
253
|
end
|
254
|
+
|
255
|
+
def text
|
256
|
+
t = "#{@service}:#{@version} #{@name}"
|
257
|
+
t << " default" if @default
|
258
|
+
t
|
259
|
+
end
|
138
260
|
end
|
139
261
|
|
140
262
|
|
@@ -148,6 +270,14 @@ module AST
|
|
148
270
|
def nullable?
|
149
271
|
@nullable
|
150
272
|
end
|
273
|
+
|
274
|
+
def text
|
275
|
+
if @nullable
|
276
|
+
"#{@name}?"
|
277
|
+
else
|
278
|
+
"#{@name}"
|
279
|
+
end
|
280
|
+
end
|
151
281
|
end
|
152
282
|
|
153
283
|
class GenericType < Type
|
@@ -156,6 +286,10 @@ module AST
|
|
156
286
|
@type_params = type_params
|
157
287
|
end
|
158
288
|
attr_reader :type_params
|
289
|
+
|
290
|
+
def text
|
291
|
+
"#{super}<#{@type_params.map {|tp| tp.text }.join(',')}>"
|
292
|
+
end
|
159
293
|
end
|
160
294
|
|
161
295
|
FIELD_OPTIONAL = :optional
|
@@ -170,6 +304,10 @@ module AST
|
|
170
304
|
@name = name
|
171
305
|
end
|
172
306
|
attr_reader :name
|
307
|
+
|
308
|
+
def text
|
309
|
+
"#{@name}"
|
310
|
+
end
|
173
311
|
end
|
174
312
|
|
175
313
|
class EnumLiteral < Literal
|
@@ -178,6 +316,10 @@ module AST
|
|
178
316
|
@field = field
|
179
317
|
end
|
180
318
|
attr_reader :name, :field
|
319
|
+
|
320
|
+
def text
|
321
|
+
"#{@name}.#{@field}"
|
322
|
+
end
|
181
323
|
end
|
182
324
|
|
183
325
|
class IntLiteral < Literal
|
@@ -185,6 +327,10 @@ module AST
|
|
185
327
|
@value = value
|
186
328
|
end
|
187
329
|
attr_reader :value
|
330
|
+
|
331
|
+
def text
|
332
|
+
"#{@value}"
|
333
|
+
end
|
188
334
|
end
|
189
335
|
|
190
336
|
class FlaotLiteral < Literal
|
@@ -192,9 +338,16 @@ module AST
|
|
192
338
|
@value = value
|
193
339
|
end
|
194
340
|
attr_reader :value
|
341
|
+
|
342
|
+
def text
|
343
|
+
"#{@value}"
|
344
|
+
end
|
195
345
|
end
|
196
346
|
|
197
347
|
class NilLiteral < Literal
|
348
|
+
def text
|
349
|
+
%[nil]
|
350
|
+
end
|
198
351
|
end
|
199
352
|
|
200
353
|
class BoolLiteral < Literal
|
@@ -202,6 +355,10 @@ module AST
|
|
202
355
|
@value = value
|
203
356
|
end
|
204
357
|
attr_reader :value
|
358
|
+
|
359
|
+
def text
|
360
|
+
"#{@value}"
|
361
|
+
end
|
205
362
|
end
|
206
363
|
|
207
364
|
class TrueLiteral < BoolLiteral
|
@@ -220,6 +377,10 @@ module AST
|
|
220
377
|
def initialize(value)
|
221
378
|
@value = value
|
222
379
|
end
|
380
|
+
|
381
|
+
def text
|
382
|
+
@value.dump
|
383
|
+
end
|
223
384
|
end
|
224
385
|
|
225
386
|
#class ListLiteral < Literal
|
@@ -22,16 +22,16 @@ module Example
|
|
22
22
|
LIST
|
23
23
|
end
|
24
24
|
|
25
|
-
def self.
|
25
|
+
def self.get(name)
|
26
26
|
n, summary, code = LIST.find {|n, summary, code|
|
27
27
|
name == n
|
28
28
|
}
|
29
29
|
unless code
|
30
30
|
raise "unknown example name: #{name}"
|
31
31
|
end
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
result = "# #{name} - #{summary} example\n"
|
33
|
+
result << code
|
34
|
+
result
|
35
35
|
end
|
36
36
|
|
37
37
|
def self.add(name, summary, code)
|
@@ -129,6 +129,66 @@ message LogInLog {
|
|
129
129
|
1: UserInfo user
|
130
130
|
2: Sites site
|
131
131
|
}
|
132
|
+
EOF
|
133
|
+
|
134
|
+
add 'service', 'simple rpc', <<EOF
|
135
|
+
exception DiskError {
|
136
|
+
1: string message
|
137
|
+
}
|
138
|
+
|
139
|
+
service PropertyStoreService {
|
140
|
+
raw? get(1: raw key)
|
141
|
+
void set(1: raw key, 2: raw value) throws DiskError
|
142
|
+
}
|
143
|
+
EOF
|
144
|
+
|
145
|
+
add 'version', 'versioned rpc', <<EOF
|
146
|
+
exception DiskError {
|
147
|
+
1: string message
|
148
|
+
}
|
149
|
+
|
150
|
+
service PropertyStoreService:0 {
|
151
|
+
void set(1: raw key, 2: raw value)
|
152
|
+
raw? get(1: raw key)
|
153
|
+
}
|
154
|
+
|
155
|
+
service PropertyStoreService:1 {
|
156
|
+
void set(1: raw key, 2: raw value) throws DiskError
|
157
|
+
|
158
|
+
# inherit former version's function
|
159
|
+
inherit get
|
160
|
+
}
|
161
|
+
|
162
|
+
service PropertyStoreService:2 {
|
163
|
+
void set(1: raw key, 2: raw value, 3: int flags) throws DiskError
|
164
|
+
|
165
|
+
# type-checked inheritance
|
166
|
+
inherit raw? get(1: raw key)
|
167
|
+
|
168
|
+
int? getFlags(1: raw key)
|
169
|
+
}
|
170
|
+
|
171
|
+
service PropertyStoreService:3 {
|
172
|
+
# inherit all functions
|
173
|
+
inherit *
|
174
|
+
}
|
175
|
+
EOF
|
176
|
+
|
177
|
+
add 'application', 'multi-namespace rpc', <<EOF
|
178
|
+
service KeyValueService:0 {
|
179
|
+
void set(1: raw key, 2: raw value)
|
180
|
+
raw? get(1: raw key)
|
181
|
+
}
|
182
|
+
|
183
|
+
service CacheService:0 {
|
184
|
+
void set(1: raw key, 2: raw value, 3: long expire)
|
185
|
+
raw? get(1: raw key)
|
186
|
+
}
|
187
|
+
|
188
|
+
application MyApp {
|
189
|
+
KeyValueService:0 kv default
|
190
|
+
CacheService:0 cache
|
191
|
+
}
|
132
192
|
EOF
|
133
193
|
|
134
194
|
end
|
@@ -29,6 +29,8 @@ Usage: #{prog} [options] -g LANG files...
|
|
29
29
|
options:
|
30
30
|
EOF
|
31
31
|
|
32
|
+
op.summary_indent = " "
|
33
|
+
|
32
34
|
comment = <<EOF
|
33
35
|
examples:
|
34
36
|
- generate java code from test.msgspec file:
|
@@ -36,19 +38,19 @@ examples:
|
|
36
38
|
$ ls gen-java # generated codes are here
|
37
39
|
|
38
40
|
- generate java code from test.msgspec file to ./out directory:
|
39
|
-
$ #{prog} -g java -o out test.msgspec
|
41
|
+
$ #{prog} -g java -o ./out test.msgspec
|
40
42
|
|
41
43
|
- install or update language module
|
42
|
-
$
|
44
|
+
$ #{prog} --update java
|
43
45
|
|
44
46
|
- show examples
|
45
|
-
$
|
46
|
-
$
|
47
|
+
$ #{prog} --example # show list of examples
|
48
|
+
$ #{prog} --example "types"
|
47
49
|
|
48
50
|
- generate sample code
|
49
|
-
$
|
50
|
-
$
|
51
|
-
$
|
51
|
+
$ #{prog} --install java
|
52
|
+
$ #{prog} --example sample > sample.msgspec
|
53
|
+
$ #{prog} -g java sample.msgspec
|
52
54
|
EOF
|
53
55
|
|
54
56
|
(class<<self;self;end).module_eval do
|
@@ -82,15 +84,15 @@ op.on('--update', 'install or update a language module') {
|
|
82
84
|
cmd = :update
|
83
85
|
}
|
84
86
|
|
85
|
-
op.on('--list', 'show list of
|
87
|
+
op.on('--list', 'show list of installed language modules') {
|
86
88
|
cmd = :list
|
87
89
|
}
|
88
90
|
|
89
|
-
op.
|
91
|
+
op.on('--help', 'show this message') {
|
90
92
|
usage nil
|
91
93
|
}
|
92
94
|
|
93
|
-
op.
|
95
|
+
op.on('--version', 'show version') {
|
94
96
|
require 'msgpack/idl/version'
|
95
97
|
puts MessagePack::IDL::VERSION
|
96
98
|
exit 0
|
@@ -124,11 +126,22 @@ when :example
|
|
124
126
|
|
125
127
|
def show_available_examples
|
126
128
|
puts "available examples:"
|
129
|
+
name_max = Example.list.max {|name,_,_| name.length }[0].length
|
127
130
|
Example.list.each {|name,summary,code|
|
128
|
-
puts " #{name}#{" "*(
|
131
|
+
puts " #{name}#{" "*(name_max+2-name.length)}: #{summary}"
|
129
132
|
}
|
130
133
|
end
|
131
134
|
|
135
|
+
def try_color_print(code)
|
136
|
+
require 'msgpack/idl/command/vimcolor'
|
137
|
+
syntax = File.join(
|
138
|
+
File.expand_path(File.dirname(__FILE__)), 'vimcolor', 'msgspec.vim')
|
139
|
+
vc = VimColor.new('vim', nil, nil, [":filetype off", ":source #{syntax}"])
|
140
|
+
puts vc.run(code, 'msgspec', :ansi)
|
141
|
+
rescue
|
142
|
+
puts code
|
143
|
+
end
|
144
|
+
|
132
145
|
if ARGV.length == 0
|
133
146
|
show_available_examples
|
134
147
|
exit 1
|
@@ -139,7 +152,7 @@ when :example
|
|
139
152
|
|
140
153
|
name = ARGV[0]
|
141
154
|
begin
|
142
|
-
Example.
|
155
|
+
code = Example.get(name)
|
143
156
|
rescue
|
144
157
|
show_available_examples
|
145
158
|
puts ""
|
@@ -147,6 +160,12 @@ when :example
|
|
147
160
|
exit 1
|
148
161
|
end
|
149
162
|
|
163
|
+
if STDOUT.tty?
|
164
|
+
try_color_print(code)
|
165
|
+
else
|
166
|
+
puts code
|
167
|
+
end
|
168
|
+
|
150
169
|
when :update
|
151
170
|
require 'rubygems'
|
152
171
|
require 'rubygems/gem_runner'
|
@@ -178,13 +197,14 @@ when :update
|
|
178
197
|
|
179
198
|
when :list
|
180
199
|
list = []
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
list
|
186
|
-
|
200
|
+
langdir = File.join('lib', 'msgpack', 'idl', 'lang')
|
201
|
+
Gem.path.each {|gemdir|
|
202
|
+
pattern = File.join(gemdir, 'gems', 'msgpack-idl-*', 'lib', 'msgpack', 'idl', 'lang', '*.rb')
|
203
|
+
Dir.glob(pattern).each {|path|
|
204
|
+
list << File.basename(path, '.rb')
|
205
|
+
}
|
187
206
|
}
|
207
|
+
list = list.sort.uniq
|
188
208
|
|
189
209
|
puts "available language modules:"
|
190
210
|
list.each {|lang|
|
@@ -221,6 +241,7 @@ when :generate
|
|
221
241
|
rescue LoadError
|
222
242
|
available = false
|
223
243
|
end
|
244
|
+
|
224
245
|
if !available || !MessagePack::IDL::Generator.available?(lang)
|
225
246
|
puts "Language module #{lang.dump} is not available."
|
226
247
|
puts "Try to install it as follows:"
|
@@ -228,35 +249,47 @@ when :generate
|
|
228
249
|
exit 1
|
229
250
|
end
|
230
251
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
252
|
+
begin
|
253
|
+
parser = MessagePack::IDL::Parser.new
|
254
|
+
files.each {|path|
|
255
|
+
if path == "-"
|
256
|
+
text = STDIN.read
|
257
|
+
parser.parse(text, '(stdin)', '.')
|
258
|
+
else
|
259
|
+
parser.parse_file(path)
|
260
|
+
end
|
261
|
+
}
|
262
|
+
ast = parser.ast
|
263
|
+
|
264
|
+
if conf[:show_ast]
|
265
|
+
require 'pp'
|
266
|
+
$stderr.puts "AST:"
|
267
|
+
$stderr.puts ast.pretty_inspect
|
238
268
|
end
|
239
|
-
}
|
240
|
-
ast = parser.ast
|
241
269
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
270
|
+
ev = MessagePack::IDL::Evaluator.new
|
271
|
+
ev.evaluate(ast)
|
272
|
+
ev.evaluate_inheritance
|
273
|
+
ir = ev.evaluate_spec(lang)
|
274
|
+
|
275
|
+
if conf[:show_ir]
|
276
|
+
require 'pp'
|
277
|
+
$stderr.puts "IR:"
|
278
|
+
$stderr.puts ir.pretty_inspect
|
279
|
+
end
|
247
280
|
|
248
|
-
|
249
|
-
|
250
|
-
ev.evaluate_inheritance
|
251
|
-
ir = ev.evaluate_spec(lang)
|
281
|
+
gen = MessagePack::IDL::Generator.new
|
282
|
+
gen.generate(lang, ir, out)
|
252
283
|
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
284
|
+
rescue MessagePack::IDL::SyntaxError => error
|
285
|
+
puts error.to_s
|
286
|
+
puts ""
|
287
|
+
exit 1
|
288
|
+
rescue MessagePack::IDL::SemanticsError => error
|
289
|
+
puts error.to_s
|
290
|
+
puts ""
|
291
|
+
exit 1
|
257
292
|
end
|
258
293
|
|
259
|
-
gen = MessagePack::IDL::Generator.new
|
260
|
-
gen.generate(lang, ir, out)
|
261
294
|
end
|
262
295
|
|