Module: RubyRunJs::Operation

Includes:
Helper
Included in:
RubyRunJs::OPCODES::OP_CODE
Defined in:
lib/ruby_run_js/operations.rb

Instance Method Summary collapse

Methods included from Helper

#check_object, #get_member, #get_member_dot, #is_accessor_descriptor, #is_callable, #is_data_descriptor, #is_generic_descriptor, #is_primitive, #make_error, #strict_equality

Methods included from ConversionHelper

#convert_to_js_type, #to_boolean, #to_int32, #to_integer, #to_number, #to_object, #to_primitive, #to_string, #to_uint16, #to_uint32

Instance Method Details

#abstract_equality_op(p1, p2) ⇒ Object



305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/ruby_run_js/operations.rb', line 305

def abstract_equality_op(p1, p2)
  ''' returns the result of JS == compare.
    result is PyJs type: bool'''
  tx, ty = p1.js_type, p2.js_type
  if tx == ty
    if tx == :Undefined || tx == :Null
      return true
    end
    if tx == :Number || tx == :String || tx == :Boolean
      return p1 == p2
    end
    return p1.equal?(p2)
  elsif (tx == :Undefined && ty == :Null) || (ty == :Undefined && tx == :Null)
    return true
  elsif tx == :Number && ty == :String
    return abstract_equality_op(p1, to_number(p2))
  elsif tx == :String && ty == :Number
    return abstract_equality_op(to_number(p1), p2)
  elsif tx == :Boolean
    return abstract_equality_op(to_number(p1), p2)
  elsif ty == :Boolean
    return abstract_equality_op(p1, to_number(p2))
  elsif (tx == :String || tx == :Number) && p2.js_type == :Object
    return abstract_equality_op(p1, to_primitive(p2))
  elsif (ty == :String || ty == :Number) && p1.js_type == :Object
    return abstract_equality_op(to_primitive(p1), p2)
  else
    return false
  end
end

#abstract_inequality_op(p1, p2) ⇒ Object



336
337
338
# File 'lib/ruby_run_js/operations.rb', line 336

def abstract_inequality_op(p1, p2)
  !abstract_equality_op(p1, p2)
end

#abstract_relational_comparison(p1, p2, p1_first = true) ⇒ Object

Comparisons <, <=, !=, ==, >=, > are implemented here.



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/ruby_run_js/operations.rb', line 238

def abstract_relational_comparison(p1, p2, p1_first = true)  # todo speed up!
  ''' p1<p2 if p1_first else p2<p1.
    Returns the result of the question: is p1 smaller than p2?
    in case p1_first is false it returns the answer of:
                                        is p2 smaller than p1.
    result is PyJs type: bool || undefined'''
  
  px = to_primitive(p1, :Number)
  py = to_primitive(p2, :Number)
  if !p1_first  # reverse ||der
    px, py = py, px
  end
  unless (px.js_type == :String && py.js_type == :String)
    px = to_number(px)
    py = to_number(py)
    if px.nan? || py.nan?
      return nil  # watch out here!
    end
    return px < py  # same cmp alg||ithm
  else
    return px < py
  end
end

#add_op(p1, p2) ⇒ Object

+



176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
# File 'lib/ruby_run_js/operations.rb', line 176

def add_op(p1, p2)
  if p1.js_type == :Float && p2.js_type == :Float
      return p1 + p2
  end
  if p1.js_type == :String && p2.js_type == :String
      return p1 + p2
  end
  # st&&ard way...
  a = to_primitive(p1)
  b = to_primitive(p2)
  if a.js_type == :String || b.js_type == :String  # string wins hehe
    return to_string(a) + to_string(b)
  end
  to_number(a) + to_number(b)
end

#binary_operation(operator, p1, p2) ⇒ Object



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/ruby_run_js/operations.rb', line 25

def binary_operation(operator, p1, p2)
  case operator
  when '+'
    add_op(p1, p2)
  when '-'
    sub_op(p1, p2)
  when '*'
    mul_op(p1, p2)
  when '/'
    div_op(p1, p2)
  when '%'
    mod_op(p1, p2)
  when '<<'
    bit_lshift_op(p1, p2)
  when '>>'
    bit_rshift_op(p1, p2)
  when '>>>'
    bit_bshift_op(p1, p2)
  when '|'
    bit_or_op(p1, p2)
  when '&'
    bit_and_op(p1, p2)
  when '^'
    bit_xor_op(p1, p2)
  when '=='
    abstract_equality_op(p1, p2)
  when '!='
    abstract_inequality_op(p1, p2)
  when '==='
    strict_equality_op(p1, p2)
  when '!=='
    strict_inequality_op(p1, p2)
  when '<'
    less_op(p1, p2)
  when '<='
    less_eq_op(p1, p2)
  when '>'
    greater_op(p1, p2)
  when '>='
    greater_eq_op(p1, p2)
  when 'in'
    in_op(p1, p2)
  when 'instanceof'
    instanceof_op(p1, p2)
  end
