lib/ridl/type.rb
#-------------------------------------------------------------------- # type.rb - IDL types # # Author: Martin Corino # # This program is free software; you can redistribute it and/or # modify it under the terms of the RIDL LICENSE which is # included with this program. # # Copyright (c) Remedy IT Expertise BV #-------------------------------------------------------------------- module IDL class Type def typename self.class.name end def typeerror(val) raise "#{val.inspect} cannot narrow to #{self.typename}" end def narrow(obj) obj end def resolved_type self end def is_complete? true end def is_local?(_recurstk = nil) false end def is_anonymous? false end def is_node?(_node_class) false end def resolved_node nil end def is_template? false end def matches?(idltype) self.class == idltype.class end def instantiate(_) self end class UndefinedType def initialize(*_args) raise "#{self.class.name}'s not implemented yet." end end class Void < Type def narrow(obj) typeerror(obj) unless obj.nil? obj end end class NodeType < Type attr_reader :node def initialize(node) raise node.inspect if node && !node.is_a?(IDL::AST::Leaf) @node = node end def is_local?(_recurstk = nil) @node.is_local? end def is_node?(node_class) @node.is_a?(node_class) end def resolved_node @node end def matches?(idltype) super && self.resolved_node == idltype.resolved_node end end class ScopedName < NodeType def typename @node.name end def narrow(obj) @node.idltype.narrow(obj) end def resolved_type @node.idltype.resolved_type end def is_complete? resolved_type.is_complete? end def is_local?(recurstk = []) resolved_type.is_local?(recurstk) end def is_node?(node_class) @node.is_a?(IDL::AST::Typedef) ? @node.idltype.is_node?(node_class) : @node.is_a?(node_class) end def resolved_node @node.is_a?(IDL::AST::Typedef) ? @node.idltype.resolved_node : @node end def is_template? @node.is_template? end def instantiate(instantiation_context) if self.is_template? cp = IDL::AST::TemplateParam.concrete_param(instantiation_context, @node) cp.is_a?(Type) ? cp : ScopedName.new(cp) else self end end end class Integer < Type def narrow(obj) typeerror(obj) unless ::Integer === obj typeerror(obj) unless self.class::Range === obj obj end def self.is_unsigned? self::Range.first.zero? end def self.bits self::BITS end def range_length 1 + (self.class::Range.last - self.class::Range.first) end def min self.class::Range.first end def max self.class::Range.last end def in_range?(val) val >= self.min && val <= self.max end def next(val) val < self.max ? val + 1 : self.min end def Integer.newclass(range, bits) k = Class.new(self) k.const_set('Range', range) k.const_set('BITS', bits) k end end Octet = Integer.newclass(0..0xFF, 8) UShort = Integer.newclass(0..0xFFFF, 16) ULong = Integer.newclass(0..0xFFFFFFFF, 32) ULongLong = Integer.newclass(0..0xFFFFFFFFFFFFFFFF, 64) Short = Integer.newclass(-0x8000...0x8000, 16) Long = Integer.newclass(-0x80000000...0x80000000, 32) LongLong = Integer.newclass(-0x8000000000000000...0x8000000000000000, 64) class Boolean < Type Range = [true, false] def narrow(obj) typeerror(obj) unless [TrueClass, FalseClass].include? obj.class obj end def range_length 2 end def min false end def max true end def in_range?(val) Range.include?(val) end def next(val) !val end end class Char < Type def narrow(obj) typeerror(obj) unless ::Integer === obj typeerror(obj) unless (0..255) === obj obj end def range_length 256 end def min 0 end def in_range?(val) val >= self.min && val <= self.max end def max 255 end def next(val) val < self.max ? val + 1 : self.min end end class Float < Type def narrow(obj) typeerror(obj) unless ::Float === obj obj end end class Double < Float; end class LongDouble < Float; end class Fixed < Type attr_reader :digits, :scale def initialize(digits = nil, scale = nil) raise "significant digits for Fixed should be in the range 0-31" unless digits.nil? || (0..31) === digits.to_i @digits = digits.nil? ? digits : digits.to_i @scale = scale.nil? ? scale : scale.to_i end def narrow(obj) # typeerror(obj) obj end def is_anonymous? false end def is_template? (@size && @size.is_a?(IDL::Expression) && @size.is_template?) end def instantiate(instantiation_context) self.is_template? ? (Type::Fixed.new(@size.instantiate(instantiation_context).value)) : self end end class String < Type attr_reader :size def length @size end def initialize(size = nil) @size = size end def narrow(obj) typeerror(obj) unless ::String === obj if @size.nil? obj elsif @size < obj.size typeerror(obj) else obj end end def is_anonymous? @size ? true : false end def is_template? (@size && @size.is_a?(IDL::Expression) && @size.is_template?) end def matches?(idltype) super && self.size == idltype.size end def instantiate(instantiation_context) self.is_template? ? (Type::String.new(@size.instantiate(instantiation_context).value)) : self end end class Sequence < Type attr_reader :size, :basetype attr_accessor :recursive def length @size end def initialize(t, size) raise "Anonymous type definitions are not allowed!" if t.is_anonymous? @basetype = t @size = size @typename = format("sequence<%s%s>", t.typename, if @size.nil? then "" else ", #{IDL::Expression::ScopedName === size ? size.node.name : size.to_s}" end) @recursive = false end def typename @typename end def narrow(obj) typeerror(obj) end def is_complete? @basetype.resolved_type.is_complete? end def is_local?(recurstk = []) @basetype.resolved_type.is_local?(recurstk) end def is_recursive? @recursive end def is_anonymous? true end def is_template? (@size && @size.is_a?(IDL::Expression::ScopedName) && @size.node.is_a?(IDL::AST::TemplateParam)) || @basetype.is_template? end def matches?(idltype) super && self.size == idltype.size && self.basetype.resolved_type.matches?(idltype.basetype.resolved_type) end def instantiate(instantiation_context) if self.is_template? Type::Sequence.new(@basetype.instantiate(instantiation_context), @size ? @size.instantiate(instantiation_context).value : nil) else self end end end class Array < Type attr_reader :basetype, :sizes def initialize(t, sizes) raise "Anonymous type definitions are not allowed!" if t.is_anonymous? @basetype = t if sizes.nil? @sizes = [] @typename = t.typename + "[]" else @sizes = sizes @typename = t.typename + sizes.collect { |s| "[#{IDL::Expression::ScopedName === s ? s.node.name : s.to_s}]" }.join end end def typename @typename end def narrow(obj) typeerror(obj) end def is_complete? @basetype.resolved_type.is_complete? end def is_local?(recurstk = []) @basetype.resolved_type.is_local?(recurstk) end def is_anonymous? true end def is_template? @sizes.any? { |sz| (sz.is_a?(IDL::Expression::ScopedName) && sz.node.is_a?(IDL::AST::TemplateParam)) } || @basetype.is_template? end def matches?(idltype) super && self.sizes == idltype.sizes && self.basetype.resolved_type.matches?(idltype.basetype.resolved_type) end def instantiate(instantiation_context) self.is_template? ? Type::Array.new(@basetype.instantiate(instantiation_context), @sizes.collect { |sz| sz.instantiate(instantiation_context).value }) : self end end class WString < Type attr_reader :size def length @size end def initialize(size = nil) @size = size end def narrow(obj) typeerror(obj) unless ::Array === obj if @size.nil? obj elsif @size < obj.size typeerror(obj) else obj end end def is_anonymous? @size ? true : false end def is_template? (@size && @size.is_a?(IDL::Expression::ScopedName) && @size.node.is_a?(IDL::AST::TemplateParam)) end def matches?(idltype) super && self.size == idltype.size end def instantiate(instantiation_context) self.is_template? ? Type::WString.new(@size.instantiate(instantiation_context).value) : self end end class WChar < Type def narrow(obj) typeerror(obj) unless ::Array === obj typeerror(obj) unless obj.size == 2 obj end end class Any < Type end class Object < Type end class ValueBase < Type end class Native < Type end class TemplateModule < NodeType end class Interface < NodeType end class Home < NodeType end class Component < NodeType end class Porttype < NodeType end class Valuebox < NodeType def is_local?(recurstk = []) node.is_local?(recurstk) end end class Valuetype < NodeType def is_complete? node.is_defined? end def is_local?(recurstk = []) node.is_local?(recurstk) end end class Eventtype < Valuetype end class Struct < NodeType def is_complete? node.is_defined? end def is_local?(recurstk = []) node.is_local?(recurstk) end end class Exception < Struct end class Union < NodeType def is_complete? node.is_defined? end def is_local?(recurstk = []) node.is_local?(recurstk) end end class Enum < NodeType def narrow(obj) typeerror(obj) unless ::Integer === obj typeerror(obj) unless (0...@node.enumerators.length) === obj obj end def range_length @node.enumerators.length end def min 0 end def max @node.enumerators.length - 1 end def in_range?(val) val >= self.min && val <= self.max end def next(val) val < self.max ? val + 1 : self.min end end class Const < Type attr_reader :type def initialize(t) @type = t @typename = "const #{t.typename}" end def typename @typename end def narrow(obj) @type.narrow(obj) end def is_complete? @type.resolved_type.is_complete? end def is_local?(recurstk = []) @type.resolved_type.is_local?(recurstk) end def is_anonymous? t.resolved_type.is_anonymous? end def is_template? @type.is_template? end def instantiate(instantiation_context) self.is_template? ? Type::Const.new(@type.instantiate(instantiation_context)) : self end def is_node?(node_class) @type.is_node?(node_class) end def resolved_node @type.resolved_node end def matches?(idltype) super && self.type.resolved_type.matches?(idltype.type.resolved_type) end end end end