Class: Mirah::JVM::Types::Number

Inherits:
PrimitiveType show all
Defined in:
lib/mirah/jvm/types/number.rb

Direct Known Subclasses

FloatType, IntegerType, LongType

Constant Summary collapse

TYPE_ORDERING =
['byte', 'short', 'int', 'long', 'float', 'double']

Constants inherited from PrimitiveType

PrimitiveType::WIDENING_CONVERSIONS

Constants included from Logging::Logged

Logging::Logged::VLEVELS

Instance Attribute Summary

Attributes inherited from Type

#inner_class, #name, #type_system

Instance Method Summary collapse

Methods inherited from PrimitiveType

#convertible_to?, #initialize, #interfaces, #newarray, #primitive?, #primitive_type, #superclass

Methods inherited from Type

#abstract?, #add_compiled_macro, #add_enumerable_macros, #add_method, #add_method_listener, #aload, #ancestors_and_interfaces, #array?, #array_type, #assignableFrom, #assignable_from?, #astore, #basic_type, #compatible?, #component_type, #constructor, #declared_class_methods, #declared_constructors, #declared_instance_methods, #declared_intrinsics, #declared_macros, #dynamic?, #error?, #expand_each, #field_getter, #field_setter, #find_callable_macros, #find_callable_macros2, #find_callable_methods, #find_callable_methods2, #full_name, #generic, #generic?, #get_method, #include, #init_value, #initialize, #inner_class?, #inner_class_getter, #inspect, #interface?, #interfaces, #intrinsics, #isArray, #isBlock, #isError, #isGeneric, #isMeta, #is_parent, #iterable?, #java_method, #jvm_type, #load, #load_extensions, #macro, #macros, #matchesAnything, #meta, #meta?, #method_listeners, #method_updated, #newarray, #pop, #prefix, #primitive?, #read_macrodef_annotation, #return, #store, #superclass, #to_s, #type_parameters, #ungeneric, #unmeta, #void?, #wide?, #widen

Methods included from Logging::Logged

#error, #info, #log, #logger, #logger_name, #logging?, #vlog, #warning

Methods included from MethodLookup

#each_is_exact, #each_is_exact_or_subtype_or_convertible, #field_lookup, #find_jls, #find_jls2, #find_method, #find_method2, #inner_class, #is_more_specific?, #phase1, #phase2, #phase3, #primitive_convertible?

Constructor Details

This class inherits a constructor from Mirah::JVM::Types::PrimitiveType

Instance Method Details

#add_delegates(name, return_type = nil) ⇒ Object



68
69
70
71
72
73
74
75
# File 'lib/mirah/jvm/types/number.rb', line 68

def add_delegates(name, return_type = nil)
  index = TYPE_ORDERING.index(math_type.name)
  larger_types = TYPE_ORDERING[index + 1, TYPE_ORDERING.size]
  larger_types.each do |type|
    type = @type_system.type(nil, type)
    delegate_intrinsic(name, type, return_type || type)
  end
end

#add_intrinsicsObject



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/mirah/jvm/types/number.rb', line 141

def add_intrinsics
  boolean_operator('<', :lt)
  boolean_operator('<=', :le)
  boolean_operator('==', :eq)
  boolean_operator('!=', :ne)
  boolean_operator('>=', :ge)
  boolean_operator('>', :gt)
  math_operator('+', :add)
  math_operator('-', :sub)
  math_operator('*', :mul)
  math_operator('/', :div)
  math_operator('%', :rem)
  unary_operator('-@', :neg)
  unary_operator('+@', nil)
end

#boolean_operator(name, op) ⇒ Object



83
84
85
86
87
# File 'lib/mirah/jvm/types/number.rb', line 83

def boolean_operator(name, op)
  args = [math_type]
  add_method(name, args, ComparisonIntrinsic.new(self, name, op, args))
  add_delegates(name, @type_system.type(nil, 'boolean'))
end

#box(builder) ⇒ Object



157
158
159
# File 'lib/mirah/jvm/types/number.rb', line 157

def box(builder)
  builder.invokestatic box_type, "valueOf", [box_type, math_type]
end

#compile_boolean_operator(compiler, op, negated, call, label) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/mirah/jvm/types/number.rb', line 102

def compile_boolean_operator(compiler, op, negated, call, label)
  # Promote the target or the argument if necessary
  convert_args(compiler,
               [call.target, *call.parameters],
               [math_type, math_type])
  if negated
    op = invert_op(op)
  end
  if label
    jump_if(compiler.method, op, label)
  else
    compiler.method.op_to_bool do |label|
      jump_if(compiler.method, op, label)
    end
  end
end

#delegate_intrinsic(name, type, return_type) ⇒ Object

Adds an intrinsic that delegates to an intrinsic in another primitive type. That type must support promoting the “this” argument.



54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/mirah/jvm/types/number.rb', line 54

def delegate_intrinsic(name, type, return_type)
  args = [type]
  delegate = type.intrinsics[name][args]
  if delegate.kind_of?(ComparisonIntrinsic)
    add_method(name, args, ComparisonIntrinsic.new(type, name, delegate.op, args))
  else
    add_method(name, args, return_type) do |compiler, call, expression|
      if expression
        delegate.call(compiler, call, expression)
      end
    end
  end
end

#invert_op(op) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/mirah/jvm/types/number.rb', line 89

def invert_op(op)
  inverted = {
    :lt => :ge,
    :le => :gt,
    :eq => :ne,
    :ne => :eq,
    :gt => :le,
    :ge => :lt
  }[op]
  raise "Can't invert #{op}." unless inverted
  inverted
end

#jump_if(builder, op, label) ⇒ Object

if_cmpxx for non-ints



78
79
80
81
# File 'lib/mirah/jvm/types/number.rb', line 78

def jump_if(builder, op, label)
  builder.send "#{prefix}cmp#{suffix}"
  builder.send "if#{op}", label
end

#math_operator(name, op) ⇒ Object



119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/mirah/jvm/types/number.rb', line 119

def math_operator(name, op)
  add_method(name, [math_type], math_type) do |compiler, call, expression|
    if expression
      # Promote the target or the argument if necessary
      convert_args(compiler,
                   [call.target, *call.parameters],
                   [math_type, math_type])
      compiler.method.send "#{prefix}#{op}"
    end
  end
  add_delegates(name)
end

#math_typeObject

The type returned by arithmetic operations with this type.



44
45
46
# File 'lib/mirah/jvm/types/number.rb', line 44

def math_type
  self
end

#suffixObject



48
49
50
# File 'lib/mirah/jvm/types/number.rb', line 48

def suffix
  ''
end

#unary_operator(name, op) ⇒ Object



132
133
134
135
136
137
138
139
# File 'lib/mirah/jvm/types/number.rb', line 132

def unary_operator(name, op)
  add_method(name, [], math_type) do |compiler, call, expression|
    if expression
      call.target.compile(compiler, true)
      compiler.method.send("#{prefix}#{op}") if op
    end
  end
end