Fixed compare bugs. Report results from js2 test cases. Rewrote generic

equal to match ECMA 1.5


git-svn-id: svn://10.0.0.236/trunk@82354 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
rogerl%netscape.com
2000-11-06 22:57:10 +00:00
parent b942b55420
commit eee3dbd0a5
12 changed files with 140 additions and 66 deletions

View File

@@ -1442,12 +1442,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
TypedRegister r1 = genExpr(b->op1);
TypedRegister r2 = genExpr(b->op2);
ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r2, r1);
ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); // will generate equal/identical code
if (trueBranch || falseBranch) {
if (trueBranch == NULL)
branchFalse(falseBranch, ret);
branchTrue(falseBranch, ret);
else {
branchTrue(trueBranch, ret);
branchFalse(trueBranch, ret);
if (falseBranch)
branch(falseBranch);
}
@@ -2104,11 +2104,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
case StmtNode::IfElse:
{
Label *falseLabel = getLabel();
Label *trueLabel = getLabel();
Label *beyondLabel = getLabel();
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
TypedRegister c = genExpr(i->expr, false, NULL, falseLabel);
TypedRegister c = genExpr(i->expr, false, trueLabel, falseLabel);
if (!generatedBoolean(i->expr))
branchFalse(falseLabel, test(c));
setLabel(trueLabel);
genStmt(i->stmt);
branch(beyondLabel);
setLabel(falseLabel);

View File

@@ -372,7 +372,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2)
lv = lv.toNumber();
rv = rv.toNumber();
if (lv.isNaN() || rv.isNaN())
return JSValue();
return kFalseValue;
else
return JSValue(lv.f64 < rv.f64);
}
@@ -388,26 +388,48 @@ static JSValue lessOrEqual_Default(const JSValue& r1, const JSValue& r2)
lv = lv.toNumber();
rv = rv.toNumber();
if (lv.isNaN() || rv.isNaN())
return JSValue();
return kFalseValue;
else
return JSValue(lv.f64 <= rv.f64);
}
}
static JSValue equal_Default(const JSValue& r1, const JSValue& r2)
{
JSValue lv = r1.toPrimitive(JSValue::Number);
JSValue rv = r2.toPrimitive(JSValue::Number);
if (lv.isString() && rv.isString()) {
return JSValue(bool(lv.string->compare(*rv.string) == 0));
if (r1.isSameType(r2)) {
if (r1.isUndefined()) return kTrueValue;
if (r1.isNull()) return kTrueValue;
if (r1.isNumber()) {
JSValue lv = r1.toNumber(); // make sure we have f64's
JSValue rv = r2.toNumber();
if (lv.isNaN() || rv.isNaN())
return kFalseValue;
else
return JSValue(lv.f64 == rv.f64); // does the right thing for +/- 0
}
if (r1.isString())
return JSValue(bool(r1.string->compare(*r2.string) == 0));
if (r1.isBoolean())
return JSValue(bool(r1.boolean == r2.boolean));
if (r1.isObject())
return JSValue(bool(r1.object == r2.object));
}
else {
lv = lv.toNumber();
rv = rv.toNumber();
if (lv.isNaN() || rv.isNaN())
return JSValue();
else
return JSValue(lv.f64 == rv.f64);
else { // different types
if (r1.isNull() && r2.isUndefined()) return kTrueValue;
if (r2.isNull() && r1.isUndefined()) return kTrueValue;
if (r1.isNumber() && r2.isString())
return equal_Default(r1, r2.toNumber());
if (r2.isNumber() && r1.isString())
return equal_Default(r1.toNumber(), r2);
if (r1.isBoolean())
return equal_Default(r1.toNumber(), r2);
if (r2.isBoolean())
return equal_Default(r1, r2.toNumber());
if ((r1.isString() || r1.isNumber()) && r2.isObject())
return equal_Default(r1, r2.toPrimitive());
if ((r2.isString() || r2.isNumber()) && r1.isObject())
return equal_Default(r1.toPrimitive(), r2);
}
return kFalseValue;
}
static JSValue identical_Default(const JSValue& r1, const JSValue& r2)
{

View File

@@ -347,7 +347,8 @@ static void testCompile()
icg.genStmt(s);
s = s->next;
}
cx.interpret(icg.complete(&Void_Type), JSValues());
JSValue result = cx.interpret(icg.complete(&Void_Type), JSValues());
stdOut << "result = " << result << "\n";
}
}