end

#bit_and_op(p1, p2) ⇒ Object

&



148
149
150
151
152
# File 'lib/ruby_run_js/operations.rb', line 148

def bit_and_op(p1, p2)
  lnum = to_int32(p1)
  rnum = to_int32(p2)
  float(to_int32(float(lnum & rnum)))
end

#bit_bshift_op(p1, p2) ⇒ Object



139
140
141
142
143
144
# File 'lib/ruby_run_js/operations.rb', line 139

def bit_bshift_op(p1, p2)
  lnum = to_uint32(p1)
  rnum = to_uint32(p2)
  shiftCount = rnum & 0x1F
  float(to_uint32(float(lnum >> shiftCount)))
end

#bit_invert_uop(target) ⇒ Object

~u



99
100
101
102
103
# File 'lib/ruby_run_js/operations.rb', line 99

def bit_invert_uop(target)
  target = ~to_int32(target)
  target = to_int32(target.to_f)
  target.to_f
end

#bit_lshift_op(p1, p2) ⇒ Object



122
123
124
125
126
127
# File 'lib/ruby_run_js/operations.rb', line 122

def bit_lshift_op(p1, p2)
  lnum = to_int32(p1)
  rnum = to_uint32(p2)
  shiftCount = rnum & 0x1F
  float(to_int32(float(lnum << shiftCount)))
end

#bit_or_op(p1, p2) ⇒ Object

|



164
165
166
167
168
# File 'lib/ruby_run_js/operations.rb', line 164

def bit_or_op(p1, p2)
  lnum = to_int32(p1)
  rnum = to_int32(p2)
  float(to_int32(float(lnum | rnum)))
end

#bit_rshift_op(p1, p2) ⇒ Object

>>



130
131
132
133
134
135
# File 'lib/ruby_run_js/operations.rb', line 130

def bit_rshift_op(p1, p2)
  lnum = to_int32(p1)
  rnum = to_uint32(p2)
  shiftCount = rnum & 0x1F
  float(to_int32(float(lnum >> shiftCount)))
end

#bit_xor_op(p1, p2) ⇒ Object

^



156
157
158
159
160
# File 'lib/ruby_run_js/operations.rb', line 156

def bit_xor_op(p1, p2)
  lnum = to_int32(p1)
  rnum = to_int32(p2)
  float(to_int32(float(lnum ^ rnum)))
end

#div_op(p1, p2) ⇒ Object

/



207
208
209
210
211
# File 'lib/ruby_run_js/operations.rb', line 207

def div_op(p1, p2)
  a = to_number(p1)
  b = to_number(p2)
  a / b
end

#float(x) ⇒ Object

<<



118
119
120
# File 'lib/ruby_run_js/operations.rb', line 118

def float(x)
  x.to_f
end

#greater_eq_op(p1, p2) ⇒ Object

>=



284
285
286
287
288
289
290
# File 'lib/ruby_run_js/operations.rb', line 284

def greater_eq_op(p1, p2)
  res = abstract_relational_comparison(p1, p2, true)
  if res.nil?
    return false
  end
  return !res
end

#greater_op(p1, p2) ⇒ Object

>



294
295
296
297
298
299
300
# File 'lib/ruby_run_js/operations.rb', line 294

def greater_op(p1, p2)
  res = abstract_relational_comparison(p1, p2, false)
  if res.nil?
    return false
  end
  return res
end

#in_op(p1, p2) ⇒ Object



370
371
372
373
374
375
376
# File 'lib/ruby_run_js/operations.rb', line 370

def in_op(p1, p2)
  '''checks if p1 is in p2'''
  if p2.js_type != :Object
    raise make_error('TypeError', "You can\'t use 'in' operator to search in non-objects")
  end
  p2.has_property(to_string(p1))
end

#instanceof_op(p1, p2) ⇒ Object



