Author: Stephan <[email protected]>
Branch:
Changeset: r157:394bffae727b
Date: 2011-11-10 00:51 +0100
http://bitbucket.org/pypy/lang-js/changeset/394bffae727b/
Log: cleaned up primitive types
diff --git a/js/baseop.py b/js/baseop.py
--- a/js/baseop.py
+++ b/js/baseop.py
@@ -18,8 +18,8 @@
return W_String(sleft + sright)
# hot path
if isinstance(nleft, W_IntNumber) and isinstance(nright, W_IntNumber):
- ileft = nleft.intval
- iright = nright.intval
+ ileft = nleft.ToInteger()
+ iright = nright.ToInteger()
try:
return W_IntNumber(ovfcheck(ileft + iright))
except OverflowError:
@@ -31,13 +31,13 @@
def increment(ctx, nleft, constval=1):
if isinstance(nleft, W_IntNumber):
- return W_IntNumber(nleft.intval + constval)
+ return W_IntNumber(nleft.ToInteger() + constval)
else:
return plus(ctx, nleft, W_IntNumber(constval))
def decrement(ctx, nleft, constval=1):
if isinstance(nleft, W_IntNumber):
- return W_IntNumber(nleft.intval - constval)
+ return W_IntNumber(nleft.ToInteger() - constval)
else:
return sub(ctx, nleft, W_IntNumber(constval))
@@ -89,11 +89,11 @@
def compare(ctx, x, y):
if isinstance(x, W_IntNumber) and isinstance(y, W_IntNumber):
- return x.intval > y.intval
+ return x.ToInteger() > y.ToInteger()
if isinstance(x, W_FloatNumber) and isinstance(y, W_FloatNumber):
- if isnan(x.floatval) or isnan(y.floatval):
+ if isnan(x.ToNumber()) or isnan(y.ToNumber()):
return -1
- return x.floatval > y.floatval
+ return x.ToNumber() > y.ToNumber()
s1 = x.ToPrimitive('Number')
s2 = y.ToPrimitive('Number')
if not (isinstance(s1, W_String) and isinstance(s2, W_String)):
@@ -109,11 +109,11 @@
def compare_e(ctx, x, y):
if isinstance(x, W_IntNumber) and isinstance(y, W_IntNumber):
- return x.intval >= y.intval
+ return x.ToInteger() >= y.ToInteger()
if isinstance(x, W_FloatNumber) and isinstance(y, W_FloatNumber):
- if isnan(x.floatval) or isnan(y.floatval):
+ if isnan(x.ToNumber()) or isnan(y.ToNumber()):
return -1
- return x.floatval >= y.floatval
+ return x.ToNumber() >= y.ToNumber()
s1 = x.ToPrimitive('Number')
s2 = y.ToPrimitive('Number')
if not (isinstance(s1, W_String) and isinstance(s2, W_String)):
@@ -133,11 +133,11 @@
trying to be fully to the spec
"""
if isinstance(x, W_IntNumber) and isinstance(y, W_IntNumber):
- return x.intval == y.intval
+ return x.ToInteger() == y.ToInteger()
if isinstance(x, W_FloatNumber) and isinstance(y, W_FloatNumber):
- if isnan(x.floatval) or isnan(y.floatval):
+ if isnan(x.ToNumber()) or isnan(y.ToNumber()):
return False
- return x.floatval == y.floatval
+ return x.ToNumber() == y.ToNumber()
type1 = x.type()
type2 = y.type()
if type1 == type2:
@@ -217,7 +217,8 @@
def commonnew(ctx, obj, args):
- if not isinstance(obj, W_PrimitiveObject):
+ from js.jsobj import W_BasicObject
+ if not (isinstance(obj, W_PrimitiveObject) or isinstance(obj,
W_BasicObject)):
raise ThrowException(W_String('it is not a constructor'))
try:
res = obj.Construct(args=args)
@@ -227,5 +228,5 @@
def uminus(obj, ctx):
if isinstance(obj, W_IntNumber):
- return W_IntNumber(-obj.intval)
+ return W_IntNumber(-obj.ToInteger())
return W_FloatNumber(-obj.ToNumber())
diff --git a/js/builtins.py b/js/builtins.py
--- a/js/builtins.py
+++ b/js/builtins.py
@@ -6,7 +6,7 @@
from js.jsobj import W_Object,\
w_Undefined, W_NewBuiltin, W_IntNumber, w_Null, create_object, W_Boolean,\
W_FloatNumber, W_String, W_Builtin, W_Array, w_Null, newbool,\
- isnull_or_undefined, W_PrimitiveObject, W_ListObject, W_BaseNumber,\
+ isnull_or_undefined, W_PrimitiveObject, W_ListObject, W_Number,\
DONT_DELETE, DONT_ENUM, READ_ONLY, INTERNAL
from js.execution import ThrowException, JsTypeError
@@ -59,7 +59,7 @@
if len(args) >= 1:
arg0 = args[0]
if isinstance(arg0, W_String):
- src = arg0.strval
+ src = arg0.ToString()
else:
return arg0
else:
@@ -508,8 +508,8 @@
t = 'W_FloatNumber'
elif isinstance(o, W_IntNumber):
t = 'W_IntNumber'
- elif isinstance(o, W_BaseNumber):
- t = 'W_Base_Number'
+ elif isinstance(o, W_Number):
+ t = 'W_Number'
return W_String(t)
def put_values(ctx, obj, dictvalues):
@@ -580,9 +580,9 @@
def absjs(args, this):
val = args[0]
if isinstance(val, W_IntNumber):
- if val.intval > 0:
+ if val.ToInteger() > 0:
return val # fast path
- return W_IntNumber(-val.intval)
+ return W_IntNumber(-val.ToInteger())
return W_FloatNumber(abs(args[0].ToNumber()))
def floorjs(args, this):
@@ -636,7 +636,7 @@
if not isinstance(w_string, W_String):
raise JsTypeError(W_String("Expected string"))
assert isinstance(w_string, W_String)
- strval = w_string.strval
+ strval = w_string.ToString()
lgt = len(strval)
i = 0
while i < lgt:
@@ -736,7 +736,7 @@
W_NativeObject.__init__(self, Class, Prototype, None )
def Call(self, args=[], this=None):
- if len(args) == 1 and isinstance(args[0], W_BaseNumber):
+ if len(args) == 1 and isinstance(args[0], W_Number):
array = create_array()
array.Put('length', args[0])
else:
diff --git a/js/jsobj.py b/js/jsobj.py
--- a/js/jsobj.py
+++ b/js/jsobj.py
@@ -20,7 +20,45 @@
class SeePage(NotImplementedError):
pass
-class W_Root(object):
+class W___Root(object):
+ pass
+
+class W__Root(W___Root):
+ _settled_ = True
+ _attrs_ = []
+ _type_ = ''
+
+ def __str__(self):
+ return self.ToString()
+
+ def type(self):
+ return self._type_
+
+ def ToBoolean(self):
+ return False
+
+ def ToPrimitive(self, hint=""):
+ return self
+
+ def ToString(self):
+ return ''
+
+ def ToObject(self):
+ raise JsTypeError
+
+ def ToNumber(self):
+ return 0.0
+
+ def ToInteger(self):
+ return int(self.ToNumber())
+
+ def ToInt32(self):
+ return r_int32(self.ToInteger())
+
+ def ToUInt32(self):
+ return r_uint32(self.ToInteger())
+
+class W_Root(W___Root):
_settled_ = True
_attrs_ = []
def __init__(self):
@@ -84,43 +122,28 @@
def Delete(self, name):
return False
-class W_Undefined(W_Root):
- def __str__(self):
- return "w_undefined"
+class W__Primitive(W__Root):
+ pass
+class W_Undefined(W__Primitive):
+ _type_ = 'undefined'
def ToInteger(self):
return 0
def ToNumber(self):
return NAN
- def ToBoolean(self):
- return False
+ def ToString(self):
+ return self._type_
- def ToString(self):
- return "undefined"
-
- def type(self):
- return 'undefined'
-
- def tolist(self):
- return []
-
-class W_Null(W_Root):
- def __str__(self):
- return "null"
+class W_Null(W__Primitive):
+ _type_ = 'null'
def ToBoolean(self):
return False
def ToString(self):
- return "null"
-
- def type(self):
- return 'null'
-
- def tolist(self):
- return []
+ return self._type_
w_Undefined = W_Undefined()
w_Null = W_Null()
@@ -279,12 +302,12 @@
t1 = self.Get(tryone)
if isinstance(t1, W_PrimitiveObject):
val = t1.Call(this=self)
- if isinstance(val, W_Primitive):
+ if isinstance(val, W__Primitive):
return val
t2 = self.Get(trytwo)
if isinstance(t2, W_PrimitiveObject):
val = t2.Call(this=self)
- if isinstance(val, W_Primitive):
+ if isinstance(val, W__Primitive):
return val
raise JsTypeError
@@ -350,11 +373,6 @@
def type(self):
return 'function'
-class W_Primitive(W_Root):
- """unifying parent for primitives"""
- def ToPrimitive(self, hint=""):
- return self
-
class W_NewBuiltin(W_PrimitiveObject):
length = -1
def __init__(self, Prototype=None, Class='function', Value=w_Undefined):
@@ -464,120 +482,111 @@
raise RangeError()
self.set_length(arrayindex+1)
-class W_Boolean(W_Primitive):
- _immutable_fields_ = ['boolval']
+class W_Boolean(W__Primitive):
+ _immutable_fields_ = ['_boolval_']
+ _type_ = 'boolean'
+
def __init__(self, boolval):
- self.boolval = bool(boolval)
+ W__Primitive.__init__(self)
+ self._boolval_ = bool(boolval)
+
+ def __repr__(self):
+ return 'W_Bool(%s)' % (str(self._boolval_), )
def ToObject(self):
+ # TODO
return create_object('Boolean', Value=self)
def ToString(self):
- if self.boolval == True:
+ if self._boolval_ == True:
return "true"
return "false"
def ToNumber(self):
- if self.boolval:
+ if self._boolval_ == True:
return 1.0
return 0.0
def ToBoolean(self):
- return self.boolval
+ return self._boolval_
- def type(self):
- return 'boolean'
+class W_String(W__Primitive):
+ _immutable_fields_ = ['_strval_']
+ _type_ = 'string'
+
+ def __init__(self, strval):
+ W__Primitive.__init__(self)
+ self._strval_ = strval
def __repr__(self):
- return "<W_Bool "+str(self.boolval)+" >"
-
-class W_String(W_Primitive):
- _immutable_fields_ = ['strval']
- def __init__(self, strval):
- W_Primitive.__init__(self)
- self.strval = strval
-
- def __repr__(self):
- return 'W_String(%s)' % (self.strval,)
+ return 'W_String(%s)' % (repr(self._strval_),)
def ToObject(self):
+ # TODO
o = create_object('String', Value=self)
- o.Put('length', W_IntNumber(len(self.strval)), flags = READ_ONLY |
DONT_DELETE | DONT_ENUM)
+ o.Put('length', W_IntNumber(len(self._strval_)), flags = READ_ONLY |
DONT_DELETE | DONT_ENUM)
return o
def ToString(self):
- return self.strval
+ return self._strval_
def ToBoolean(self):
- if len(self.strval) == 0:
+ if len(self._strval_) == 0:
return False
else:
return True
- def type(self):
- return 'string'
-
- def GetPropertyName(self):
- return self.ToString()
-
def ToNumber(self):
- if not self.strval:
+ if not self._strval_:
return 0.0
try:
- return float(self.strval)
+ return float(self._strval_)
except ValueError:
try:
- return float(int(self.strval, 16))
+ return float(int(self._strval_, 16))
except ValueError:
try:
- return float(int(self.strval, 8))
+ return float(int(self._strval_, 8))
except ValueError:
return NAN
-
-class W_BaseNumber(W_Primitive):
+class W_Number(W__Primitive):
""" Base class for numbers, both known to be floats
and those known to be integers
"""
+ _type_ = 'number'
+
def ToObject(self):
+ # TODO
return create_object('Number', Value=self)
- def Get(self, P):
- return w_Undefined
+ def ToBoolean(self):
+ num = self.ToNumber()
+ if isnan(num):
+ return False
+ return bool(num)
- def type(self):
- return 'number'
-
-class W_IntNumber(W_BaseNumber):
- _immutable_fields_ = ['intval']
+class W_IntNumber(W_Number):
+ _immutable_fields_ = ['_intval_']
""" Number known to be an integer
"""
def __init__(self, intval):
- W_BaseNumber.__init__(self)
- self.intval = intmask(intval)
+ W_Number.__init__(self)
+ self._intval_ = intmask(intval)
+
+ def __repr__(self):
+ return 'W_IntNumber(%s)' % (self._intval_,)
+
+ def ToInteger(self):
+ return self._intval_
+
+ def ToNumber(self):
+ # XXX
+ return float(self._intval_)
def ToString(self):
# XXX incomplete, this doesn't follow the 9.8.1 recommendation
- return str(self.intval)
-
- def ToBoolean(self):
- return bool(self.intval)
-
- def ToNumber(self):
- # XXX
- return float(self.intval)
-
- def ToInt32(self):
- return r_int32(self.intval)
-
- def ToUInt32(self):
- return r_uint32(self.intval)
-
- def GetPropertyName(self):
- return self.ToString()
-
- def __repr__(self):
- return 'W_IntNumber(%s)' % (self.intval,)
+ return str(self.ToInteger())
def r_int32(n):
return intmask(rffi.cast(rffi.INT, n))
@@ -585,26 +594,29 @@
def r_uint32(n):
return intmask(rffi.cast(rffi.UINT, n))
-class W_FloatNumber(W_BaseNumber):
- _immutable_fields_ = ['floatval']
+class W_FloatNumber(W_Number):
+ _immutable_fields_ = ['_floatval_']
""" Number known to be a float
"""
def __init__(self, floatval):
- W_BaseNumber.__init__(self)
- self.floatval = float(floatval)
+ W_Number.__init__(self)
+ self._floatval_ = float(floatval)
+
+ def __repr__(self):
+ return 'W_FloatNumber(%s)' % (self._floatval_,)
def ToString(self):
# XXX incomplete, this doesn't follow the 9.8.1 recommendation
- if isnan(self.floatval):
+ if isnan(self._floatval_):
return 'NaN'
- if isinf(self.floatval):
- if self.floatval > 0:
+ if isinf(self._floatval_):
+ if self._floatval_ > 0:
return 'Infinity'
else:
return '-Infinity'
res = ''
try:
- res = formatd(self.floatval, 'g', 10)
+ res = formatd(self._floatval_, 'g', 10)
except OverflowError:
raise
@@ -614,35 +626,17 @@
res = res[:cut] + res[-1]
return res
- def ToBoolean(self):
- if isnan(self.floatval):
- return False
- return bool(self.floatval)
-
def ToNumber(self):
- return self.floatval
+ return self._floatval_
def ToInteger(self):
- if isnan(self.floatval):
+ if isnan(self._floatval_):
return 0
- if self.floatval == 0 or isinf(self.floatval):
- return self.floatval
+ if self._floatval_ == 0 or isinf(self._floatval_):
+ return self._floatval_
- return intmask(int(self.floatval))
-
- def ToInt32(self):
- if isnan(self.floatval) or isinf(self.floatval):
- return 0
- return r_int32(int(self.floatval))
-
- def ToUInt32(self):
- if isnan(self.floatval) or isinf(self.floatval):
- return r_uint(0)
- return r_uint32(int(self.floatval))
-
- def __repr__(self):
- return 'W_FloatNumber(%s)' % (self.floatval,)
+ return intmask(int(self._floatval_))
class W_List(W_Root):
def __init__(self, list_w):
diff --git a/js/opcodes.py b/js/opcodes.py
--- a/js/opcodes.py
+++ b/js/opcodes.py
@@ -68,7 +68,7 @@
ctx.append(self.w_intvalue)
def __repr__(self):
- return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.intval,)
+ return 'LOAD_INTCONSTANT %s' % (self.w_intvalue.ToInteger(),)
class LOAD_BOOLCONSTANT(Opcode):
def __init__(self, value):
@@ -85,7 +85,7 @@
ctx.append(self.w_floatvalue)
def __repr__(self):
- return 'LOAD_FLOATCONSTANT %s' % (self.w_floatvalue.floatval,)
+ return 'LOAD_FLOATCONSTANT %s' % (self.w_floatvalue.ToNumber(),)
class LOAD_STRINGCONSTANT(Opcode):
_immutable_fields_ = ['w_stringvalue']
@@ -96,7 +96,7 @@
ctx.append(self.w_stringvalue)
def __repr__(self):
- return 'LOAD_STRINGCONSTANT "%s"' % (self.w_stringvalue.strval,)
+ return 'LOAD_STRINGCONSTANT "%s"' % (self.w_stringvalue.ToString(),)
class LOAD_UNDEFINED(Opcode):
def eval(self, ctx):
diff --git a/js/operations.py b/js/operations.py
--- a/js/operations.py
+++ b/js/operations.py
@@ -7,7 +7,7 @@
from js.jsobj import W_IntNumber, W_FloatNumber, W_Object,\
w_Undefined, W_NewBuiltin, W_String, create_object, W_List,\
W_PrimitiveObject, ActivationObject, W_Array, W_Boolean,\
- w_Null, W_BaseNumber, isnull_or_undefined
+ w_Null, isnull_or_undefined
from pypy.rlib.parsing.ebnfparse import Symbol, Nonterminal
from js.execution import JsTypeError, ThrowException
from js.jscode import JsCode
diff --git a/js/test/test_interp.py b/js/test/test_interp.py
--- a/js/test/test_interp.py
+++ b/js/test/test_interp.py
@@ -1,7 +1,7 @@
import py
from js import interpreter
from js.operations import IntNumber, FloatNumber, Position, Plus
-from js.jsobj import W_Object, W_Root, w_Null
+from js.jsobj import W_Object, W_Root, w_Null, W___Root
from js.execution import ThrowException
from js.jscode import JsCode, POP
from js.baseop import AbstractEC
@@ -44,7 +44,7 @@
except ThrowException, excpt:
code_val = excpt.exception
print code_val, value
- if isinstance(value, W_Root):
+ if isinstance(value, W___Root):
assert AbstractEC(jsint.global_context, code_val, value) == True
elif isinstance(value, bool):
assert code_val.ToBoolean() == value
diff --git a/js/test/test_jsobj.py b/js/test/test_jsobj.py
--- a/js/test/test_jsobj.py
+++ b/js/test/test_jsobj.py
@@ -1,5 +1,5 @@
-import pytest
-from js.jsobj import W_IntNumber, W_FloatNumber, W_Null
+import py
+from js.jsobj import W_IntNumber, W_FloatNumber, w_Null, w_Undefined, w_True,
w_False, NAN, W_String, W__Object as W_Object, W_BasicObject, W_BooleanObject
def test_intnumber():
n = W_IntNumber(0x80000000)
@@ -11,5 +11,116 @@
assert n.ToInt32() == -0x80000000
assert n.ToUInt32() == 0x80000000
-def test_type_null():
- assert W_Null().type() == 'null'
+class TestType():
+ def test_undefined(self):
+ assert w_Undefined.type() == 'undefined'
+
+ def test_null(self):
+ assert w_Null.type() == 'null'
+
+ def test_boolean(self):
+ assert w_True.type() == 'boolean'
+ assert w_False.type() == 'boolean'
+
+ def test_number(self):
+ assert W_IntNumber(0).type() == 'number'
+ assert W_FloatNumber(0.0).type() == 'number'
+ assert W_FloatNumber(NAN).type() == 'number'
+
+ def test_string(self):
+ assert W_String('').type() == 'string'
+
+ def test_object(self):
+ assert W_Object().type() == 'object'
+
+class TestToBoolean():
+ def test_undefined(self):
+ assert w_Undefined.ToBoolean() == False
+
+ def test_null(self):
+ assert w_Null.ToBoolean() == False
+
+ def test_boolean(self):
+ assert w_True.ToBoolean() == True
+ assert w_False.ToBoolean() == False
+
+ def test_number(self):
+ assert W_IntNumber(0).ToBoolean() == False
+ assert W_IntNumber(1).ToBoolean() == True
+ assert W_FloatNumber(0.0).ToBoolean() == False
+ assert W_FloatNumber(1.0).ToBoolean() == True
+ assert W_FloatNumber(NAN).ToBoolean() == False
+
+ def test_string(self):
+ assert W_String('').ToBoolean() == False
+ assert W_String('a').ToBoolean() == True
+
+ def test_object(self):
+ assert W_Object().ToBoolean() == True
+
+class TestToNumber():
+ def test_undefined(self):
+ assert w_Undefined.ToNumber() is NAN
+
+ def test_null(self):
+ assert w_Null.ToNumber() == 0
+
+ def test_boolean(self):
+ assert w_True.ToNumber() == 1
+ assert w_False.ToNumber() == 0
+
+ def test_number(self):
+ assert W_IntNumber(0).ToNumber() == 0
+ assert W_IntNumber(1).ToNumber() == 1
+ assert W_FloatNumber(0.0).ToNumber() == 0
+ assert W_FloatNumber(1.0).ToNumber() == 1.0
+ assert W_FloatNumber(NAN).ToNumber() is NAN
+
+ def test_string(self):
+ assert W_String('').ToNumber() == 0
+ assert W_String('x').ToNumber() is NAN
+ assert W_String('1').ToNumber() == 1
+
+ def test_object(self):
+ py.test.skip()
+ W_Object().ToNumber()
+
+class TestToString():
+ def test_undefined(self):
+ assert w_Undefined.ToString() == 'undefined'
+
+ def test_null(self):
+ assert w_Null.ToString() == 'null'
+
+ def test_boolean(self):
+ assert w_True.ToString() == 'true'
+ assert w_False.ToString() == 'false'
+
+ def test_number(self):
+ assert W_IntNumber(0).ToString() == '0'
+ assert W_IntNumber(1).ToString() == '1'
+ assert W_FloatNumber(0.0).ToString() == '0'
+ assert W_FloatNumber(1.0).ToString() == '1'
+ assert W_FloatNumber(NAN).ToString() == 'NaN'
+
+ def test_string(self):
+ assert W_String('').ToString() == ''
+ assert W_String('x').ToString() == 'x'
+ assert W_String('1').ToString() == '1'
+
+ def test_object(self):
+ py.test.skip()
+ W_Object().ToString()
+
+class TestW_BasicObject():
+ def test_Prototype(self):
+ assert W_BasicObject().Prototype() is None
+
+ def test_Class(self):
+ assert W_BasicObject().Class() == 'Object'
+
+class Test_WBooleanObject():
+ def test_toPrimitive(self):
+ py.test.skip()
+ b = W_BooleanObject(w_True)
+ assert b.ToPrimitive() == w_True
diff --git a/js/utils.py b/js/utils.py
--- a/js/utils.py
+++ b/js/utils.py
@@ -26,8 +26,8 @@
return self.stack[i]
def append(self, element):
- from js.jsobj import W_Root
- assert isinstance(element, W_Root)
+ from js.jsobj import W___Root
+ assert isinstance(element, W___Root)
i = self.stack_pointer
assert i >= 0
self.stack[i] = element
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit