2019-04-11 00:02:14 +00:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
# Type Conversions. to_type. All must return PyJs subclass instance
|
2019-05-12 04:23:46 +00:00
|
|
|
from .simplex import *
|
2019-04-11 00:02:14 +00:00
|
|
|
|
|
|
|
|
|
|
|
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':
|
2019-05-12 04:23:46 +00:00
|
|
|
return js_dtoa(self)
|
2019-04-11 00:02:14 +00:00
|
|
|
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')
|