msgpack-idl 0.1.0 → 0.1.1

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