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 CHANGED
@@ -1,4 +1,8 @@
1
1
 
2
+ 2011-04-26 version 0.1.1
3
+
4
+ * Added RPC support
5
+
2
6
  2011-04-23 version 0.1.0
3
7
 
4
8
  * Initial release
@@ -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, funcs)
155
+ def initialize(name, version, functions)
98
156
  @name = name
99
157
  @version = version
100
- @funcs = funcs
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.show(name)
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
- puts "# #{name} - #{summary} example"
33
- puts code
34
- nil
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
- $ msgpack-idl --update java
44
+ $ #{prog} --update java
43
45
 
44
46
  - show examples
45
- $ msgpack-idl --example # show list of examples
46
- $ msgpack-idl --example "types"
47
+ $ #{prog} --example # show list of examples
48
+ $ #{prog} --example "types"
47
49
 
48
50
  - generate sample code
49
- $ msgpack-idl --update java
50
- $ msgpack-idl --example sample > sample.msgspec
51
- $ msgpack-idl -g java sample.msgspec
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 available language modules') {
87
+ op.on('--list', 'show list of installed language modules') {
86
88
  cmd = :list
87
89
  }
88
90
 
89
- op.on_tail('--help', 'show this message') {
91
+ op.on('--help', 'show this message') {
90
92
  usage nil
91
93
  }
92
94
 
93
- op.on_tail('--version', 'show version') {
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}#{" "*(10-name.length)}: #{summary}"
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.show(name)
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
- dirs = Gem.all_load_paths.grep("msgpack-idl")
182
- dirs.each {|dir|
183
- path = File.join(dir, "msgpack/idl/lang")
184
- if File.directory?(path)
185
- list.concat Dir.entries(path)
186
- end
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
- parser = MessagePack::IDL::Parser.new
232
- files.each {|path|
233
- if path == "-"
234
- text = STDIN.read
235
- parser.parse(text, '(stdin)', '.')
236
- else
237
- parser.parse_file(path)
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
- if conf[:show_ast]
243
- require 'pp'
244
- $stderr.puts "AST:"
245
- $stderr.puts ast.pretty_inspect
246
- end
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
- ev = MessagePack::IDL::Evaluator.new
249
- ev.evaluate(ast)
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
- if conf[:show_ir]
254
- require 'pp'
255
- $stderr.puts "IR:"
256
- $stderr.puts ir.pretty_inspect
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