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.
@@ -0,0 +1,254 @@
1
+ #
2
+ # VimColor for Ruby
3
+ #
4
+ # Copyright (c) 2008-2011 FURUHASHI Sadayuki
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+
25
+ class VimColor
26
+ VIM_COMMAND = "vim"
27
+ VIM_OPTIONS = %w[-R -X -Z -i NONE -u NONE -N]
28
+ VIM_PRESET = ["+set nomodeline", '+set expandtab'] # +set shiftwidth
29
+ VIM_POSTSET = [":let b:is_bash=1", ":filetype on"]
30
+ VIM_MARK_SCRIPT = File.join(File.dirname(__FILE__), 'vimcolor', 'mark.vim')
31
+ VIM_UNESCAPE = {'&l' => '<', '&g' => '>', '&a' => '&'}
32
+
33
+ def initialize(command=nil, options=nil, preset=nil, postset=nil)
34
+ require 'tempfile'
35
+ @command = VIM_COMMAND.dup
36
+ @options = VIM_OPTIONS + (options || [])
37
+ @preset = VIM_PRESET + (preset || [])
38
+ @postset = VIM_POSTSET + (postset || [])
39
+ end
40
+
41
+ attr_accessor :command, :options, :preset, :postset
42
+
43
+ def run_file(path, options, formatter_class, *formatter_args)
44
+ preset = @preset.dup
45
+ postset = @postset.dup
46
+
47
+ if formatter_class.class == Symbol
48
+ formatter_class = self.class.const_get("Format_#{formatter_class}")
49
+ end
50
+
51
+ if options.is_a? Hash
52
+ if options.include? :filetype
53
+ postset.unshift(":set filetype=#{options[:filetype]}")
54
+ end
55
+ if options.include? :encoding
56
+ preset.unshift("+set encoding=#{options[:encoding]}")
57
+ end
58
+ else
59
+ postset.unshift(":set filetype=#{options}")
60
+ end
61
+
62
+ vimout = nil
63
+ tmp_stream = Tempfile.new('ruby-vimcolor')
64
+ begin
65
+ tmp_path = tmp_stream.path
66
+ tmp_stream.puts <<SCRIPT
67
+ :syntax on
68
+ #{postset.join("\n")}
69
+ :source #{VIM_MARK_SCRIPT}
70
+ :write! #{tmp_path}
71
+ :qall!
72
+
73
+ SCRIPT
74
+ tmp_stream.flush
75
+ pid = Process.fork {
76
+ STDIN.reopen "/dev/null"
77
+ STDOUT.reopen "/dev/null", "a"
78
+ STDERR.reopen "/dev/null", "a"
79
+ args = []
80
+ args.concat @options
81
+ args.concat ['-s', tmp_path]
82
+ args.push path
83
+ args.concat preset
84
+ exec(@command, *args)
85
+ exit 127
86
+ }
87
+ Process.waitpid(pid)
88
+ tmp_stream.seek(0)
89
+ vimout = tmp_stream.read
90
+ ensure
91
+ tmp_stream.close
92
+ end
93
+
94
+ require 'strscan'
95
+ s = StringScanner.new(vimout)
96
+
97
+ formatter = formatter_class.new(*formatter_args)
98
+ while s.scan_until(/(.*?)>(.*?)>(.*?)<\2</m)
99
+ formatter.push('', s[1]) unless s[1].empty?
100
+ type = s[2]
101
+ text = s[3]
102
+ text.gsub!(/&[agl]/) do
103
+ VIM_UNESCAPE[$&]
104
+ end
105
+ formatter.push(type, text)
106
+ end
107
+ formatter.result
108
+ end
109
+
110
+
111
+ def run_stream(stream, options, formatter_class, *formatter_args)
112
+ tmp_in = Tempfile.new('ruby-vimcolor-input')
113
+ begin
114
+ tmp_in.write(stream.read)
115
+ tmp_in.flush
116
+ run_file(tmp_in.path, options, formatter_class, *formatter_args)
117
+ ensure
118
+ tmp_in.close
119
+ end
120
+ end
121
+
122
+
123
+ def run(str, options, formatter_class, *formatter_args)
124
+ tmp_in = Tempfile.new('ruby-vimcolor-input')
125
+ begin
126
+ tmp_in.write(str)
127
+ tmp_in.flush
128
+ run_file(tmp_in.path, options, formatter_class, *formatter_args)
129
+ ensure
130
+ tmp_in.close
131
+ end
132
+ end
133
+ end
134
+
135
+
136
+
137
+ class VimColor
138
+
139
+ class Format_array
140
+ def initialize
141
+ @result = []
142
+ end
143
+ def push(type, text)
144
+ @result.push [type, text]
145
+ end
146
+ attr_reader :result
147
+ end
148
+
149
+
150
+ class Format_xml
151
+ def initialize
152
+ @result = ''
153
+ end
154
+ def push(type, text)
155
+ VimColor._escape_xml!(text)
156
+ type = 'Normal' if type.empty?
157
+ @result << %[<#{type}>#{text}</#{type}>]
158
+ end
159
+ attr_reader :result
160
+ end
161
+
162
+
163
+ class Format_html
164
+ def initialize(class_prefix = 'syn')
165
+ @result = ''
166
+ @prefix = class_prefix
167
+ end
168
+ def push(type, text)
169
+ VimColor._escape_xml!(text)
170
+ if type.empty?
171
+ @result << text
172
+ else
173
+ @result << %[<span class="#{@prefix}#{type}">#{text}</span>]
174
+ end
175
+ end
176
+ attr_reader :result
177
+ end
178
+
179
+
180
+ def self._escape_xml!(text)
181
+ text.gsub!("&", "&amp;")
182
+ text.gsub!("<", "&lt;")
183
+ text.gsub!(">", "&gt;")
184
+ text.gsub!("'", "&#39;")
185
+ text.gsub!('"', "&quot;")
186
+ text
187
+ end
188
+
189
+
190
+ class Format_ansi
191
+ AnsiCodes = {
192
+ :normal => 0,
193
+ :reset => 0,
194
+ :bold => 1,
195
+ :dark => 2,
196
+ :italic => 3,
197
+ :underline => 4,
198
+ :blink => 5,
199
+ :rapid_blink => 6,
200
+ :negative => 7,
201
+ :concealed => 8,
202
+ :strikethrough => 9,
203
+ :black => 30,
204
+ :red => 31,
205
+ :green => 32,
206
+ :yellow => 33,
207
+ :blue => 34,
208
+ :magenta => 35,
209
+ :cyan => 36,
210
+ :white => 37,
211
+ :on_black => 40,
212
+ :on_red => 41,
213
+ :on_green => 42,
214
+ :on_yellow => 43,
215
+ :on_blue => 44,
216
+ :on_magenta => 45,
217
+ :on_cyan => 46,
218
+ :on_white => 47,
219
+ }
220
+ def initialize(colors = {})
221
+ @result = ''
222
+ @colors = Hash.new([])
223
+ @colors.merge!({
224
+ 'Comment' => [ :cyan ],
225
+ 'Constant' => [ :red ],
226
+ 'Identifier' => [ :green ],
227
+ 'Statement' => [ :yellow ],
228
+ 'PreProc' => [ :magenta ],
229
+ 'Type' => [ :green ],
230
+ 'Special' => [ :magenta ],
231
+ 'Underlined' => [ :underline ],
232
+ 'Error' => [ :red ],
233
+ 'Todo' => [ :black, :on_yellow ],
234
+ })
235
+ @colors.merge!(colors)
236
+ end
237
+ def push(type, text)
238
+ seq = ''
239
+ codes = @colors[type].dup
240
+ codes.unshift(:reset)
241
+ codes.each {|c|
242
+ num = AnsiCodes[c]
243
+ seq << "\e[#{num}m" if num
244
+ }
245
+ @result << seq << text
246
+ end
247
+ def result
248
+ @result << "\e[0m"
249
+ @result
250
+ end
251
+ end
252
+
253
+ end
254
+
@@ -0,0 +1,67 @@
1
+ " mark.vim - turn Vim syntax highlighting into an ad-hoc markup language that
2
+ " can be parsed by the Text::VimColor Perl module.
3
+ "
4
+ " Maintainer: Geoff Richards <qef@laxan.com>
5
+ " Based loosely on 2html.vim, by Bram Moolenaar <Bram@vim.org>,
6
+ " modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>.
7
+
8
+ set report=1000000
9
+
10
+ " For some reason (I'm sure it used to work) we now need to get Vim
11
+ " to make another attempt to detect the filetype if it wasn't set
12
+ " explicitly.
13
+ if !strlen(&filetype)
14
+ filetype detect
15
+ endif
16
+ "syn on
17
+
18
+ " Set up the output buffer.
19
+ new
20
+ set modifiable
21
+ set paste
22
+
23
+ " Expand tabs. Without this they come out as '^I'.
24
+ set isprint+=9
25
+
26
+ wincmd p
27
+
28
+ " Loop over all lines in the original text
29
+ let s:end = line("$")
30
+ let s:lnum = 1
31
+ while s:lnum <= s:end
32
+
33
+ " Get the current line
34
+ let s:line = getline(s:lnum)
35
+ let s:len = strlen(s:line)
36
+ let s:new = ""
37
+
38
+ " Loop over each character in the line
39
+ let s:col = 1
40
+ while s:col <= s:len
41
+ let s:startcol = s:col " The start column for processing text
42
+ let s:id = synID(s:lnum, s:col, 1)
43
+ let s:col = s:col + 1
44
+ " Speed loop (it's small - that's the trick)
45
+ " Go along till we find a change in synID
46
+ while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
47
+
48
+ " Output the text with the same synID, with class set to c{s:id}
49
+ let s:id = synIDtrans(s:id)
50
+ let s:name = synIDattr(s:id, 'name')
51
+ let s:new = s:new . '>' . s:name . '>' . substitute(substitute(substitute(strpart(s:line, s:startcol - 1, s:col - s:startcol), '&', '\&a', 'g'), '<', '\&l', 'g'), '>', '\&g', 'g') . '<' . s:name . '<'
52
+
53
+ if s:col > s:len
54
+ break
55
+ endif
56
+ endwhile
57
+
58
+ exe "normal \<C-W>pa" . strtrans(s:new) . "\n\e\<C-W>p"
59
+ let s:lnum = s:lnum + 1
60
+ +
61
+ endwhile
62
+
63
+ " Strip whitespace from the ends of lines
64
+ %s:\s\+$::e
65
+
66
+ wincmd p
67
+ normal dd
@@ -0,0 +1,68 @@
1
+
2
+ if version < 600
3
+ syntax clear
4
+ elseif exists("b:current_syntax")
5
+ finish
6
+ endif
7
+
8
+ syn case match
9
+
10
+ " Todo
11
+ syn keyword msgspecTodo TODO FIXME XXX contained
12
+
13
+ " Comments
14
+ syn match msgspecComment "#.*" contains=msgspecTodo
15
+ syn match msgspecComment "\/\/.*$" contains=msgspecTodo
16
+ syn region msgspecComment start="/\*" end="\*/" contains=msgspecTodo,msgspecComment
17
+
18
+ " Literal
19
+ syn match msgspecString "'\(\\.\|[^'\\]\)*'"
20
+ syn match msgspecString "\"\(\\.\|[^\"\\]\)*\""
21
+ syn match msgspecNumber "\<[0-9][0-9]*\(\.[0-9][0-9]*\)\?\>"
22
+ syn keyword msgspecBoolean true false
23
+
24
+ " Keywords
25
+ syn keyword msgspecKeyword default
26
+ syn keyword msgspecDeclareKeyword include namespace
27
+ syn keyword msgspecTypeKeyword const typedef typespec
28
+ syn keyword msgspecStructure interface service message exception enum application
29
+ "syn keyword msgspecStructureDeclaration import
30
+ syn keyword msgspecException throws
31
+ syn keyword msgspecModifier required optional
32
+ syn keyword msgspecBasicType void
33
+ syn keyword msgspecBasicType byte int short long
34
+ syn keyword msgspecBasicType ubyte uint ushort ulong
35
+ syn keyword msgspecBasicType float double bool string raw
36
+ syn keyword msgspecContainerType map list
37
+ "syn match msgspecSpecial "?"
38
+ syn keyword msgspecSpecial inherit
39
+ "syn keyword msgspecSpecial obsolete
40
+
41
+ " Special
42
+ syn match msgspecId "\<\d\+:"
43
+ syn match msgspecServiceVersion ":\d\+\>"
44
+
45
+ " Block
46
+ syn region msgspecBlock matchgroup=NONE start="{" end="}" contains=@msgspecBlockItems
47
+ syn cluster msgspecBlockItems contains=msgspecComment,msgspecString,msgspecNumber,msgspecKeyword,msgspecId,msgspecServiceVersion,msgspecStructureDeclaration,msgspecException,msgspecModifier,msgspecBasicType,msgspecContainerType,msgspecSpecial,msgspecBlock
48
+
49
+ hi link msgspecTodo Todo
50
+ hi link msgspecComment Comment
51
+ hi link msgspecString String
52
+ hi link msgspecNumber Number
53
+ hi link msgspecBoolean Boolean
54
+ hi link msgspecTypeKeyword Type
55
+ hi link msgspecStructure Structure
56
+ hi link msgspecStructureDeclaration Special
57
+ hi link msgspecException Exception
58
+ hi link msgspecModifier Special
59
+ hi link msgspecDeclareKeyword PreProc
60
+ hi link msgspecKeyword Keyword
61
+ hi link msgspecBasicType Type
62
+ hi link msgspecSpecial Special
63
+ "hi link msgspecContainerType Type
64
+ hi link msgspecId Label
65
+ hi link msgspecServiceVersion Label
66
+
67
+ let b:current_syntax = "msgspec"
68
+
@@ -49,7 +49,7 @@ end
49
49
  class TypeError < SemanticsError
50
50
  end
51
51
 
52
- class InheritanceError < IDLError
52
+ class InheritanceError < SemanticsError
53
53
  end
54
54
 
55
55
  class GeneratorError < IDLError
@@ -55,16 +55,42 @@ class Evaluator
55
55
  end
56
56
  end
57
57
 
58
+ class InheritAllMark
59
+ def initialize(ast)
60
+ @ast = ast
61
+ end
62
+ attr_reader :ast
63
+ def name
64
+ ""
65
+ end
66
+ end
67
+
68
+ class InheritMark
69
+ def initialize(ast, name)
70
+ @ast = ast
71
+ @name = name
72
+ end
73
+ attr_reader :ast, :name
74
+ end
75
+
76
+ class InheritMarkWithCheck < InheritMark
77
+ def initialize(ast, func)
78
+ super(ast, func.name)
79
+ @func = func
80
+ end
81
+ attr_reader :func
82
+ end
83
+
58
84
  def initialize
59
85
  @names = {} # name:String => AST::Element
60
86
 
61
87
  @types = {} # name:String => AST::Type
62
88
  @generic_types = [] # Template
63
89
 
64
- @global_namespace = "" # Namespace
90
+ @global_namespace = [""] # Namespace
65
91
  @lang_namespace = {} # lang:String => scope:Namespace
66
92
 
67
- @services = [] # name:String => IR::Service
93
+ @service_versions = {} # serviceName:String => (IR::Service, [(IR::ServiceVersion, AST::ServiceVersion)])
68
94
 
69
95
  init_built_in
70
96
 
@@ -89,7 +115,7 @@ class Evaluator
89
115
  if e.super_class
90
116
  super_message = resolve_type(e.super_class)
91
117
  if !super_message.is_a?(IR::Exception)
92
- raise InvalidNameError, "`#{e.super_class}' is not a #{IR::Exception} but a #{super_message.class}"
118
+ raise InvalidNameError, "Super class of the exception `#{e.super_class}' must be an exception"
93
119
  end
94
120
  end
95
121
  new_fields = resolve_fields(e.fields, super_message)
@@ -100,7 +126,7 @@ class Evaluator
100
126
  if e.super_class
101
127
  super_message = resolve_type(e.super_class)
102
128
  if !super_message.is_a?(IR::Message)
103
- raise InvalidNameError, "`#{e.super_class}' is not a #{IR::Message} but a #{super_message.class}"
129
+ raise InvalidNameError, "Super class of the message `#{e.super_class}' must be a message"
104
130
  end
105
131
  end
106
132
  new_fields = resolve_fields(e.fields, super_message)
@@ -113,9 +139,9 @@ class Evaluator
113
139
 
114
140
  when AST::Service
115
141
  v = e.version || 0
116
- s = check_service_version(e.name, v)
117
- funcs = resolve_funcs(e.funcs)
118
- add_service_version(s, e.name, v, funcs)
142
+ check_service_version(e.name, v)
143
+ funcs = resolve_service_partial(e.functions)
144
+ add_service_version(e, e.name, v, funcs)
119
145
 
120
146
  when AST::Application
121
147
  check_name(e.name, e)
@@ -123,34 +149,93 @@ class Evaluator
123
149
  add_application(e.name, scopes)
124
150
 
125
151
  else
126
- raise SemanticsError, "Unknown toplevel AST element `#{e.class}': #{e.inspect}"
152
+ raise SemanticsError, "Unknown toplevel AST element `#{e.class}'"
127
153
  end
154
+
155
+ rescue => error
156
+ raise_error(error, e)
128
157
  end
129
158
 
130
159
  def evaluate_inheritance
131
- @services.each {|s|
160
+ @ir_services = @service_versions.values.map {|s,versions|
161
+ versions = versions.sort_by {|sv,ast| sv.version }
162
+
132
163
  super_versions = []
133
- s.versions = s.versions.sort_by {|sv| sv.version }
134
- s.versions.each do |sv|
135
-
136
- sv.functions.each {|f|
137
- f.super_version = nil
138
- f.super_func = nil
139
- super_versions.reverse_each do |ssv|
140
- if sf = ssv.functions.find {|sf| sf.name == f.name }
141
- if f.args == sf.args && f.return_type == sf.return_type
142
- f.super_version = ssv.version
143
- f.super_func = sf
164
+ versions.each do |sv,ast|
165
+ begin
166
+ real_functions = []
167
+ sv.functions.each {|f|
168
+ case f
169
+ when InheritAllMark
170
+ begin
171
+ if super_versions.empty?
172
+ raise InheritanceError, "Inherit on the oldest version is invalid"
173
+ end
174
+ last = super_versions.last
175
+ last.functions.each {|ifunc|
176
+ real_functions << IR::InheritedFunction.new(last.version, ifunc)
177
+ }
178
+ rescue => error
179
+ raise_error(error, f.ast)
144
180
  end
145
- break
181
+
182
+ when InheritMark
183
+ begin
184
+ if super_versions.empty?
185
+ raise InheritanceError, "Inherit on the oldest version is invalid"
186
+ end
187
+ inherit_func = nil
188
+ inherit_version = nil
189
+ super_versions.reverse_each do |ssv|
190
+ inherit_func = ssv.functions.find {|ifunc| f.name == ifunc.name }
191
+ if inherit_func
192
+ inherit_version = ssv.version
193
+ break
194
+ end
195
+ end
196
+
197
+ unless inherit_func
198
+ raise InheritanceError, "No such function: #{f.name}"
199
+ end
200
+
201
+ if f.is_a?(InheritMarkWithCheck)
202
+ if inherit_func.args != f.func.args ||
203
+ inherit_func.return_type != f.func.return_type ||
204
+ inherit_func.exceptions != f.func.exceptions
205
+ raise InheritanceError, "Function signature is mismatched with #{s.name}:#{inherit_version}.#{f.name}"
206
+ end
207
+ end
208
+
209
+ real_functions << IR::InheritedFunction.new(inherit_version, inherit_func)
210
+ rescue => error
211
+ raise_error(error, f.ast)
212
+ end
213
+
214
+ when IR::Function
215
+ real_functions << f
216
+
217
+ else
218
+ raise "Unknown partially evaluated function: #{f.inspect}"
146
219
  end
220
+ }
221
+
222
+ if real_functions.uniq!
223
+ # may be caused by InheritAllMark
224
+ # FIXME show warning?
147
225
  end
148
- }
149
226
 
150
- super_versions << sv
227
+ sv.functions = real_functions
228
+
229
+ super_versions << sv
230
+ rescue => error
231
+ raise_error(error, ast)
232
+ end
151
233
  end
234
+ s.versions = super_versions
235
+
236
+ s
152
237
  }
153
- @ir_services = @services
238
+
154
239
  self
155
240
  end
156
241
 
@@ -164,6 +249,22 @@ class Evaluator
164
249
  end
165
250
 
166
251
  private
252
+ def raise_error(error, ast = nil)
253
+ if ast
254
+ msg = %[#{error.message}
255
+
256
+ while processing:
257
+ #{ast.summary.split("\n").map {|l| " #{l}" }.join("\n")}]
258
+
259
+ else
260
+ msg = error.message
261
+ end
262
+
263
+ wrap = error.class.new(msg)
264
+ wrap.set_backtrace(error.backtrace)
265
+ raise wrap
266
+ end
267
+
167
268
  def spec_namespace(lang)
168
269
  if ns = @lang_namespace[lang]
169
270
  return ns
@@ -186,7 +287,7 @@ class Evaluator
186
287
 
187
288
  def check_name(name, e)
188
289
  if ee = @names[name]
189
- raise DuplicatedNameError, "duplicated name `#{name}': #{e.inspect}"
290
+ raise DuplicatedNameError, "Duplicated name `#{name}'"
190
291
  end
191
292
  @names[name] = e
192
293
  end
@@ -195,7 +296,7 @@ class Evaluator
195
296
  def resolve_simple_type(e)
196
297
  type = @types[e.name]
197
298
  unless type
198
- raise NameNotFoundError, "type not found: #{e.name}"
299
+ raise NameNotFoundError, "Type not found `#{e.name}'"
199
300
  end
200
301
  if e.nullable? && !type.is_a?(IR::NullableType)
201
302
  IR::NullableType.new(type)
@@ -217,7 +318,7 @@ class Evaluator
217
318
  end
218
319
  }
219
320
  unless resolved_types
220
- raise NameNotFoundError, "generic type not matched: #{e.name}"
321
+ raise NameNotFoundError, "Generic type not matched `#{e.name}'"
221
322
  end
222
323
  type = IR::ParameterizedType.new(resolved_types, template.generic_type)
223
324
  if template.nullable || e.nullable?
@@ -249,42 +350,46 @@ class Evaluator
249
350
  end
250
351
 
251
352
  new_fields = fields.map {|e|
252
- if e.id == 0
253
- raise InvalidNameError, "field id 0 is invalid"
254
- end
255
- if e.id < 0
256
- raise InvalidNameError, "field id < 0 is invalid"
257
- end
258
- if n = used_ids[e.id]
259
- raise DuplicatedNameError, "duplicated field id #{e.id}: #{n}, #{e.name}"
260
- end
261
- if used_names[e.name]
262
- raise DuplicatedNameError, "duplicated field name: #{e.name}"
263
- end
264
- if super_used_ids[e.id]
265
- raise InheritanceError, "field id is duplicated with super class: #{e.is}"
266
- end
267
- if super_used_names[e.name]
268
- raise InheritanceError, "field name is duplicated with super class: #{e.name}"
269
- end
353
+ begin
354
+ if e.id == 0
355
+ raise InvalidNameError, "Field id 0 is invalid"
356
+ end
357
+ if e.id < 0
358
+ raise InvalidNameError, "Field id < 0 is invalid"
359
+ end
360
+ if n = used_ids[e.id]
361
+ raise DuplicatedNameError, "Field id #{e.id} is duplicated with field `#{n}'"
362
+ end
363
+ if i = used_names[e.name]
364
+ raise DuplicatedNameError, "Field name `#{e.name}' is duplicated with id #{i}"
365
+ end
366
+ if super_used_ids[e.id]
367
+ raise InheritanceError, "Field id #{e.id} is duplicated with super class `#{e.name}'"
368
+ end
369
+ if super_used_names[e.name]
370
+ raise InheritanceError, "Field name is duplicated with super class `#{e.name}'"
371
+ end
270
372
 
271
- used_ids[e.id] = e.name
272
- used_names[e.name] = e.name
373
+ used_ids[e.id] = e.name
374
+ used_names[e.name] = e.id
273
375
 
274
- type = resolve_type(e.type)
275
- if e.modifier == AST::FIELD_OPTIONAL
276
- option = IR::FIELD_OPTIONAL
277
- else
278
- option = IR::FIELD_REQUIRED
279
- end
376
+ type = resolve_type(e.type)
377
+ if e.modifier == AST::FIELD_OPTIONAL
378
+ option = IR::FIELD_OPTIONAL
379
+ else
380
+ option = IR::FIELD_REQUIRED
381
+ end
280
382
 
281
- if e.is_a?(AST::ValueAssignedField)
282
- v = resolve_initial_value(type, e.value)
283
- else
284
- v = resolve_implicit_value(type)
285
- end
383
+ if e.is_a?(AST::ValueAssignedField)
384
+ v = resolve_initial_value(type, e.value)
385
+ else
386
+ v = resolve_implicit_value(type)
387
+ end
286
388
 
287
- IR::Field.new(e.id, type, e.name, option, v)
389
+ IR::Field.new(e.id, type, e.name, option, v)
390
+ rescue => error
391
+ raise_error(error, e)
392
+ end
288
393
  }.sort_by {|f|
289
394
  f.id
290
395
  }
@@ -327,21 +432,21 @@ class Evaluator
327
432
  when AST::EnumLiteral
328
433
  enum = resolve_type(e.name)
329
434
  if !enum.is_a?(IR::Enum)
330
- raise NameNotFoundError, "not a enum type: #{e.name}"
435
+ raise NameNotFoundError, "Not a enum type `#{e.name}'"
331
436
  end
332
437
  f = enum.fields.find {|f|
333
438
  f.name == e.field
334
439
  }
335
440
  if !f
336
- raise NameNotFoundError, "no such field in enum `#{e.name}': #{e.field}"
441
+ raise NameNotFoundError, "No such field at enum `#{e.name}': #{e.field}"
337
442
  end
338
443
  IR::EnumValue.new(enum, f)
339
444
 
340
445
  when AST::ConstLiteral
341
- raise NameNotFoundError, "unknown constant: #{name}"
446
+ raise NameNotFoundError, "Unknown constant `#{name}'"
342
447
 
343
448
  else
344
- raise SemanticsError, "Unknown literal type: #{e.class}"
449
+ raise SemanticsError, "unknown literal type: #{e.class}"
345
450
  end
346
451
 
347
452
  check_assignable(type, v)
@@ -350,24 +455,24 @@ class Evaluator
350
455
 
351
456
  def check_assignable(type, v)
352
457
  if type.nullable_type? && v != IR::NilValue.nil
353
- raise TypeError, "not-nullable value for nullable type is not allowed"
458
+ raise TypeError, "Non-null value for nullable type is not allowed"
354
459
  end
355
460
 
356
461
  case v
357
462
  when IR::NilValue
358
463
  unless type.nullable_type?
359
- raise TypeError, "nullable is expected: #{type}"
464
+ raise TypeError, "Assigning null to non-nullable field"
360
465
  end
361
466
 
362
467
  when IR::IntValue
363
468
  unless IR::Primitive::INT_TYPES.include?(type)
364
- raise TypeError, "integer type is expected: #{type}"
469
+ raise TypeError, "Integer type is expected: #{type}"
365
470
  end
366
471
  # TODO overflow
367
472
 
368
473
  when IR::BoolValue
369
474
  if type != IR::Primitive::bool
370
- raise TypeError, "bool type is expected: #{type}"
475
+ raise TypeError, "Bool type is expected: #{type}"
371
476
  end
372
477
 
373
478
  end
@@ -386,7 +491,7 @@ class Evaluator
386
491
 
387
492
  elsif t.is_a?(IR::Enum)
388
493
  if t.fields.empty?
389
- raise TypeError, "empty enum: #{t.name}"
494
+ raise TypeError, "Empty enum is not allowed: enum #{t.name}"
390
495
  end
391
496
  IR::EnumValue.new(t, t.fields.first)
392
497
 
@@ -400,20 +505,24 @@ class Evaluator
400
505
  used_names = {}
401
506
 
402
507
  fields = fields.map {|e|
403
- if e.id < 0
404
- raise InvalidNameError, "enum id < 0 is invalid"
405
- end
406
- if n = used_ids[e.id]
407
- raise DuplicatedNameError, "duplicated enum id #{e.id}: #{n}, #{e.name}"
408
- end
409
- if used_names[e.name]
410
- raise DuplicatedNameError, "duplicated field name: #{e.name}"
411
- end
508
+ begin
509
+ if e.id < 0
510
+ raise InvalidNameError, "Enum id < 0 is invalid"
511
+ end
512
+ if n = used_ids[e.id]
513
+ raise DuplicatedNameError, "Enum field id #{e.id} is duplicated with `#{n}'"
514
+ end
515
+ if i = used_names[e.name]
516
+ raise DuplicatedNameError, "Enum field name `#{e.name}' is duplicated with id #{i}"
517
+ end
412
518
 
413
- used_ids[e.id] = e.name
414
- used_names[e.name] = e.name
519
+ used_ids[e.id] = e.name
520
+ used_names[e.name] = e.id
415
521
 
416
- IR::EnumField.new(e.id, e.name)
522
+ IR::EnumField.new(e.id, e.name)
523
+ rescue => error
524
+ raise_error(error, e)
525
+ end
417
526
  }.sort_by {|f|
418
527
  f.id
419
528
  }
@@ -422,39 +531,52 @@ class Evaluator
422
531
  end
423
532
 
424
533
  def check_service_version(name, version)
425
- s = @services.find {|s|
426
- s.name == name
427
- }
534
+ s, versions = @service_versions[name]
428
535
  if s
429
- s.versions.each {|sv|
536
+ versions.each {|sv,ast|
430
537
  if sv.version == version
431
- raise DuplicatedNameError, "duplicated version #{version}"
538
+ raise DuplicatedNameError, "Duplicated version #{version}"
432
539
  end
433
540
  }
434
541
  else
435
542
  check_name(name, nil)
436
543
  end
437
- s
544
+ nil
438
545
  end
439
546
 
440
- def resolve_funcs(funcs)
547
+ def resolve_service_partial(funcs)
441
548
  used_names = {}
442
549
 
443
550
  funcs = funcs.map {|e|
444
- if used_names[e.name]
445
- raise DuplicatedNameError, "duplicated function name: #{e.name}"
446
- end
551
+ case e
552
+ when AST::InheritAll
553
+ InheritAllMark.new(e)
447
554
 
448
- used_names[e.name] = true
555
+ when AST::InheritName, AST::InheritFunc
556
+ if used_names[e.name]
557
+ raise DuplicatedNameError, "Duplicated function name `#{e.name}'"
558
+ end
559
+ used_names[e.name] = true
560
+
561
+ if e.is_a?(AST::InheritFunc)
562
+ func = resolve_func(e)
563
+ InheritMarkWithCheck.new(e, func)
564
+ else
565
+ InheritMark.new(e, e.name)
566
+ end
567
+
568
+ when AST::Func
569
+ if used_names[e.name]
570
+ raise DuplicatedNameError, "Duplicated function name `#{e.name}'"
571
+ end
572
+ used_names[e.name] = true
573
+
574
+ resolve_func(e)
449
575
 
450
- args = resolve_args(e.args)
451
- if e.return_type.name == "void"
452
- return_type = IR::Primitive.void
453
576
  else
454
- return_type = resolve_type(e.return_type)
577
+ raise SemanticsError, "Unknown service body AST element `#{e.class}': #{e.inspect}"
455
578
  end
456
579
 
457
- IR::Function.new(e.name, return_type, args, nil, nil)
458
580
  }.sort_by {|f|
459
581
  f.name
460
582
  }
@@ -462,41 +584,62 @@ class Evaluator
462
584
  return funcs
463
585
  end
464
586
 
587
+ def resolve_func(e)
588
+ args = resolve_args(e.args)
589
+
590
+ if e.return_type.name == "void"
591
+ return_type = IR::Primitive.void
592
+ else
593
+ return_type = resolve_type(e.return_type)
594
+ end
595
+
596
+ exceptions = resolve_exceptions(e.exceptions)
597
+
598
+ IR::Function.new(e.name, return_type, args, exceptions)
599
+
600
+ rescue => error
601
+ raise_error(error, e)
602
+ end
603
+
465
604
  def resolve_args(args)
466
605
  used_ids = []
467
606
  used_names = {}
468
607
 
469
608
  args = args.map {|e|
470
- if e.id == 0
471
- raise InvalidNameError, "argument id 0 is invalid"
472
- end
473
- if e.id < 0
474
- raise InvalidNameError, "argument id < 0 is invalid"
475
- end
476
- if n = used_ids[e.id]
477
- raise DuplicatedNameError, "duplicated argument id #{e.id}: #{n}, #{e.name}"
478
- end
479
- if used_names[e.name]
480
- raise DuplicatedNameError, "duplicated argument name: #{e.name}"
481
- end
609
+ begin
610
+ if e.id == 0
611
+ raise InvalidNameError, "Argument id 0 is invalid"
612
+ end
613
+ if e.id < 0
614
+ raise InvalidNameError, "Argument id < 0 is invalid"
615
+ end
616
+ if n = used_ids[e.id]
617
+ raise DuplicatedNameError, "Argument id #{e.id} is duplicated with `#{n}'"
618
+ end
619
+ if i = used_names[e.name]
620
+ raise DuplicatedNameError, "Argument name `#{e.name}' is duplicated with id #{i}"
621
+ end
482
622
 
483
- used_ids[e.id] = e.name
484
- used_names[e.name] = e.name
623
+ used_ids[e.id] = e.name
624
+ used_names[e.name] = e.id
485
625
 
486
- type = resolve_type(e.type)
487
- if e.modifier == AST::FIELD_OPTIONAL
488
- option = IR::FIELD_OPTIONAL
489
- else
490
- option = IR::FIELD_REQUIRED
491
- end
626
+ type = resolve_type(e.type)
627
+ if e.modifier == AST::FIELD_OPTIONAL
628
+ option = IR::FIELD_OPTIONAL
629
+ else
630
+ option = IR::FIELD_REQUIRED
631
+ end
492
632
 
493
- if e.is_a?(AST::ValueAssignedField)
494
- v = resolve_initial_value(type, e.value)
495
- else
496
- v = resolve_implicit_value(type)
497
- end
633
+ if e.is_a?(AST::ValueAssignedField)
634
+ v = resolve_initial_value(type, e.value)
635
+ else
636
+ v = resolve_implicit_value(type)
637
+ end
498
638
 
499
- IR::Argument.new(e.id, type, e.name, option, v)
639
+ IR::Argument.new(e.id, type, e.name, option, v)
640
+ rescue => error
641
+ raise_error(error, e)
642
+ end
500
643
  }.sort_by {|a|
501
644
  a.id
502
645
  }
@@ -504,12 +647,17 @@ class Evaluator
504
647
  return args
505
648
  end
506
649
 
650
+ def resolve_exceptions(exceptions)
651
+ # TODO
652
+ []
653
+ end
654
+
507
655
  def resolve_scopes(scopes)
508
656
  ds = scopes.find_all {|e|
509
657
  e.default?
510
658
  }
511
659
  if ds.size > 1
512
- raise DuplicatedNameError, "multiple default scope: #{ds.map {|e| e.name}.join(', ')}"
660
+ raise DuplicatedNameError, "Multiple default scope: #{ds.map {|e| e.name}.join(', ')}"
513
661
  end
514
662
 
515
663
  if ds.empty?
@@ -522,21 +670,17 @@ class Evaluator
522
670
 
523
671
  scopes = scopes.map {|e|
524
672
  if used_names[e.name]
525
- raise DuplicatedNameError, "duplicated scope name: #{e.name}"
673
+ raise DuplicatedNameError, "Duplicated scope name: #{e.name}"
526
674
  end
527
675
 
528
- s = @services.find {|s|
529
- s.name == e.service
530
- }
676
+ s, versions = @service_versions[e.service]
531
677
  unless s
532
- raise NameNotFoundError, "no such service: #{e.name}"
678
+ raise NameNotFoundError, "No such service: #{e.name}"
533
679
  end
534
680
 
535
- sv = s.versions.find {|sv|
536
- sv.version == e.version
537
- }
681
+ sv = versions.find {|sv,ast| sv.version == e.version }
538
682
  unless sv
539
- raise NameNotFoundError, "no such service version: #{e.service}:#{s.version}"
683
+ raise NameNotFoundError, "No such service version: #{e.service}:#{s.version}"
540
684
  end
541
685
 
542
686
  used_names[e.name] = true
@@ -579,14 +723,15 @@ class Evaluator
579
723
  e
580
724
  end
581
725
 
582
- def add_service_version(s, name, version, funcs)
726
+ def add_service_version(e, name, version, funcs)
583
727
  sv = IR::ServiceVersion.new(version, funcs)
584
- if s
585
- s.versions << sv
586
- else
587
- s = IR::Service.new(name, [sv])
588
- @services << s
728
+ s, versions = @service_versions[name]
729
+ unless s
730
+ s = IR::Service.new(name, nil)
731
+ versions = []
732
+ @service_versions[name] = [s, versions]
589
733
  end
734
+ versions << [sv, e]
590
735
  sv
591
736
  end
592
737