359
360
361
362
363
364
365
366
367
368
# File 'lib/ruby_run_js/operations.rb', line 359

def instanceof_op(p1, p2)
  '''checks if p1 is instance of p2'''
  if p2.js_type != :Object
    raise make_error('TypeError', 'instanceof called on a non-object')
  end
  unless p2.methods.include?(:has_instance)
    raise make_error('TypeError', 'instanceof called on a non-object')
  end
  return p2.has_instance(p1)
end

#less_eq_op(p1, p2) ⇒ Object

<=



274
275
276
277
278
279
280
# File 'lib/ruby_run_js/operations.rb', line 274

def less_eq_op(p1, p2)
  res = abstract_relational_comparison(p1, p2, false)
  if res.nil?
    return false
  end
  return !res
end

#less_op(p1, p2) ⇒ Object

<



264
265
266
267
268
269
270
# File 'lib/ruby_run_js/operations.rb', line 264

def less_op(p1, p2)
  res = abstract_relational_comparison(p1, p2, true)
  if res.nil?
    return false
  end
  return res
end

#logical_negation_uop(target) ⇒ Object

!x



82
83
84
# File 'lib/ruby_run_js/operations.rb', line 82

def logical_negation_uop(target)  # !u  cant do 'not u' :(
  !to_boolean(target)
end

#minus_uop(target) ⇒ Object

-x



73
74
75
# File 'lib/ruby_run_js/operations.rb', line 73

def minus_uop(target)
    -to_number(target)
end

#mod_op(p1, p2) ⇒ Object

%



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/ruby_run_js/operations.rb', line 214

def mod_op(p1, p2)
  a = to_number(p1)
  b = to_number(p2)
  if a.abs == Float::INFINITY || b == 0.0
    return Float::NAN
  end
  if b.abs == Float::INFINITY
    return a
  end
  res = a % b  # different signs in python && javascript
  # python has the same sign as b && js has the same
  # sign as a.
  if a < 0 && res > 0
    res -= b.abs
  elsif a > 0 && res < 0
    res += b.abs
  end
  return float(res)
end

#mul_op(p1, p2) ⇒ Object

*



202
203
204
# File 'lib/ruby_run_js/operations.rb', line 202

def mul_op(p1, p2)
  return to_number(p1) * to_number(p2)
end

#plus_uop(target) ⇒ Object

+x



77
78
79
# File 'lib/ruby_run_js/operations.rb', line 77

def plus_uop(target)  # +u
  to_number(target)
end

#strict_equality_op(p1, p2) ⇒ Object



340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/ruby_run_js/operations.rb', line 340

def strict_equality_op(p1, p2)
  typ = p1.js_type
  if typ != p2.js_type
    return false
  end
  if typ == :Undefined || typ == :Null
    return true
  end
  if typ == :Boolean || typ == :String || typ == :Number
    return p1 == p2
  else  # object
    return p1.equal?(p2)  # Id compare.
  end
end

#strict_inequality_op(p1, p2) ⇒ Object



355
356
357
# File 'lib/ruby_run_js/operations.rb', line 355

def strict_inequality_op(p1, p2)
  !strict_equality_op(p1, p2)
end

#sub_op(p1, p2) ⇒ Object

-



193
194
195
# File 'lib/ruby_run_js/operations.rb', line 193

def sub_op(p1, p2)
  return to_number(p1) - to_number(p2)
end

#typeof_uop(target) ⇒ Object

typeof x



87
88
89
90
91
92
93
94
95
96
# File 'lib/ruby_run_js/operations.rb', line 87

def typeof_uop(target)
  if is_callable(target)
      return 'function'
  end
  typ = target.js_type.to_s.downcase
  if typ == 'null'
      typ = 'object'  # absolutely idiotic...
  end
  typ
end

#unary_operation(operator, target) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/ruby_run_js/operations.rb', line 6

def unary_operation(operator, target)
  case operator
  when '+'
    plus_uop(target)
  when '-'
    minus_uop(target)
  when '!'
    logical_negation_uop(target)
  when '~'
    bit_invert_uop(target)
  when 'void'
    void_op(target)
  when 'typeof'
    typeof_uop(target)
  else
    raise 'Unkown operator: ' + operator
  end
end

#void_op(target) ⇒ Object

void



106
107
108
# File 'lib/ruby_run_js/operations.rb', line 106

def void_op(target)
  undefined
end