[jsbuilt-ins] implementing Boolean object

* renames _type to jstype
* mocks up type conversions
* adds jslass internal property
This commit is contained in:
sulyi 2017-02-01 21:29:15 +01:00
parent 9ead39caee
commit 87331205ba

View File

@ -13,7 +13,7 @@ def _to_js(o, name=None):
elif o is None: elif o is None:
return undefined return undefined
elif isinstance(o, _native_bool): elif isinstance(o, _native_bool):
return JSBoolean.construct(o) return JSBooleanPrototype(o)
elif isinstance(o, _native_string): elif isinstance(o, _native_string):
return JSStringPrototype(o) return JSStringPrototype(o)
elif isinstance(o, _native_number): elif isinstance(o, _native_number):
@ -36,37 +36,60 @@ def js(func):
return wrapper return wrapper
def _type(o): def jstype(o):
if o is undefined: if o is undefined:
return _undefined_type return _undefined_type
elif o is None or o is null: elif o is None or o is null:
return _null_type return _null_type
elif isinstance(o, _native_bool) or isinstance(o, JSBooleanPrototype): elif isinstance(o, _native_bool) or o is true or o is false:
return _boolean_type return _boolean_type
elif isinstance(o, _native_string) or isinstance(o, JSStringPrototype): elif isinstance(o, _native_string):
return _string_type return _string_type
elif isinstance(o, _native_number) or isinstance(o, JSNumberPrototype): elif isinstance(o, _native_number):
return _number_type return _number_type
elif isinstance(o, _native_object) or isinstance(o, JSObjectPrototype): elif isinstance(o, _native_object):
return _object_type return _object_type
return None return None
def to_object(o): def to_primitive(o, hint=None):
# TODO to_primitive
return o
def to_boolean(o):
if o is undefined or o is null: if o is undefined or o is null:
raise Exception('TypeError: Cannot convert undefined or null to object') return false
elif isinstance(o, JSBooleanPrototype): elif isinstance(o, JSBooleanPrototype):
return JSBooleanPrototype(o) return o.value
elif isinstance(o, JSNumberPrototype): elif isinstance(o, JSNumberPrototype):
return JSNumberPrototype(o) return true if o.value and not isnan(o.value) else false
elif isinstance(o, JSStringPrototype): elif isinstance(o, JSStringPrototype):
return JSStringPrototype(o) return true if o.value else false
elif isinstance(o, JSObjectPrototype): elif isinstance(o, JSObjectPrototype):
return o return true
else:
raise Exception('Failed to convert type %s to boolean (not specified)' % type(o))
def to_primitive(o, hint): def to_number(o):
return o # TODO to_number
pass
def to_integer(o):
# TODO to_integer
pass
def to_int32(o):
# TODO to_int32
pass
def to_int16(o):
# TODO to_int16
pass
def to_string(o): def to_string(o):
@ -122,6 +145,19 @@ def to_string(o):
return to_string(prim_value) return to_string(prim_value)
def to_object(o):
if o is undefined or o is null:
raise Exception('TypeError: Cannot convert undefined or null to object')
elif isinstance(o, JSBooleanPrototype):
return JSBooleanPrototype(o)
elif isinstance(o, JSNumberPrototype):
return JSNumberPrototype(o)
elif isinstance(o, JSStringPrototype):
return JSStringPrototype(o)
elif isinstance(o, JSObjectPrototype):
return o
class JSBase(object): class JSBase(object):
def __init__(self, name): def __init__(self, name):
@ -136,16 +172,13 @@ class JSProtoBase(JSBase):
def __init__(self): def __init__(self):
super(JSProtoBase, self).__init__('') super(JSProtoBase, self).__init__('')
cls = self.__class__ cls = self.__class__
while cls is not JSProtoBase: while cls.__base__ is not JSProtoBase:
cls = cls.__base__ cls = cls.__base__
props = cls.own.copy() props = cls.own.copy()
props.update(self.props) props.update(self.props)
self.props = props self.props = props
self.value = {} self.value = {}
def __str__(self):
return ''
def get_prop(self, prop): def get_prop(self, prop):
result = self.value.get(prop) if hasattr(self.value, 'get') else None result = self.value.get(prop) if hasattr(self.value, 'get') else None
if result is None: if result is None:
@ -170,6 +203,8 @@ class JSProtoBase(JSBase):
# interpreter should raise JSTypeError # interpreter should raise JSTypeError
raise Exception('TypeError: %s is not a function' % prop) raise Exception('TypeError: %s is not a function' % prop)
jsclass = ''
class JSObjectPrototype(JSProtoBase): class JSObjectPrototype(JSProtoBase):
@ -199,6 +234,7 @@ class JSObjectPrototype(JSProtoBase):
def _is_property_enumerable(self, v): def _is_property_enumerable(self, v):
return 'object is property enumerable' return 'object is property enumerable'
jsclass = 'Object'
own = { own = {
'constructor': _constructor, 'constructor': _constructor,
'toString': _to_string, 'toString': _to_string,
@ -272,7 +308,7 @@ class JSObject(JSBase):
def _keys(self, o): def _keys(self, o):
return 'object keys' return 'object keys'
name = 'Object' name = JSObjectPrototype.jsclass
own = { own = {
'length': 1, 'length': 1,
'prototype': JSObjectPrototype(), 'prototype': JSObjectPrototype(),
@ -349,6 +385,7 @@ class JSFunctionPrototype(JSObjectPrototype):
def _bind(self, this_arg, *args): def _bind(self, this_arg, *args):
return 'function bind' return 'function bind'
jsclass = 'Function'
own = { own = {
'length': 0, 'length': 0,
'constructor': _constructor, 'constructor': _constructor,
@ -375,7 +412,7 @@ class JSFunction(JSObject):
formal_args = formal_args[:-1] formal_args = formal_args[:-1]
return JSFunctionPrototype('anonymous', body, formal_args) return JSFunctionPrototype('anonymous', body, formal_args)
name = 'Function' name = JSFunctionPrototype.jsclass
own = { own = {
'length': 1, 'length': 1,
'prototype': JSFunctionPrototype(None, None, None) 'prototype': JSFunctionPrototype(None, None, None)
@ -468,6 +505,7 @@ class JSArrayPrototype(JSObjectPrototype):
def _reduce_right(self, callback, init=None): def _reduce_right(self, callback, init=None):
return 'array reduce right' return 'array reduce right'
jsclass = 'Array'
own = { own = {
'length': _length, 'length': _length,
'constructor': _constructor, 'constructor': _constructor,
@ -516,7 +554,7 @@ class JSArray(JSObject):
def _is_array(self, arg): def _is_array(self, arg):
return 'array is array' return 'array is array'
name = 'Array' name = JSArrayPrototype.jsclass
own = { own = {
'length': 1, 'length': 1,
'prototype': JSArrayPrototype(), 'prototype': JSArrayPrototype(),
@ -597,6 +635,7 @@ class JSStringPrototype(JSObjectPrototype):
def _trim(self): def _trim(self):
return 'string trim' return 'string trim'
jsclass = 'String'
own = { own = {
'length': _length, 'length': _length,
'constructor': _constructor, 'constructor': _constructor,
@ -635,7 +674,7 @@ class JSString(JSObject):
def _from_char_code(self, *args): def _from_char_code(self, *args):
return 'String from char code' return 'String from char code'
name = 'String' name = JSStringPrototype.jsclass
own = { own = {
'length': 1, 'length': 1,
'prototype': JSStringPrototype(), 'prototype': JSStringPrototype(),
@ -644,13 +683,52 @@ class JSString(JSObject):
class JSBooleanPrototype(JSObjectPrototype): class JSBooleanPrototype(JSObjectPrototype):
pass
def __init__(self, value=None):
if value is None:
# prototype
value = False
super(JSBooleanPrototype, self).__init__(value)
@staticmethod
def _constructor(value=None):
return JSBoolean.construct(value)
def _to_string(self):
# TODO find way to test it in other interpreters
if jstype(self) is _boolean_type:
b = self
elif jstype(self) is _object_type and self.jsclass == 'Boolean':
b = self.value
else:
raise Exception('TypeError')
return 'true' if b is true else 'false'
def _value_of(self):
return 'boolean value of'
jsclass = 'Boolean'
own = {
'constructor': _constructor,
'toString': _to_string,
'valueOf': _value_of
}
class JSBoolean(JSObject): class JSBoolean(JSObject):
@staticmethod
def call(value=None):
return to_boolean(value)
@staticmethod @staticmethod
def construct(value=None): def construct(value=None):
pass return JSBooleanPrototype(to_boolean(_to_js(value)))
name = JSBooleanPrototype.jsclass
own = {
'prototype': JSBooleanPrototype()
}
class JSNumberPrototype(JSObjectPrototype): class JSNumberPrototype(JSObjectPrototype):
@ -661,10 +739,10 @@ class JSNumber(JSObject):
pass pass
undefined = object() undefined = JSBase('undefined')
null = object() null = JSBase('null')
true = JSBoolean.construct(True) true = JSBooleanPrototype(True)
false = JSBoolean.construct(False) false = JSBooleanPrototype(False)
_native_bool = bool _native_bool = bool
_native_string = compat_str _native_string = compat_str