Commits

FURUHASHI Sadayuki  committed 939baba

updated

  • Participants
  • Parent commits fa0b6ad

Comments (0)

Files changed (10)

File lib/msgpack/idl/ast.rb

 		attr_reader :id, :type, :name, :modifier
 	end
 
+	class ValueAssignedField < Field
+		def initialize(id, type, modifier, name, value)
+			super(id, type, modifier, name)
+			@value = value
+		end
+		attr_reader :value
+	end
+
 
 	class Enum < Element
 		def initialize(name, fields)
 			@name = name
 			@nullable = nullable
 		end
-		attr_reader :name
+		attr_reader :name, :nullable
 
 		def nullable?
 			@nullable
 			@type_params = type_params
 		end
 		attr_reader :type_params
-
-		def nullable?
-			@nullable
-		end
 	end
 
 	FIELD_OPTIONAL = :optional
 	FIELD_REQUIRED = :required
 
+
+	class Literal
+	end
+
+	class ConstLiteral < Literal
+		def initialize(name)
+			@name = name
+		end
+		attr_reader :name
+	end
+
+	class EnumLiteral < Literal
+		def initialize(name, field)
+			@name = name
+			@field = field
+		end
+		attr_reader :name, :field
+	end
+
+	class IntLiteral < Literal
+		def initialize(value)
+			@value = value
+		end
+		attr_reader :value
+	end
+
+	class FlaotLiteral < Literal
+		def initialize(value)
+			@value = value
+		end
+		attr_reader :value
+	end
+
+	class NilLiteral < Literal
+	end
+
+	class BoolLiteral < Literal
+		def initialize(value)
+			@value = value
+		end
+		attr_reader :value
+	end
+
+	class TrueLiteral < BoolLiteral
+		def initialize
+			super(true)
+		end
+	end
+
+	class FalseLiteral < BoolLiteral
+		def initialize
+			super(false)
+		end
+	end
+
+	class StringLiteral < Literal
+		def initialize(value)
+			@value = value
+		end
+	end
+
+	#class ListLiteral < Literal
+	#	def initialize(array)
+	#		@array = array
+	#	end
+	#end
+
+	#class MapLiteralPair
+	#	def initialize(k, v)
+	#		@key = k
+	#		@value = v
+	#	end
+	#end
+
+	#class MapLiteral < Literal
+	#	def initialize(pairs)
+	#		@pairs = pairs
+	#	end
+	#end
+
+
 	class Sequence < Array
 	end
 end

File lib/msgpack/idl/error.rb

 class DuplicatedNameError < NameError
 end
 
+class TypeError < SemanticsError
+end
+
 class InheritanceError < IDLError
 end
 

File lib/msgpack/idl/evaluator.rb

 			@generic_type = generic_type
 			@nullable = nullable
 		end
+		attr_reader :generic_type, :nullable
 
-		attr_reader :generic_type, :nullable
+		def nullable?
+			@nullable
+		end
 
 		def match_all(name, array)
 			if @name != name
 	def resolve_simple_type(e)
 		type = @types[e.name]
 		unless type
-			raise NameNotFoundError, "message not found: #{e.name}"
+			raise NameNotFoundError, "type not found: #{e.name}"
 		end
-		type
+		if e.nullable? && !type.is_a?(IR::NullableType)
+			IR::NullableType.new(type)
+		else
+			type
+		end
 	end
 
 	def resolve_generic_type(e)
 		unless resolved_types
 			raise NameNotFoundError, "generic type not matched: #{e.name}"
 		end
-		IR::ParameterizedType.new(resolved_types, template.generic_type)
-		#TODO template.nullable?||e.nullable?
+		type = IR::ParameterizedType.new(resolved_types, template.generic_type)
+		if template.nullable || e.nullable?
+			IR::NullableType.new(type)
+		else
+			type
+		end
 	end
 
 	def resolve_type(e)
 			used_names[e.name] = e.name
 
 			type = resolve_type(e.type)
-			required = e.modifier == AST::FIELD_OPTIONAL ? false : true
+			if e.modifier == AST::FIELD_OPTIONAL
+				option  = IR::FIELD_OPTIONAL
+			else
+				option  = IR::FIELD_REQUIRED
+			end
 
-			IR::Field.new(e.id, type, e.name, required)
+			if e.is_a?(AST::ValueAssignedField)
+				v = resolve_initial_value(type, e.value)
+			else
+				v = resolve_implicit_value(type)
+			end
+
+			IR::Field.new(e.id, type, e.name, option, v)
 		}.sort_by {|f|
 			f.id
 		}
 		return new_fields
 	end
 