View File

@@ -267,7 +267,7 @@ static JSValue array_constructor(Context *, const JSValues& argv)
return JSValue(result);
}
else
return JSValue(new JSArray(JSValue::valueToInteger(argv[1]).i32));
return JSValue(new JSArray(JSValue::valueToInt32(argv[1]).i32));
else
return JSValue(new JSArray());
}
@@ -358,15 +358,6 @@ JSType Date_Type = JSType(widenCString("Date"), NULL, new JSNativeFunction(date_
// the canonical undefined value, etc.
const JSValue kUndefinedValue;
const JSValue kNaNValue = JSValue(nan);
const JSValue kTrueValue = JSValue(true);
const JSValue kFalseValue = JSValue(false);
const JSValue kNullValue = JSValue((JSObject*)NULL);
const JSValue kNegativeZero = JSValue(-0.0);
const JSValue kPositiveZero = JSValue(0.0);
const JSValue kNegativeInfinity = JSValue(negativeInfinity);
const JSValue kPositiveInfinity = JSValue(positiveInfinity);
const JSType *JSValue::getType() const
@@ -712,10 +703,10 @@ JSValue JSValue::valueToInteger(const JSValue& value)
{
JSValue result = valueToNumber(value);
ASSERT(result.tag == f64_tag);
result.tag = i32_tag;
result.tag = integer_tag;
bool neg = (result.f64 < 0);
result.i32 = (int32)floor((neg) ? -result.f64 : result.f64);
result.i32 = (neg) ? -result.i32 : result.i32;
result.f64 = floor((neg) ? -result.f64 : result.f64);
result.f64 = (neg) ? -result.f64 : result.f64;
return result;
}

View File

@@ -105,7 +105,7 @@ namespace JSTypes {
f32_tag, f64_tag,
integer_tag,
object_tag, array_tag, function_tag, string_tag, boolean_tag, type_tag,
undefined_tag,
undefined_tag, null_tag,
uninitialized_tag
} Tag;
Tag tag;
@@ -145,7 +145,7 @@ namespace JSTypes {
bool isInitialized() const { return (tag != uninitialized_tag); }
bool isUndefined() const { return (tag == undefined_tag); }
bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); }
bool isNull() const { return (tag == null_tag); }
bool isNaN() const;
bool isNegativeInfinity() const;
bool isPositiveInfinity() const;
@@ -173,6 +173,16 @@ namespace JSTypes {
const JSType *getType() const; // map from tag type to JS2 type
bool isSameType(const JSValue &other) const
{
const JSType *thisType = getType();
const JSType *otherType = other.getType();
if (thisType == otherType)
return true;
if (isNumber() && other.isNumber())
return true;
return false;
}
int operator==(const JSValue& value) const;
};

View File

@@ -22,9 +22,11 @@
#include <cstring>
#include <cfloat>
#include "numerics.h"
#include "jstypes.h"
namespace JS = JavaScript;
using namespace JavaScript;
using namespace JSTypes;
//
@@ -225,6 +227,15 @@ InitNumerics::InitNumerics()
word1(nan) = 0xFFFFFFFF;
}
const JSValue JSTypes::kUndefinedValue;
const JSValue JSTypes::kNaNValue = JSValue(nan);
const JSValue JSTypes::kTrueValue = JSValue(true);
const JSValue JSTypes::kFalseValue = JSValue(false);
const JSValue JSTypes::kNullValue = JSValue(JSValue::Tag::null_tag);
const JSValue JSTypes::kNegativeZero = JSValue(-0.0);
const JSValue JSTypes::kPositiveZero = JSValue(0.0);
const JSValue JSTypes::kNegativeInfinity = JSValue(negativeInfinity);
const JSValue JSTypes::kPositiveInfinity = JSValue(positiveInfinity);
//
// Portable double-precision floating point to string and back conversions

View File

