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