+	BUILT_IN_LITERAL = {
+		'BYTE_MAX'   => AST::IntLiteral.new((2**7)-1),
+		'SHORT_MAX'  => AST::IntLiteral.new((2**15)-1),
+		'INT_MAX'    => AST::IntLiteral.new((2**31)-1),
+		'LONG_MAX'   => AST::IntLiteral.new((2**63)-1),
+		'UBYTE_MAX'  => AST::IntLiteral.new((2**8)-1),
+		'USHORT_MAX' => AST::IntLiteral.new((2**16)-1),
+		'UINT_MAX'   => AST::IntLiteral.new((2**32)-1),
+		'ULONG_MAX'  => AST::IntLiteral.new((2**64)-1),
+		'BYTE_MIN'   => AST::IntLiteral.new(-(2**7)),
+		'SHORT_MIN'  => AST::IntLiteral.new(-(2**15)),
+		'INT_MIN'    => AST::IntLiteral.new(-(2**31)),
+		'LONG_MIN'   => AST::IntLiteral.new(-(2**63)),
+	}
+
+	def resolve_initial_value(type, e)
+		if e.is_a?(ConstLiteral)
+			e = BUILT_IN_LITERAL[e.name] || e
+		end
+		v = case e
+		when NilLiteral
+			IR::NilValue.nil
+
+		when TrueLiteral
+			IR::BoolValue.true
+
+		when FalseLiteral
+			IR::BoolValue.false
+
+		when IntLiteral
+			IR::IntValue.new(e.value)
+
+		when EnumLiteral
+			enum = resolve_type(e.name)
+			if !enum.is_a?(IR::Enum)
+				raise NameNotFoundError, "not a enum type: #{e.name}"
+			end
+			f = enum.fields.find {|f|
+				f.name == e.field
+			}
+			if !f
+				raise NameNotFoundError, "no such field in enum `#{e.name}': #{e.field}"
+			end
+			IR::EnumValue.new(enum, f)
+
+		when ConstLiteral
+			raise NameNotFoundError, "unknown constant: #{name}"
+
+		else
+			raise SemanticsError, "Unknown literal type: #{e.class}"
+		end
+
+		check_assignable(type, v)
+		v
+	end
+
+	def check_assignable(type, v)
+		if type.nullable_type? && v != IR::NilValue.nil
+			raise TypeError, "not-nullable value for nullable type is not allowed"
+		end
+
+		case v
+		when IR::NilValue
+			unless type.nullable_type?
+				raise TypeError, "nullable is expected: #{type}"
+			end
+
+		when IR::IntValue
+			unless IR::Primitive::INT_TYPES.include?(type)
+				raise TypeError, "integer type is expected: #{type}"
+			end
+			# TODO overflow
+
+		when IR::BoolValue
+			if type != IR::Primitive::bool
+				raise TypeError, "bool type is expected: #{type}"
+			end
+
+		end
+	end
+
+	def resolve_implicit_value(t)
+		if t.nullable_type?
+			return IR::NilValue.nil
+		end
+
+		if IR::Primitive::INT_TYPES.include?(t)
+			IR::IntValue.new(0)
+
+		elsif t == IR::Primitive.bool
+			IR::BoolValue.false
+
+		elsif t.is_a?(IR::Enum)
+			if t.fields.empty?
+				raise TypeError, "empty enum: #{t.name}"
+			end
+			t.fields.first
+
+		else
+			IR::EmptyValue.new
+		end
+	end
+
 	def resolve_enum_fields(fields)
 		used_ids = []
 		used_names = {}
 			used_names[e.name] = e.name
 
 			type = resolve_type(e.type)
-			required = e.modifier == AST::FIELD_OPTIONAL ? false : true
+			if e.modifier == AST::FIELD_OPTIONAL
+				option  = IR::FIELD_OPTIONAL
+			else
+				option  = IR::FIELD_REQUIRED
+			end
 
-			IR::Argument.new(e.id, type, e.name, required)
+			if e.is_a?(AST::ValueAssignedField)
+				v = resolve_initial_value(type, e.value)
+			else
+				v = resolve_implicit_value(type)
+			end
+
+			IR::Argument.new(e.id, type, e.name, option, v)
 		}.sort_by {|a|
 			a.id
 		}
 	def init_built_in
 		%w[byte short int long ubyte ushort uint ulong float double bool raw string].each {|name|
 			check_name(name, nil)
-			@types[name] = IR::PrimitiveType.new(name)
+			@types[name] = IR::Primitive.send(name)
 		}
-		@generic_types << Template.new(
-				IR::PrimitiveGenericType.new('list', [
-						IR::TypeParameterSymbol.new('E')]))
 		check_name('list', nil)
-		@generic_types << Template.new(
-				IR::PrimitiveGenericType.new('map', [
-						IR::TypeParameterSymbol.new('K'),
-						IR::TypeParameterSymbol.new('V')]))
+		@generic_types << Template.new(IR::Primitive.list)
 		check_name('map', nil)
+		@generic_types << Template.new(IR::Primitive.map)
+		#check_name('nullable', nil)
+		#@generic_types << Template.new(IR::Primitive.nullable)
 	end
 end
 

File lib/msgpack/idl/ir.rb

 	end
 
 	class Type