@@ -1442,12 +1442,12 @@ TypedRegister ICodeGenerator::genExpr(ExprNode *p,
BinaryExprNode *b = static_cast<BinaryExprNode *>(p);
TypedRegister r1 = genExpr(b->op1);
TypedRegister r2 = genExpr(b->op2);
ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r2, r1);
ret = binaryOp(mapExprNodeToICodeOp(p->getKind()), r1, r2); // will generate equal/identical code
if (trueBranch || falseBranch) {
if (trueBranch == NULL)
branchFalse(falseBranch, ret);
branchTrue(falseBranch, ret);
else {
branchTrue(trueBranch, ret);
branchFalse(trueBranch, ret);
if (falseBranch)
branch(falseBranch);
}
@@ -2104,11 +2104,13 @@ TypedRegister ICodeGenerator::genStmt(StmtNode *p, LabelSet *currentLabelSet)
case StmtNode::IfElse:
{
Label *falseLabel = getLabel();
Label *trueLabel = getLabel();
Label *beyondLabel = getLabel();
BinaryStmtNode *i = static_cast<BinaryStmtNode *>(p);
TypedRegister c = genExpr(i->expr, false, NULL, falseLabel);
TypedRegister c = genExpr(i->expr, false, trueLabel, falseLabel);
if (!generatedBoolean(i->expr))
branchFalse(falseLabel, test(c));
setLabel(trueLabel);
genStmt(i->stmt);
branch(beyondLabel);
setLabel(falseLabel);

View File

@@ -372,7 +372,7 @@ static JSValue less_Default(const JSValue& r1, const JSValue& r2)
lv = lv.toNumber();
rv = rv.toNumber();
if (lv.isNaN() || rv.isNaN())
return JSValue();
return kFalseValue;
else
return JSValue(lv.f64 < rv.f64);
}
@@ -388,26 +388,48 @@ static JSValue lessOrEqual_Default(const JSValue& r1, const JSValue& r2)
lv = lv.toNumber();
rv = rv.toNumber();
if (lv.isNaN() || rv.isNaN())
return JSValue();
return kFalseValue;
else
return JSValue(lv.f64 <= rv.f64);
}
}
static JSValue equal_Default(const JSValue& r1, const JSValue& r2)
{
JSValue lv = r1.toPrimitive(JSValue::Number);
JSValue rv = r2.toPrimitive(JSValue::Number);
if (lv.isString() && rv.isString()) {
return JSValue(bool(lv.string->compare(*rv.string) == 0));
if (r1.isSameType(r2)) {
if (r1.isUndefined()) return kTrueValue;
if (r1.isNull()) return kTrueValue;
if (r1.isNumber()) {
JSValue lv = r1.toNumber(); // make sure we have f64's
JSValue rv = r2.toNumber();
if (lv.isNaN() || rv.isNaN())
return kFalseValue;
else
return JSValue(lv.f64 == rv.f64); // does the right thing for +/- 0
}
if (r1.isString())
return JSValue(bool(r1.string->compare(*r2.string) == 0));
if (r1.isBoolean())
return JSValue(bool(r1.boolean == r2.boolean));
if (r1.isObject())
return JSValue(bool(r1.object == r2.object));
}
else {
lv = lv.toNumber();
rv = rv.toNumber();
if (lv.isNaN() || rv.isNaN())
return JSValue();
else
return JSValue(lv.f64 == rv.f64);
else { // different types
if (r1.isNull() && r2.isUndefined()) return kTrueValue;
if (r2.isNull() && r1.isUndefined()) return kTrueValue;
if (r1.isNumber() && r2.isString())
return equal_Default(r1, r2.toNumber());
if (r2.isNumber() && r1.isString())
return equal_Default(r1.toNumber(), r2);
if (r1.isBoolean())
return equal_Default(r1.toNumber(), r2);
if (r2.isBoolean())
return equal_Default(r1, r2.toNumber());
if ((r1.isString() || r1.isNumber()) && r2.isObject())
return equal_Default(r1, r2.toPrimitive());
if ((r2.isString() || r2.isNumber()) && r1.isObject())
return equal_Default(r1.toPrimitive(), r2);
}
return kFalseValue;
}
static JSValue identical_Default(const JSValue& r1, const JSValue& r2)
{

View File

@@ -267,7 +267,7 @@ static JSValue array_constructor(Context *, const JSValues& argv)
return JSValue(result);
}
else
return JSValue(new JSArray(JSValue::valueToInteger(argv[1]).i32));
return JSValue(new JSArray(JSValue::valueToInt32(argv[1]).i32));
else
return JSValue(new JSArray());
}
@@ -358,15 +358,6 @@ JSType Date_Type = JSType(widenCString("Date"), NULL, new JSNativeFunction(date_
// the canonical undefined value, etc.
const JSValue kUndefinedValue;
const JSValue kNaNValue = JSValue(nan);
const JSValue kTrueValue = JSValue(true);
const JSValue kFalseValue = JSValue(false);
const JSValue kNullValue = JSValue((JSObject*)NULL);
const JSValue kNegativeZero = JSValue(-0.0);
const JSValue kPositiveZero = JSValue(0.0);
const JSValue kNegativeInfinity = JSValue(negativeInfinity);
const JSValue kPositiveInfinity = JSValue(positiveInfinity);
const JSType *JSValue::getType() const
@@ -712,10 +703,10 @@ JSValue JSValue::valueToInteger(const JSValue& value)
{
JSValue result = valueToNumber(value);
ASSERT(result.tag == f64_tag);
result.tag = i32_tag;
result.tag = integer_tag;
bool neg = (result.f64 < 0);
result.i32 = (int32)floor((neg) ? -result.f64 : result.f64);
result.i32 = (neg) ? -result.i32 : result.i32;
result.f64 = floor((neg) ? -result.f64 : result.f64);
result.f64 = (neg) ? -result.f64 : result.f64;
return result;
}

View File

@@ -105,7 +105,7 @@ namespace JSTypes {
f32_tag, f64_tag,
integer_tag,
object_tag, array_tag, function_tag, string_tag, boolean_tag, type_tag,
undefined_tag,
undefined_tag, null_tag,
uninitialized_tag
} Tag;
Tag tag;
@@ -145,7 +145,7 @@ namespace JSTypes {
bool isInitialized() const { return (tag != uninitialized_tag); }
bool isUndefined() const { return (tag == undefined_tag); }
bool isNull() const { return ((tag == object_tag) && (this->object == NULL)); }
bool isNull() const { return (tag == null_tag); }
bool isNaN() const;
bool isNegativeInfinity() const;
bool isPositiveInfinity() const;
@@ -173,6 +173,16 @@ namespace JSTypes {
const JSType *getType() const; // map from tag type to JS2 type
bool isSameType(const JSValue &other) const
{
const JSType *thisType = getType();
const JSType *otherType = other.getType();
if (thisType == otherType)
return true;
if (isNumber() && other.isNumber())
return true;
return false;
}
int operator==(const JSValue& value) const;
};

View File

@@ -22,9 +22,11 @@
#include <cstring>
#include <cfloat>
#include "numerics.h"
#include "jstypes.h"
namespace JS = JavaScript;
using namespace JavaScript;
using namespace JSTypes;
//
@@ -225,6 +227,15 @@ InitNumerics::InitNumerics()
word1(nan) = 0xFFFFFFFF;
}
const JSValue JSTypes::kUndefinedValue;
const JSValue JSTypes::kNaNValue = JSValue(nan);
const JSValue JSTypes::kTrueValue = JSValue(true);
const JSValue JSTypes::kFalseValue = JSValue(false);
const JSValue JSTypes::kNullValue = JSValue(JSValue::Tag::null_tag);
const JSValue JSTypes::kNegativeZero = JSValue(-0.0);
const JSValue JSTypes::kPositiveZero = JSValue(0.0);
const JSValue JSTypes::kNegativeInfinity = JSValue(negativeInfinity);
const JSValue JSTypes::kPositiveInfinity = JSValue(positiveInfinity);
//
// Portable double-precision floating point to string and back conversions

View File

@@ -347,7 +347,8 @@ static void testCompile()
icg.genStmt(s);
s = s->next;
}
cx.interpret(icg.complete(&Void_Type), JSValues());
JSValue result = cx.interpret(icg.complete(&Void_Type), JSValues());
stdOut << "result = " << result << "\n";
}
}