bazarr/libs/js2py/internals/conversions.py

142 lines
4.1 KiB
Python

from __future__ import unicode_literals
# Type Conversions. to_type. All must return PyJs subclass instance
from .simplex import *
def to_primitive(self, hint=None):
if is_primitive(self):
return self
if hint is None and (self.Class == 'Number' or self.Class == 'Boolean'):
# favour number for Class== Number or Boolean default = String
hint = 'Number'
return self.default_value(hint)
def to_boolean(self):
typ = Type(self)
if typ == 'Boolean': # no need to convert
return self
elif typ == 'Null' or typ == 'Undefined': # they are both always false
return False
elif typ == 'Number': # false only for 0, and NaN
return self and self == self # test for nan (nan -> flase)
elif typ == 'String':
return bool(self)
else: # object - always True
return True
def to_number(self):
typ = Type(self)
if typ == 'Number': # or self.Class=='Number': # no need to convert
return self
elif typ == 'Null': # null is 0
return 0.
elif typ == 'Undefined': # undefined is NaN
return NaN
elif typ == 'Boolean': # 1 for True 0 for false
return float(self)
elif typ == 'String':
s = self.strip() # Strip white space
if not s: # '' is simply 0
return 0.
if 'x' in s or 'X' in s[:3]: # hex (positive only)
try: # try to convert
num = int(s, 16)
except ValueError: # could not convert -> NaN
return NaN
return float(num)
sign = 1 # get sign
if s[0] in '+-':
if s[0] == '-':
sign = -1
s = s[1:]
if s == 'Infinity': # Check for infinity keyword. 'NaN' will be NaN anyway.
return sign * Infinity
try: # decimal try
num = sign * float(s) # Converted
except ValueError:
return NaN # could not convert to decimal > return NaN
return float(num)
else: # object - most likely it will be NaN.
return to_number(to_primitive(self, 'Number'))
def to_string(self):
typ = Type(self)
if typ == 'String':
return self
elif typ == 'Null':
return 'null'
elif typ == 'Undefined':
return 'undefined'
elif typ == 'Boolean':
return 'true' if self else 'false'
elif typ == 'Number': # or self.Class=='Number':
return js_dtoa(self)
else: # object
return to_string(to_primitive(self, 'String'))
def to_object(self, space):
typ = Type(self)
if typ == 'Object':
return self
elif typ == 'Boolean': # Unsure ... todo check here
return space.Boolean.create((self, ), space)
elif typ == 'Number': # ?
return space.Number.create((self, ), space)
elif typ == 'String': # ?
return space.String.create((self, ), space)
elif typ == 'Null' or typ == 'Undefined':
raise MakeError('TypeError',
'undefined or null can\'t be converted to object')
else:
raise RuntimeError()
def to_int32(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
int32 = int(num) % 2**32
return int(int32 - 2**32 if int32 >= 2**31 else int32)
def to_int(self):
num = to_number(self)
if is_nan(num):
return 0
elif is_infinity(num):
return 10**20 if num > 0 else -10**20
return int(num)
def to_uint32(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
return int(num) % 2**32
def to_uint16(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
return int(num) % 2**16
def to_int16(self):
num = to_number(self)
if is_nan(num) or is_infinity(num):
return 0
int16 = int(num) % 2**16
return int(int16 - 2**16 if int16 >= 2**15 else int16)
def cok(self):
"""Check object coercible"""
if type(self) in (UNDEFINED_TYPE, NULL_TYPE):
raise MakeError('TypeError',
'undefined or null can\'t be converted to object')