+		def parameterized_type?
+			false
+		end
+
+		def nullable_type?
+			false
+		end
+
+		def real_type
+			self
+		end
+
+		def list_type?
+			false
+		end
+
+		def map_type?
+			false
+		end
 	end
 
 	class PrimitiveType < Type
 			@type_params = type_params
 		end
 		attr_reader :type_params, :generic_type
+
 		def name
 			@generic_type.name
 		end
+
+		def parameterized_type?
+			true
+		end
+
+		def list_type?
+			@generic_type == Primitive.list
+		end
+
+		def map_type?
+			@generic_type == Primitive.map
+		end
 	end
 
 	class TypeParameterSymbol
 			@type_params = type_params
 		end
 		attr_reader :name, :type_params
+
+		def list_type?
+			false
+		end
+
+		def map_type?
+			false
+		end
 	end
 
 	class PrimitiveGenericType < GenericType
 	end
 
-	#class NullableType < ParameterizedType
-	#	def initialize(type)
-	#		@type = type
-	#	end
-	#	attr_reader :type
-	#end
+	class NullableType < ParameterizedType
+		def initialize(type)
+			super([type], Primitive.nullable)
+		end
+
+		def nullable_type?
+			true
+		end
+
+		def real_type
+			@type_params[0].real_type
+		end
+	end
+
+	module Primitive
+		def self.define(name, value)
+			(class << self; self; end).module_eval {
+				define_method(name) { value }
+			}
+		end
+
+		define :byte,    PrimitiveType.new('byte')
+		define :short,   PrimitiveType.new('short')
+		define :int,     PrimitiveType.new('int')
+		define :long,    PrimitiveType.new('long')
+		define :ubyte,   PrimitiveType.new('ubyte')
+		define :ushort,  PrimitiveType.new('ushort')
+		define :uint,    PrimitiveType.new('uint')
+		define :ulong,   PrimitiveType.new('ulong')
+		define :float,   PrimitiveType.new('float')
+		define :double,  PrimitiveType.new('double')
+		define :bool,    PrimitiveType.new('bool')
+		define :raw,     PrimitiveType.new('raw')
+		define :string,  PrimitiveType.new('string')
+		define :list,     PrimitiveGenericType.new('list', [
+												TypeParameterSymbol.new('E')])
+		define :map,      PrimitiveGenericType.new('map', [
+												TypeParameterSymbol.new('K'),
+												TypeParameterSymbol.new('V')])
+		define :nullable, PrimitiveGenericType.new('nullable', [
+												TypeParameterSymbol.new('T')])
+
+		INT_TYPES = [byte, short, int, long, ubyte, ushort, uint, ulong]
+	end
+
+	class Value
+	end
+
+	class NilValue < Value
+		n = NilValue.new
+
+		(class << self; self; end).module_eval {
+			define_method(:nil) { n }
+		}
+	end
+
+	class BoolValue < Value
+		def initialize(bool)
+			@bool = bool
+		end
+		attr_reader :bool
+
+		t = BoolValue.new(true)
+		f = BoolValue.new(false)
+
+		(class << self; self; end).module_eval {
+			define_method(:true) { t }
+			define_method(:false) { f }
+		}
+	end
+
+	class IntValue < Value
+		def initialize(int)
+			@int = int
+		end
+		attr_reader :int
+	end
+
+	class EnumValue < Value
+		def initialize(enum, field)
+			@enum = enum
+			@field = field
+		end
+		attr_reader :enum, :field
+	end
+
+	class EmptyValue < Value
+	end
 
 	class Message < Type
 		def initialize(name, super_class, new_fields)
 	end
 
 	class Field
-		def initialize(id, type, name, is_required)
+		def initialize(id, type, name, option, value)
 			@id = id
 			@type = type
 			@name = name
-			@is_required = is_required
+			@option = option
+			@value = value
 		end
 
-		attr_reader :id, :type, :name
+		attr_reader :id, :type, :name, :option, :value
 
 		def required?
-			@is_required
+			@option == FIELD_REQUIRED
 		end
 
 		def optional?
-			!@is_required
+			@option == FIELD_OPTIONAL
 		end
 	end
 
+	FIELD_OPTIONAL = :optional
+	FIELD_REQUIRED = :required
+
 	class Enum < Type
 		def initialize(name, fields)
 			@name = name

File lib/msgpack/idl/lang/java.rb

 class JavaGenerator < GeneratorModule
 	Generator.register('java', self)
 
-	include Tenjin::ContextHelper
-
 	def initialize(ir, outdir)
 		@ir = ir
 		@outdir = outdir
 
 	def gen_init
 		@datadir = File.join(File.dirname(__FILE__), 'java')
-
-		@dir = File.join(@outdir, @ir.namespace)
-
-		if @ir.namespace.empty?
-			@package = ""
-		else
-			@package = "package #{@ir.namespace.join('.')};"
-		end
+		@pkgoutdir = File.join(@outdir, @ir.namespace)
 
 		@engine = Tenjin::Engine.new(:cache => false)
 	end
 
 	def gen_messages
