folder reorganization
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
from __future__ import unicode_literals
|
||||
from simplex import *
|
||||
from conversions import *
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# Unary operations
|
||||
|
||||
|
||||
# -x
|
||||
def minus_uop(self):
|
||||
return -to_number(self)
|
||||
|
||||
|
||||
# +x
|
||||
def plus_uop(self): # +u
|
||||
return to_number(self)
|
||||
|
||||
|
||||
# !x
|
||||
def logical_negation_uop(self): # !u cant do 'not u' :(
|
||||
return not to_boolean(self)
|
||||
|
||||
|
||||
# typeof x
|
||||
def typeof_uop(self):
|
||||
if is_callable(self):
|
||||
return u'function'
|
||||
typ = Type(self).lower()
|
||||
if typ == u'null':
|
||||
typ = u'object' # absolutely idiotic...
|
||||
return typ
|
||||
|
||||
|
||||
# ~u
|
||||
def bit_invert_uop(self):
|
||||
return float(to_int32(float(~to_int32(self))))
|
||||
|
||||
|
||||
# void
|
||||
def void_op(self):
|
||||
return undefined
|
||||
|
||||
|
||||
UNARY_OPERATIONS = {
|
||||
'+': plus_uop,
|
||||
'-': minus_uop,
|
||||
'!': logical_negation_uop,
|
||||
'~': bit_invert_uop,
|
||||
'void': void_op,
|
||||
'typeof':
|
||||
typeof_uop, # this one only for member expressions! for identifiers its slightly different...
|
||||
}
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# ----- binary ops -------
|
||||
|
||||
# Bitwise operators
|
||||
# <<, >>, &, ^, |, ~
|
||||
|
||||
|
||||
# <<
|
||||
def bit_lshift_op(self, other):
|
||||
lnum = to_int32(self)
|
||||
rnum = to_uint32(other)
|
||||
shiftCount = rnum & 0x1F
|
||||
return float(to_int32(float(lnum << shiftCount)))
|
||||
|
||||
|
||||
# >>
|
||||
def bit_rshift_op(self, other):
|
||||
lnum = to_int32(self)
|
||||
rnum = to_uint32(other)
|
||||
shiftCount = rnum & 0x1F
|
||||
return float(to_int32(float(lnum >> shiftCount)))
|
||||
|
||||
|
||||
# >>>
|
||||
def bit_bshift_op(self, other):
|
||||
lnum = to_uint32(self)
|
||||
rnum = to_uint32(other)
|
||||
shiftCount = rnum & 0x1F
|
||||
return float(to_uint32(float(lnum >> shiftCount)))
|
||||
|
||||
|
||||
# &
|
||||
def bit_and_op(self, other):
|
||||
lnum = to_int32(self)
|
||||
rnum = to_int32(other)
|
||||
return float(to_int32(float(lnum & rnum)))
|
||||
|
||||
|
||||
# ^
|
||||
def bit_xor_op(self, other):
|
||||
lnum = to_int32(self)
|
||||
rnum = to_int32(other)
|
||||
return float(to_int32(float(lnum ^ rnum)))
|
||||
|
||||
|
||||
# |
|
||||
def bit_or_op(self, other):
|
||||
lnum = to_int32(self)
|
||||
rnum = to_int32(other)
|
||||
return float(to_int32(float(lnum | rnum)))
|
||||
|
||||
|
||||
# Additive operators
|
||||
# + and - are implemented here
|
||||
|
||||
|
||||
# +
|
||||
def add_op(self, other):
|
||||
if type(self) is float and type(other) is float:
|
||||
return self + other
|
||||
if type(self) is unicode and type(other) is unicode:
|
||||
return self + other
|
||||
# standard way...
|
||||
a = to_primitive(self)
|
||||
b = to_primitive(other)
|
||||
if type(a) is unicode or type(b) is unicode: # string wins hehe
|
||||
return to_string(a) + to_string(b)
|
||||
return to_number(a) + to_number(b)
|
||||
|
||||
|
||||
# -
|
||||
def sub_op(self, other):
|
||||
return to_number(self) - to_number(other)
|
||||
|
||||
|
||||
# Multiplicative operators
|
||||
# *, / and % are implemented here
|
||||
|
||||
|
||||
# *
|
||||
def mul_op(self, other):
|
||||
return to_number(self) * to_number(other)
|
||||
|
||||
|
||||
# /
|
||||
def div_op(self, other):
|
||||
a = to_number(self)
|
||||
b = to_number(other)
|
||||
if b:
|
||||
return a / float(b) # ensure at least one is a float.
|
||||
if not a or a != a:
|
||||
return NaN
|
||||
return Infinity if a > 0 else -Infinity
|
||||
|
||||
|
||||
# %
|
||||
def mod_op(self, other):
|
||||
a = to_number(self)
|
||||
b = to_number(other)
|
||||
if abs(a) == Infinity or not b:
|
||||
return NaN
|
||||
if abs(b) == Infinity:
|
||||
return a
|
||||
pyres = a % b # different signs in python and javascript
|
||||
# python has the same sign as b and js has the same
|
||||
# sign as a.
|
||||
if a < 0 and pyres > 0:
|
||||
pyres -= abs(b)
|
||||
elif a > 0 and pyres < 0:
|
||||
pyres += abs(b)
|
||||
return float(pyres)
|
||||
|
||||
|
||||
# Comparisons
|
||||
# <, <=, !=, ==, >=, > are implemented here.
|
||||
def abstract_relational_comparison(self, other,
|
||||
self_first=True): # todo speed up!
|
||||
''' self<other if self_first else other<self.
|
||||
Returns the result of the question: is self smaller than other?
|
||||
in case self_first is false it returns the answer of:
|
||||
is other smaller than self.
|
||||
result is PyJs type: bool or undefined'''
|
||||
|
||||
px = to_primitive(self, 'Number')
|
||||
py = to_primitive(other, 'Number')
|
||||
if not self_first: # reverse order
|
||||
px, py = py, px
|
||||
if not (Type(px) == 'String' and Type(py) == 'String'):
|
||||
px, py = to_number(px), to_number(py)
|
||||
if is_nan(px) or is_nan(py):
|
||||
return None # watch out here!
|
||||
return px < py # same cmp algorithm
|
||||
else:
|
||||
# I am pretty sure that python has the same
|
||||
# string cmp algorithm but I have to confirm it
|
||||
return px < py
|
||||
|
||||
|
||||
# <
|
||||
def less_op(self, other):
|
||||
res = abstract_relational_comparison(self, other, True)
|
||||
if res is None:
|
||||
return False
|
||||
return res
|
||||
|
||||
|
||||
# <=
|
||||
def less_eq_op(self, other):
|
||||
res = abstract_relational_comparison(self, other, False)
|
||||
if res is None:
|
||||
return False
|
||||
return not res
|
||||
|
||||
|
||||
# >=
|
||||
def greater_eq_op(self, other):
|
||||
res = abstract_relational_comparison(self, other, True)
|
||||
if res is None:
|
||||
return False
|
||||
return not res
|
||||
|
||||
|
||||
# >
|
||||
def greater_op(self, other):
|
||||
res = abstract_relational_comparison(self, other, False)
|
||||
if res is None:
|
||||
return False
|
||||
return res
|
||||
|
||||
|
||||
# equality
|
||||
|
||||
|
||||
def abstract_equality_op(self, other):
|
||||
''' returns the result of JS == compare.
|
||||
result is PyJs type: bool'''
|
||||
tx, ty = Type(self), Type(other)
|
||||
if tx == ty:
|
||||
if tx == 'Undefined' or tx == 'Null':
|
||||
return True
|
||||
if tx == 'Number' or tx == 'String' or tx == 'Boolean':
|
||||
return self == other
|
||||
return self is other # Object
|
||||
elif (tx == 'Undefined' and ty == 'Null') or (ty == 'Undefined'
|
||||
and tx == 'Null'):
|
||||
return True
|
||||
elif tx == 'Number' and ty == 'String':
|
||||
return abstract_equality_op(self, to_number(other))
|
||||
elif tx == 'String' and ty == 'Number':
|
||||
return abstract_equality_op(to_number(self), other)
|
||||
elif tx == 'Boolean':
|
||||
return abstract_equality_op(to_number(self), other)
|
||||
elif ty == 'Boolean':
|
||||
return abstract_equality_op(self, to_number(other))
|
||||
elif (tx == 'String' or tx == 'Number') and is_object(other):
|
||||
return abstract_equality_op(self, to_primitive(other))
|
||||
elif (ty == 'String' or ty == 'Number') and is_object(self):
|
||||
return abstract_equality_op(to_primitive(self), other)
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def abstract_inequality_op(self, other):
|
||||
return not abstract_equality_op(self, other)
|
||||
|
||||
|
||||
def strict_equality_op(self, other):
|
||||
typ = Type(self)
|
||||
if typ != Type(other):
|
||||
return False
|
||||
if typ == 'Undefined' or typ == 'Null':
|
||||
return True
|
||||
if typ == 'Boolean' or typ == 'String' or typ == 'Number':
|
||||
return self == other
|
||||
else: # object
|
||||
return self is other # Id compare.
|
||||
|
||||
|
||||
def strict_inequality_op(self, other):
|
||||
return not strict_equality_op(self, other)
|
||||
|
||||
|
||||
def instanceof_op(self, other):
|
||||
'''checks if self is instance of other'''
|
||||
if not hasattr(other, 'has_instance'):
|
||||
return False
|
||||
return other.has_instance(self)
|
||||
|
||||
|
||||
def in_op(self, other):
|
||||
'''checks if self is in other'''
|
||||
if not is_object(other):
|
||||
raise MakeError(
|
||||
'TypeError',
|
||||
"You can\'t use 'in' operator to search in non-objects")
|
||||
return other.has_property(to_string(self))
|
||||
|
||||
|
||||
BINARY_OPERATIONS = {
|
||||
'+': add_op,
|
||||
'-': sub_op,
|
||||
'*': mul_op,
|
||||
'/': div_op,
|
||||
'%': mod_op,
|
||||
'<<': bit_lshift_op,
|
||||
'>>': bit_rshift_op,
|
||||
'>>>': bit_bshift_op,
|
||||
'|': bit_or_op,
|
||||
'&': bit_and_op,
|
||||
'^': bit_xor_op,
|
||||
'==': abstract_equality_op,
|
||||
'!=': abstract_inequality_op,
|
||||
'===': strict_equality_op,
|
||||
'!==': strict_inequality_op,
|
||||
'<': less_op,
|
||||
'<=': less_eq_op,
|
||||
'>': greater_op,
|
||||
'>=': greater_eq_op,
|
||||
'in': in_op,
|
||||
'instanceof': instanceof_op,
|
||||
}
|
||||
Reference in New Issue
Block a user