-		render = get_render('message.java')
+		ctx = Context.new(:package, :message, :name)
+		ctx.package = @ir.namespace
 
 		@ir.messages.each {|t|
-			@message = t
-			render_write(render, t.name)
+			ctx.message = t
+			ctx.name = t.name
+			render('message.java', ctx, "#{ctx.name}")
 		}
-		@message = nil
 	end
 
 	def gen_servers
-		render = get_render('server.java')
+		ctx = Context.new(:package, :service, :version, :functions, :name)
+		ctx.package = @ir.namespace + ['server']
 
 		@ir.services.each {|s|
-			@service = s
+			ctx.service = s
 			s.versions.each {|v|
-				@version = v.version
-				@functions = v.functions
-				@name = "#{s.name}_#{v.version}"
-				render_write(render, 'server', @name)
+				ctx.version  = v.version
+				ctx.functions = v.functions
+				ctx.name = "#{s.name}_#{v.version}"
+				render('server.java', ctx, "server/#{ctx.name}")
 			}
 		}
-		@service = nil
-		@version = nil
-		@functions = nil
-		@name = nil
 	end
 
 	def gen_clients
-		render = get_render('client.java')
+		ctx = Context.new(:package, :service, :version, :functions, :name)
+		ctx.package = @ir.namespace + ['client']
 
 		@ir.services.each {|s|
-			@service = s
+			ctx.service = s
 			s.versions.each {|v|
-				@version = v.version
-				@functions = v.functions
-				@name = "#{s.name}_#{v.version}"
-				render_write(render, 'client', @name)
+				ctx.version = v.version
+				ctx.functions = v.functions
+				ctx.name = "#{s.name}_#{v.version}"
+				render('client.java', ctx, "client/#{ctx.name}")
 			}
 		}
-		@service = nil
-		@version = nil
-		@functions = nil
-		@name = nil
 	end
 
-	def get_render(*fnames)
-		path = File.join(@datadir, *fnames)
-		@engine.get_template(path)
-	end
-
-	def render_write(render, *fnames)
-		code = render.render(self)
-		path = File.join(@dir, *fnames)
+	private
+	def render(template_fname, ctx, fname)
+		template_path = File.join(@datadir, template_fname)
+		code = @engine.render(template_path, ctx)
+		path = File.join(@pkgoutdir, fname) + '.java'
 		FileUtils.mkdir_p(File.dirname(path))
-		path << '.java'
 		File.open(path, "w") {|f|
 			f.write(code)
 		}
 	end
 
-	PRIMITIVE_TYPEMAP = {
-		'void'   => 'void',
-		'byte'   => 'byte',
-		'short'  => 'short',
-		'int'    => 'int',
-		'long'   => 'long',
-		'ubyte'  => 'short',
-		'ushort' => 'int',
-		'uint'   => 'long',
-		'ulong'  => 'BigInteger',
-		'float'  => 'float',
-		'double' => 'double',
-		'bool'   => 'boolean',
-		'raw'    => 'ByteBuffer',
-		'string' => 'String',
-		'list'   => 'List',
-		'map'    => 'Map',
-	}
 
-	def format_type(t)
-		name = PRIMITIVE_TYPEMAP[t.name] || t.name
-		if t.is_a?(IR::ParameterizedType)
-			name + '<' +
-				t.type_params.map {|tp| format_type(tp) }.join(', ') +
-			'>'
-		else
-			name
+	class Context
+		include Tenjin::ContextHelper
+
+		def initialize(*member)
+			(class << self; self; end).module_eval {
+				member.each {|m|
+					define_method("#{m}") {
+						instance_variable_get("@#{m}")
+					}
+					define_method("#{m}=") {|v|
+						instance_variable_set("@#{m}", v)
+					}
+				}
+			}
 		end
-	end
 
-	PRIMITIVE_UNPACK = {
-		'byte'   => 'unpackByte()',
-		'short'  => 'unpackShort()',
-		'int'    => 'unpackInt()',
-		'long'   => 'unpackLong()',
-		'ubyte'  => 'unpackShort()',
-		'ushort' => 'unpackInt()',
-		'uint'   => 'unpackLong()',
-		'ulong'  => 'unpackBigInteger()',
-		'float'  => 'unpackFloat()',
-		'double' => 'unpackDouble()',
-		'bool'   => 'unpackBoolean()',
-		'raw'    => 'ByteBuffer.wrap(unpackByteArray())',
-		'string' => 'unpackString()',
-		'list'   => 'unpackList()',
-		'map'    => 'unpackMap()',
-	}
+		def format_package
+			if package.empty?
+				""
+			else
+				"package #{package.join('.')};"
+			end
+		end
 
-	def format_unpack(t)
-		# TODO type erasure
-		PRIMITIVE_UNPACK[t.name] || "unpack(#{t.name}.class)"
-	end
+		PRIMITIVE_TYPEMAP = {
+			'void'   => 'void',
+			'byte'   => 'byte',
+			'short'  => 'short',
+			'int'    => 'int',
+			'long'   => 'long',
+			'ubyte'  => 'short',
+			'ushort' => 'int',
+			'uint'   => 'long',
+			'ulong'  => 'BigInteger',
+			'float'  => 'float',
+			'double' => 'double',
+			'bool'   => 'boolean',
+			'raw'    => 'byte[]',
+			'string' => 'String',
+			'list'   => 'List',
+			'map'    => 'Map',
+		}
 
-	PRIMITIVE_CONVERT = {
-		'byte'   => 'asByte()',
-		'short'  => 'asShort()',
-		'int'    => 'asInt()',
-		'long'   => 'asLong()',
-		'ubyte'  => 'asShort()',
-		'ushort' => 'asInt()',
-		'uint'   => 'asLong()',
-		'ulong'  => 'asBigInteger()',
-		'float'  => 'asFloat()',
-		'double' => 'asDouble()',
-		'bool'   => 'asBoolean()',
-		'raw'    => 'ByteBuffer.wrap(asByteArray())',
-		'string' => 'asString()',
-		'list'   => 'asList()',
-		'map'    => 'asMap()',
-	}
+		NULLABLE_REMAP = {
+			'byte'    => 'Byte',
+			'short'   => 'Short',
+			'int'     => 'Integer',
+			'long'    => 'Long',
+			'float'   => 'Float',
+			'double'  => 'Double',
+			'boolean' => 'Boolean',
+		}
 
-	def format_convert(t)
-		# TODO type erasure
-		PRIMITIVE_CONVERT[t.name] || "convert(#{t.name}.class)"
+		TYPE_PARAMETER_REMAP = NULLABLE_REMAP
+
+		IFACE_CLASS_REMAP = {
+			'Map'     => 'HashMap',
+			'List'    => 'ArrayList',
+		}
+
+		def format_nullable_type(t)
+			if t.nullable_type?
+				real_type = t.real_type
+				name = PRIMITIVE_TYPEMAP[real_type.name] || real_type.name
+				name = NULLABLE_REMAP[name] || name
+				return real_type, name
+			else
+				name = PRIMITIVE_TYPEMAP[t.name] || name
+				return t, name
+			end
+		end
+
+		def format_parameterized_type(t, name)
+			if t.parameterized_type?
+				name + '<' +
+					t.type_params.map {|tp|
+						n = format_type(tp)
+						TYPE_PARAMETER_REMAP[n] || n
+					}.join(', ') + '>'
+			else
+				name
+			end
+		end
+
+		def format_type(t)
+			t, name = format_nullable_type(t)
+			format_parameterized_type(t, name)
+		end
+
+		def format_type_impl(t)
+			t, name = format_nullable_type(t)
+			name = IFACE_CLASS_REMAP[name] || name
+			format_parameterized_type(t, name)
+		end
+
+		PRIMITIVE_DEFAULT = {
+			'byte'    => '0',
+			'short'   => '0',
+			'int'     => '0',
+			'long'    => '0',
+			'float'   => '0.0',
+			'double'  => '0',
+			'boolean' => 'false',
+			'byte[]'  => 'new byte[0]',
+			'String'  => '""',
+		}
+
+		def format_initial_value(to, f)
+			v = f.value
+			case v
+			when IR::NilValue
+				"#{to} = null;"
+			when IR::IntValue
+				"#{to} = #{v.int};"
+			when IR::BoolValue
+				if v.bool
+					"#{to} = true;"
+				else
+					"#{to} = false;"
+				end
+			when IR::EnumValue
+				"#{to} = #{v.enum.name}.#{v.field.name};"
+			when IR::EmptyValue
+				tt, name = format_nullable_type(f.type)
+				v = PRIMITIVE_DEFAULT[name]
+				v ||= "new #{format_type_impl(f.type)}()"
+				"#{to} = #{v};"
+			else
+				raise SemanticsError, "unknown initial value type: #{v.class}"
+			end
+		end
+
+		PRIMITIVE_UNPACK = {
+			'byte'   => 'unpackByte()',
+			'short'  => 'unpackShort()',
+			'int'    => 'unpackInt()',
+			'long'   => 'unpackLong()',
+			'ubyte'  => 'unpackShort()',
+			'ushort' => 'unpackInt()',
+			'uint'   => 'unpackLong()',
+			'ulong'  => 'unpackBigInteger()',
+			'float'  => 'unpackFloat()',
+			'double' => 'unpackDouble()',
+			'bool'   => 'unpackBoolean()',
+			'raw'    => 'unpackByteArray()',
+			'string' => 'unpackString()',
+		}
+
+		def format_unpack(to, pac, t)
+			if t.parameterized_type?
+				if t.list_type?
+					e = t.type_params[0]
+					return %[{
+						#{to} = new #{format_type_impl(t)}();
+						int n = #{pac}.unpackArray();
+						#{format_type(e)} e;
+						for(int i=0; i < n; i++) {
+							#{format_unpack("e", pac, e)}
+							#{to}.add(e);
+						}
+					}]
+				elsif t.map_type?
+					k = t.type_params[0]
+					v = t.type_params[1]
+					return %[{
+						#{to} = new #{format_type_impl(t)}();
+						int n = #{pac}.unpackMap();
+						#{format_type(k)} k;
+						#{format_type(v)} v;
+						for(int i=0; i < n; i++) {
+							#{format_unpack("k", pac, k)}
+							#{format_unpack("v", pac, v)}
+							#{to}.put(k, v);
+						}
+					}]
+				end
+			end
+			method = PRIMITIVE_UNPACK[t.name] || "unpack(#{t.name}.class)"
+			"#{to} = #{pac}.#{method};"
+		end
+
+		PRIMITIVE_CONVERT = {
+			'byte'   => 'asByte()',
+			'short'  => 'asShort()',
+			'int'    => 'asInt()',
+			'long'   => 'asLong()',
+			'ubyte'  => 'asShort()',
+			'ushort' => 'asInt()',
+			'uint'   => 'asLong()',
+			'ulong'  => 'asBigInteger()',
+			'float'  => 'asFloat()',
+			'double' => 'asDouble()',
+			'bool'   => 'asBoolean()',
+			'raw'    => 'asByteArray()',
+			'string' => 'asString()',
+		}
+
+		def format_convert(to, obj, t)
+			if t.parameterized_type?
+				if t.list_type?
+					e = t.type_params[0]
+					return %[{
+						#{to} = new #{format_type_impl(t)}();
+						#{format_type(e)} e;
+						for(MessagePackObject o : #{obj}.asArray()) {
+							#{format_convert("e", "o", e)}
+							#{to}.add(e);
+						}
+					}]
+				elsif t.map_type?
+					k = t.type_params[0]
+					v = t.type_params[1]
+					return %[{
+						#{to} = new #{format_type_impl(t)}();
+						#{format_type(k)} k;
+						#{format_type(v)} v;
+						for(Map.EntrySet<MessagePackObject,MessagePackObject> kv : #{obj}.asMap().entrySet()) {
+							#{format_convert("k", "kv.getKey()", k)}
+							#{format_convert("v", "kv.getValue()", v)}
+							#{to}.put(k, v);
+						}
+					}]
+				end
+			end
+			method = PRIMITIVE_CONVERT[t.name] || "convert(new #{t.name}())"
+			"#{to} = #{obj}.#{method};"
+		end
 	end
 end
 

File lib/msgpack/idl/lang/java/client.java

-#{@package}
+#{format_package}
 
 import java.util.List;
 import java.util.Set;

File lib/msgpack/idl/lang/java/message.java

-#{@package}
+#{format_package}
 
 import java.util.List;
-import java.util.Set;
 import java.util.Map;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.HashMap;
 import java.io.IOException;
 import org.msgpack.MessageTypeException;
+import org.msgpack.MessagePackObject;
 
-public class #{@message.name} implements MessagePackable, MessageUnpackable, MessageConvertable {
-	<?rb @message.new_fields.each {|field| ?>
-	private #{format_type(field.type)} #{field.name};
+public class #{@name} implements MessagePackable, MessageUnpackable, MessageConvertable {
+	<?rb @message.new_fields.each {|f| ?>
+	private #{format_type(f.type)} #{f.name};
 	<?rb } ?>
 
-	public void messagePack(Packer _Pk) throws IOException {
+	public #{@name}() {
+		super();
+		<?rb @message.new_fields.each {|f| ?>
+			#{format_initial_value("this.#{f.name}", f)}
+		<?rb } ?>
+	}
+
+	<?rb @message.new_fields.each {|f| ?>
+	public void set#{f.name.capitalize}(#{format_type(f.type)} value) {
+		this.#{f.name} = v;
+	}
+	public #{format_type(f.type)} get#{f.name.capitalize}() {
+		return this.#{f.name};
+	}
+	<?rb } ?>
+
+	public void messagePack(Packer pk) throws IOException {
 		pk.packArray(#{@message.max_id});
 		<?rb 1.upto(@message.max_id) {|i| ?>
-		<?rb if f = @message[i]; ?>
-		_Pk.pack(this.#{f.name});
-		<?rb else ?>
-		_Pk.packNil();
-		<?rb end ?>
+			<?rb if f = @message[i]; ?>
+				pk.pack(this.#{f.name});
+			<?rb else ?>
+				pk.packNil();
+			<?rb end ?>
 		<?rb } ?>
 	}
 
 		}
 
 		<?rb 1.upto(@message.max_id) {|i| ?>
-		<?rb f = @message[i] ?>
-		<?rb if !f ?>
-		pac.unpackObject();
-		<?rb elsif f.required? ?>
-		this.#{f.name} = pac.#{format_unpack(f.type)};
-		<?rb elsif i <= @message.max_required_id ?>
-		if(!pac.tryUnpackNull()) {
-			this.#{f.name} = pac.#{format_unpack(f.type)};
+			<?rb f = @message[i] ?>
+			<?rb if !f ?>
+				<?rb if i > @message.max_required_id ?>
+				if(len < #{i}) { return; }
+				<?rb end ?>
+				pac.unpackObject();
+			<?rb elsif f.required? ?>
+				<?rb if f.type.nullable_type? ?>
+					if(!pac.tryUnpackNull()) {
+						#{format_unpack("this.#{f.name}", "pac", f.type.real_type)}
+					}
+				<?rb else ?>
+					if(!pac.tryUnpackNull()) {
+						throw new MessageTypeException("#{@message.name}.#{f.name} is not nullable bug got nil");
+					}
+					#{format_unpack("this.#{f.name}", "pac", f.type.real_type)}
+				<?rb end ?>
+			<?rb elsif f.optional? ?>
+				<?rb if i > @message.max_required_id ?>
+				if(len < #{i}) { return; }
+				<?rb end ?>
+				if(!pac.tryUnpackNull()) {
+					#{format_unpack("this.#{f.name}", "pac", f.type.real_type)}
+				}
+			<?rb end ?>
+		<?rb } ?>
+
+		for(int i=#{@message.max_id}; i < len; ++i) {
+			pac.unpackObject();
 		}
-		<?rb else ?>
-		if(len > #{i-1}) {
-			this.#{f.name} = pac.#{format_unpack(f.type)};
-		}
-		<?rb end ?>
-		<?rb } ?>
 	}
 
 	public void messageConvert(MessagePackObject obj) throws IOException, MessageTypeException {
 		int len = arr.length;
 
 		if(len < #{@message.max_required_id}) {
-			throw new MessagePackObject("#{@message.name} requires at least #{@message.max_required_id} elements.");
+			throw new MessageTypeException("#{@message.name} requires at least #{@message.max_required_id} elements.");
 		}
 
+		MessagePackObject obj;
+
 		<?rb 1.upto(@message.max_id) {|i| ?>
-		<?rb if f = @message[i] ?>
-
-		<?rb if f.required? ?>
-		this.#{f.name} = arr[#{i}].#{format_convert(f.type)};  // TODO
-		<?rb else ?>
-		<?rb if i > @message.max_required_id  # optional ?>
-		if(len < #{i-1}) { return; }
-		<?rb end ?>
-		if(!arr[#{i}].isNil()) {
-			this.#{f.name} = arr[#{i}].#{format_convert(f.type)};
-		}
-		<?rb end ?>
-
-		<?rb end ?>
+			<?rb f = @message[i] ?>
+			<?rb if !f ?>
+			<?rb elsif f.required? ?>
+				obj = arr[i];
+				<?rb if f.type.nullable_type? ?>
+					if(!obj.isNil()) {
+						#{format_convert("this.#{f.name}", "obj", f.type.real_type)}
+					}
+				<?rb else ?>
+					if(!obj.isNil()) {
+						throw new MessageTypeException("#{@message.name}.#{f.name} is not nullable bug got nil");
+					}
+					#{format_convert("this.#{f.name}", "obj", f.type.real_type)}
+				<?rb end ?>
+			<?rb elsif f.optional? ?>
+				<?rb if i > @message.max_required_id ?>
+				if(len < #{i}) { return; }
+				<?rb end ?>
+				obj = arr[i];
+				if(!obj.isNil()) {
+					#{format_convert("this.#{f.name}", "obj", f.type.real_type)}
+				}
+			<?rb end ?>
 		<?rb } ?>
 	}
 }

File lib/msgpack/idl/lang/java/server.java

-#{@package}
+#{format_package}
 
 import java.util.List;
-import java.util.Set;
 import java.util.Map;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.HashSet;
 import java.util.HashMap;
 import java.io.IOException;
 import org.msgpack.MessageTypeException;
+import org.msgpack.rpc.Dispatcher;
+import org.msgpack.rpc.Request;
 
-public class #{@name} {
+public class #{@name} implements Dispatcher {
 	<?rb @functions.each {|f| ?>
 	public interface I#{f.name} {
 		#{format_type(f.return_type)} #{f.name}(#{ f.args.map {|arg| format_type(arg.type) +" "+ arg.name }.join(', ') });
 	private I#{f.name} #{f.name};
 	<?rb } ?>
 
+	//void dispatch(Request request) throws Exception {
+	//}
+
 	// TODO
 }
 

File lib/msgpack/idl/parser/rule.rb

 		field_id.as(:field_id) >>
 		field_modifier.maybe.as(:field_modifier) >>
 		field_type.as(:field_type) >>
-		field_name.as(:field_name)
-		#eq_default_value.maybe.as(:field_default)
+		field_name.as(:field_name) >>
+		eq_value.maybe.as(:field_value)
 	}
 
 	rule(:field_id) {
 	}
 
 
-	rule(:eq_default_value) {
+	rule(:eq_value) {
 		k_equal >> literal
 	}
 
 
 
 	rule(:literal) {
-		literal_nil | literal_bool | literal_int | literal_float |
-		literal_str | literal_list |
-		literal_map | literal_const
+		literal_nil | literal_bool | literal_int |
+		literal_enum |
+		#literal_float | literal_str |
+		#literal_list | literal_map |
+		literal_const
 	}
 
 	rule(:literal_nil) {
 		const_name.as(:literal_const)
 	}
 
+	rule(:literal_enum) {
+		class_name.as(:literal_enum_name) >> str('.') >> field_name.as(:literal_enum_field)
+	}
+
 	rule(:literal_int) {
 		space? >> (
 			(str('-') | str('+')).maybe >>
 		(literal_str_dq | literal_str_sq).repeat(1).as(:literal_str_seq)
 	}
 
-	sequence :literal_list_seq, :k_comma, :literal
+	#sequence :literal_list_seq, :k_comma, :literal
+	#
+	#rule(:literal_list) {
+	#	space? >> k_lbracket >>
+	#		literal_list_seq.as(:literal_list) >>
+	#	k_rbracket
+	#}
 
-	rule(:literal_list) {
-		space? >> k_lbracket >>
-			literal_list_seq.as(:literal_list) >>
-		k_rbracket
-	}
-
-	sequence :literal_map_seq, :k_comma, :literal_map_pair
-
-	rule(:literal_map) {
-		space? >> k_lwing >>
-			literal_map_seq.as(:literal_map) >>
-		k_rwing
-	}
-
-	rule(:literal_map_pair) {
-		literal.as(:literal_map_key) >> k_colon >> literal.as(:literal_map_value)
-	}
+	#sequence :literal_map_seq, :k_comma, :literal_map_pair
+	#
+	#rule(:literal_map) {
+	#	space? >> k_lwing >>
+	#		literal_map_seq.as(:literal_map) >>
+	#	k_rwing
+	#}
+	#
+	#rule(:literal_map_pair) {
+	#	literal.as(:literal_map_key) >> k_colon >> literal.as(:literal_map_value)
+	#}
 
 
 	rule(:path) {

File lib/msgpack/idl/parser/transform.rb

 	rule(:field_id => simple(:i),
 			 :field_modifier => simple(:m),
 			 :field_type => simple(:t),
-			 :field_name => simple(:n)) {
+			 :field_name => simple(:n),
+			 :field_value => simple(:v)) {
 		m = m() ? m() : AST::FIELD_REQUIRED
-		AST::Field.new(i, t, m, n)
+		if v == nil
+			AST::Field.new(i, t, m, n)
+		else
+			AST::ValueAssignedField.new(i, t, m, n, v)
+		end
 	}
 
-	#rule(:field_id => simple(:i),
-	#		 :field_modifier => simple(:m),
-	#		 :field_type => simple(:t),
-	#		 :field_name => simple(:n),
-	#		 :field_default => simple(:v)) {
-	#	m ||= AST::FIELD_REQUIRED
-	#	if v == nil
-	#		AST::Field.new(i, t, m, n)
-	#	else
-	#		AST::ValueAssignedField.new(i, t, m, n, v)
-	#	end
-	#}
-
 	rule(:generic_type => simple(:n),
 			 :type_params => simple(:tp)) {
 		if tp
 	rule(:document => sequence(:es)) {
 		AST::Document.new(es)
 	}
+
+
+	rule(:literal_const => simple(:n)) {
+		AST::ConstLiteral.new(n)
+	}
+
+	rule(:literal_enum_name => simple(:n),
+			 :literal_enum_field => simple(:f)) {
+		AST::EnumLiteral.new(n, f)
+	}
+
+	rule(:literal_int => simple(:i)) {
+		AST::IntLiteral.new(i.to_i)
+	}
+
+	rule(:literal_float => simple(:f)) {
+		AST::FloatLiteral.new(f.to_f)
+	}
+
+	rule(:literal_str_dq => simple(:s)) {
+		s.to_s.gsub(/\\(.)/) {|e|
+			eval("\"\\#{$~[1]}\"")  # TODO escape
+		}
+	}
+
+	rule(:literal_str_sq => simple(:s)) {
+		s.to_s
+	}
+
+	rule(:literal_str_seq => sequence(:ss)) {
+		AST::StringLiteral.new(ss.join)
+	}
+
+	rule(:literal_nil => simple(:_)) {
+		AST::NilLiteral.new
+	}
+
+	rule(:literal_true => simple(:_)) {
+		AST::TrueLiteral.new
+	}
+
+	rule(:literal_false => simple(:_)) {
+		AST::FalseLiteral.new
+	}
+
+	#rule(:literal_list => simple(:a)) {
+	#	AST::ListLiteral.new(Array.new(a))
+	#}
+
+	#rule(:literal_map => simple(:ps)) {
+	#	AST::MapLiteral.new(Array.new(ps))
+	#}
+
+	#rule(:literal_map_key => simple(:k), :literal_map_value => simple(:v)) {
+	#	AST::MapLiteralPair.new(k, v)
+	#}
 end