Move Value into it's own header/cpp file
Change-Id: I2872d824a2016a653e64f0332f6416f416eef0e7 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
This commit is contained in:
parent
65724ce3e7
commit
1162d4dde6
|
@ -112,124 +112,6 @@ QString numberToString(double num, int radix = 10)
|
|||
return str;
|
||||
}
|
||||
|
||||
|
||||
Value Value::fromString(ExecutionContext *ctx, const QString &s)
|
||||
{
|
||||
return fromString(ctx->engine->newString(s));
|
||||
}
|
||||
|
||||
int Value::toInt32(double number)
|
||||
{
|
||||
const double D32 = 4294967296.0;
|
||||
const double D31 = D32 / 2.0;
|
||||
|
||||
if ((number >= -D31 && number < D31))
|
||||
return static_cast<int>(number);
|
||||
|
||||
|
||||
if (!std::isfinite(number))
|
||||
return 0;
|
||||
|
||||
double d = ::floor(::fabs(number));
|
||||
if (std::signbit(number))
|
||||
d = -d;
|
||||
|
||||
number = ::fmod(d , D32);
|
||||
|
||||
if (number < -D31)
|
||||
number += D32;
|
||||
else if (number >= D31)
|
||||
number -= D32;
|
||||
|
||||
return int(number);
|
||||
}
|
||||
|
||||
unsigned int Value::toUInt32(double number)
|
||||
{
|
||||
const double D32 = 4294967296.0;
|
||||
if ((number >= 0 && number < D32))
|
||||
return static_cast<uint>(number);
|
||||
|
||||
if (!std::isfinite(number))
|
||||
return +0;
|
||||
|
||||
double d = ::floor(::fabs(number));
|
||||
if (std::signbit(number))
|
||||
d = -d;
|
||||
|
||||
number = ::fmod(d , D32);
|
||||
|
||||
if (number < 0)
|
||||
number += D32;
|
||||
|
||||
return unsigned(number);
|
||||
}
|
||||
|
||||
double Value::toInteger(double number)
|
||||
{
|
||||
if (std::isnan(number))
|
||||
return +0;
|
||||
else if (! number || std::isinf(number))
|
||||
return number;
|
||||
const double v = floor(fabs(number));
|
||||
return std::signbit(number) ? -v : v;
|
||||
}
|
||||
|
||||
Object *Value::asObject() const
|
||||
{
|
||||
return isObject() ? objectValue() : 0;
|
||||
}
|
||||
|
||||
FunctionObject *Value::asFunctionObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asFunctionObject() : 0;
|
||||
}
|
||||
|
||||
BooleanObject *Value::asBooleanObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asBooleanObject() : 0;
|
||||
}
|
||||
|
||||
NumberObject *Value::asNumberObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asNumberObject() : 0;
|
||||
}
|
||||
|
||||
StringObject *Value::asStringObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asStringObject() : 0;
|
||||
}
|
||||
|
||||
DateObject *Value::asDateObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asDateObject() : 0;
|
||||
}
|
||||
|
||||
RegExpObject *Value::asRegExpObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asRegExpObject() : 0;
|
||||
}
|
||||
|
||||
ArrayObject *Value::asArrayObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asArrayObject() : 0;
|
||||
}
|
||||
|
||||
ErrorObject *Value::asErrorObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asErrorObject() : 0;
|
||||
}
|
||||
|
||||
ActivationObject *Value::asArgumentsObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asActivationObject() : 0;
|
||||
}
|
||||
|
||||
Value Value::property(ExecutionContext *ctx, String *name) const
|
||||
{
|
||||
return isObject() ? objectValue()->__get__(ctx, name) : undefinedValue();
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
Value __qmljs_init_closure(IR::Function *clos, ExecutionContext *ctx)
|
||||
|
|
311
qmljs_runtime.h
311
qmljs_runtime.h
|
@ -41,12 +41,12 @@
|
|||
#ifndef QMLJS_RUNTIME_H
|
||||
#define QMLJS_RUNTIME_H
|
||||
|
||||
#include <qmljs_value.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/qnumeric.h>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <cassert>
|
||||
|
||||
|
@ -87,185 +87,6 @@ struct ErrorObject;
|
|||
struct ActivationObject;
|
||||
struct ExecutionEngine;
|
||||
|
||||
typedef uint Bool;
|
||||
|
||||
struct Value
|
||||
{
|
||||
union {
|
||||
quint64 val;
|
||||
double dbl;
|
||||
struct {
|
||||
#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
|
||||
uint tag;
|
||||
#endif
|
||||
union {
|
||||
uint uint_32;
|
||||
int int_32;
|
||||
#if CPU(X86_64)
|
||||
#else
|
||||
Object *o;
|
||||
String *s;
|
||||
#endif
|
||||
};
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
uint tag;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
enum Masks {
|
||||
NotDouble_Mask = 0xfff80000,
|
||||
Type_Mask = 0xffff0000,
|
||||
Immediate_Mask = NotDouble_Mask | 0x00040000,
|
||||
Tag_Shift = 32
|
||||
};
|
||||
enum ValueType {
|
||||
Undefined_Type = Immediate_Mask | 0x00000,
|
||||
Null_Type = Immediate_Mask | 0x10000,
|
||||
Boolean_Type = Immediate_Mask | 0x20000,
|
||||
Integer_Type = Immediate_Mask | 0x30000,
|
||||
Object_Type = NotDouble_Mask | 0x00000,
|
||||
String_Type = NotDouble_Mask | 0x10000
|
||||
};
|
||||
|
||||
enum ImmediateFlags {
|
||||
ConvertibleToInt = Immediate_Mask | (0x1 << 15)
|
||||
};
|
||||
|
||||
enum ValueTypeInternal {
|
||||
_Undefined_Type = Undefined_Type,
|
||||
_Null_Type = Null_Type | ConvertibleToInt,
|
||||
_Boolean_Type = Boolean_Type | ConvertibleToInt,
|
||||
_Integer_Type = Integer_Type | ConvertibleToInt,
|
||||
_Object_Type = Object_Type,
|
||||
_String_Type = String_Type
|
||||
|
||||
};
|
||||
|
||||
inline ValueType type() const {
|
||||
return (ValueType)(tag & Type_Mask);
|
||||
}
|
||||
|
||||
inline bool isUndefined() const { return tag == _Undefined_Type; }
|
||||
inline bool isNull() const { return tag == _Null_Type; }
|
||||
inline bool isBoolean() const { return tag == _Boolean_Type; }
|
||||
inline bool isInteger() const { return tag == _Integer_Type; }
|
||||
inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
|
||||
inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
|
||||
#if CPU(X86_64)
|
||||
inline bool isString() const { return (tag & Type_Mask) == String_Type; }
|
||||
inline bool isObject() const { return (tag & Type_Mask) == Object_Type; }
|
||||
#else
|
||||
inline bool isString() const { return tag == String_Type; }
|
||||
inline bool isObject() const { return tag == Object_Type; }
|
||||
#endif
|
||||
inline bool isConvertibleToInt() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
|
||||
|
||||
Bool booleanValue() const {
|
||||
return int_32;
|
||||
}
|
||||
double doubleValue() const {
|
||||
return dbl;
|
||||
}
|
||||
void setDouble(double d) {
|
||||
dbl = d;
|
||||
}
|
||||
double asDouble() const {
|
||||
if (tag == _Integer_Type)
|
||||
return int_32;
|
||||
return dbl;
|
||||
}
|
||||
int integerValue() const {
|
||||
return int_32;
|
||||
}
|
||||
|
||||
#if CPU(X86_64)
|
||||
String *stringValue() const {
|
||||
return (String *)(val & ~(quint64(Type_Mask) << Tag_Shift));
|
||||
}
|
||||
Object *objectValue() const {
|
||||
return (Object *)(val & ~(quint64(Type_Mask) << Tag_Shift));
|
||||
}
|
||||
#else
|
||||
String *stringValue() const {
|
||||
return s;
|
||||
}
|
||||
Object *objectValue() const {
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
quint64 rawValue() const {
|
||||
return val;
|
||||
}
|
||||
|
||||
static Value undefinedValue();
|
||||
static Value nullValue();
|
||||
static Value fromBoolean(Bool b);
|
||||
static Value fromDouble(double d);
|
||||
static Value fromInt32(int i);
|
||||
static Value fromString(String *s);
|
||||
static Value fromObject(Object *o);
|
||||
|
||||
#ifndef QMLJS_LLVM_RUNTIME
|
||||
static Value fromString(ExecutionContext *ctx, const QString &fromString);
|
||||
#endif
|
||||
|
||||
static double toInteger(double fromNumber);
|
||||
static int toInt32(double value);
|
||||
static unsigned int toUInt32(double value);
|
||||
|
||||
inline int toUInt16(ExecutionContext *ctx);
|
||||
inline int toInt32(ExecutionContext *ctx);
|
||||
inline unsigned int toUInt32(ExecutionContext *ctx);
|
||||
inline Bool toBoolean(ExecutionContext *ctx) const;
|
||||
inline double toInteger(ExecutionContext *ctx) const;
|
||||
double toNumber(ExecutionContext *ctx) const;
|
||||
inline String *toString(ExecutionContext *ctx) const;
|
||||
inline Value toObject(ExecutionContext *ctx) const;
|
||||
|
||||
inline bool isPrimitive() const { return !isObject(); }
|
||||
#if CPU(X86_64)
|
||||
static inline bool integerCompatible(Value a, Value b) {
|
||||
const quint64 mask = quint64(ConvertibleToInt) << 32;
|
||||
return ((a.val & b.val) & mask) == mask;
|
||||
}
|
||||
static inline bool bothDouble(Value a, Value b) {
|
||||
const quint64 mask = quint64(NotDouble_Mask) << 32;
|
||||
return ((a.val | b.val) & mask) != mask;
|
||||
}
|
||||
#else
|
||||
static inline bool integerCompatible(Value a, Value b) {
|
||||
return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
|
||||
}
|
||||
static inline bool bothDouble(Value a, Value b) {
|
||||
return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
|
||||
}
|
||||
#endif
|
||||
inline bool tryIntegerConversion() {
|
||||
bool b = isConvertibleToInt();
|
||||
if (b)
|
||||
tag = _Integer_Type;
|
||||
return b;
|
||||
}
|
||||
|
||||
Object *asObject() const;
|
||||
FunctionObject *asFunctionObject() const;
|
||||
BooleanObject *asBooleanObject() const;
|
||||
NumberObject *asNumberObject() const;
|
||||
StringObject *asStringObject() const;
|
||||
DateObject *asDateObject() const;
|
||||
RegExpObject *asRegExpObject() const;
|
||||
ArrayObject *asArrayObject() const;
|
||||
ErrorObject *asErrorObject() const;
|
||||
ActivationObject *asArgumentsObject() const;
|
||||
|
||||
Value property(ExecutionContext *ctx, String *name) const;
|
||||
|
||||
// Section 9.12
|
||||
bool sameValue(Value other);
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
// context
|
||||
|
@ -439,134 +260,6 @@ Bool __qmljs_cmp_in(Value left, Value right, ExecutionContext *ctx);
|
|||
|
||||
} // extern "C"
|
||||
|
||||
inline int Value::toUInt16(ExecutionContext *ctx)
|
||||
{
|
||||
return __qmljs_to_uint16(*this, ctx);
|
||||
}
|
||||
|
||||
inline int Value::toInt32(ExecutionContext *ctx)
|
||||
{
|
||||
if (isConvertibleToInt())
|
||||
return int_32;
|
||||
|
||||
return Value::toInt32(__qmljs_to_number(*this, ctx));
|
||||
}
|
||||
|
||||
inline unsigned int Value::toUInt32(ExecutionContext *ctx)
|
||||
{
|
||||
if (isConvertibleToInt())
|
||||
return (unsigned) int_32;
|
||||
|
||||
return toUInt32(__qmljs_to_number(*this, ctx));
|
||||
}
|
||||
|
||||
inline Bool Value::toBoolean(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_boolean(*this, ctx);
|
||||
}
|
||||
|
||||
inline double Value::toInteger(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_integer(*this, ctx);
|
||||
}
|
||||
|
||||
inline double Value::toNumber(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_number(*this, ctx);
|
||||
}
|
||||
|
||||
inline String *Value::toString(ExecutionContext *ctx) const
|
||||
{
|
||||
Value v = __qmljs_to_string(*this, ctx);
|
||||
assert(v.isString());
|
||||
return v.stringValue();
|
||||
}
|
||||
|
||||
inline Value Value::toObject(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_object(*this, ctx);
|
||||
}
|
||||
|
||||
inline Value Value::undefinedValue()
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = quint64(_Undefined_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _Undefined_Type;
|
||||
v.int_32 = 0;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::nullValue()
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = quint64(_Null_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _Null_Type;
|
||||
v.int_32 = 0;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromBoolean(Bool b)
|
||||
{
|
||||
Value v;
|
||||
v.tag = _Boolean_Type;
|
||||
v.int_32 = (bool)b;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromDouble(double d)
|
||||
{
|
||||
Value v;
|
||||
v.dbl = d;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromInt32(int i)
|
||||
{
|
||||
Value v;
|
||||
v.tag = _Integer_Type;
|
||||
v.int_32 = i;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromString(String *s)
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = (quint64)s;
|
||||
v.val |= quint64(_String_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _String_Type;
|
||||
v.s = s;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromObject(Object *o)
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = (quint64)o;
|
||||
v.val |= quint64(_Object_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _Object_Type;
|
||||
v.o = o;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline bool Value::sameValue(Value other) {
|
||||
if (val == other.val)
|
||||
return true;
|
||||
if (isString() && other.isString())
|
||||
return __qmljs_string_equal(stringValue(), other.stringValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
#include <qmljs_math.h>
|
||||
|
||||
|
|
|
@ -0,0 +1,226 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the V4VM module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#include <qmljs_engine.h>
|
||||
#include <qmljs_objects.h>
|
||||
#include <qv4ecmaobjects_p.h>
|
||||
|
||||
namespace QQmlJS {
|
||||
namespace VM {
|
||||
|
||||
|
||||
int Value::toUInt16(ExecutionContext *ctx)
|
||||
{
|
||||
return __qmljs_to_uint16(*this, ctx);
|
||||
}
|
||||
|
||||
int Value::toInt32(ExecutionContext *ctx)
|
||||
{
|
||||
if (isConvertibleToInt())
|
||||
return int_32;
|
||||
|
||||
return Value::toInt32(__qmljs_to_number(*this, ctx));
|
||||
}
|
||||
|
||||
unsigned int Value::toUInt32(ExecutionContext *ctx)
|
||||
{
|
||||
if (isConvertibleToInt())
|
||||
return (unsigned) int_32;
|
||||
|
||||
return toUInt32(__qmljs_to_number(*this, ctx));
|
||||
}
|
||||
|
||||
Bool Value::toBoolean(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_boolean(*this, ctx);
|
||||
}
|
||||
|
||||
double Value::toInteger(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_integer(*this, ctx);
|
||||
}
|
||||
|
||||
double Value::toNumber(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_number(*this, ctx);
|
||||
}
|
||||
|
||||
String *Value::toString(ExecutionContext *ctx) const
|
||||
{
|
||||
Value v = __qmljs_to_string(*this, ctx);
|
||||
assert(v.isString());
|
||||
return v.stringValue();
|
||||
}
|
||||
|
||||
Value Value::toObject(ExecutionContext *ctx) const
|
||||
{
|
||||
return __qmljs_to_object(*this, ctx);
|
||||
}
|
||||
|
||||
|
||||
bool Value::sameValue(Value other) {
|
||||
if (val == other.val)
|
||||
return true;
|
||||
if (isString() && other.isString())
|
||||
return __qmljs_string_equal(stringValue(), other.stringValue());
|
||||
return false;
|
||||
}
|
||||
|
||||
Value Value::fromString(ExecutionContext *ctx, const QString &s)
|
||||
{
|
||||
return fromString(ctx->engine->newString(s));
|
||||
}
|
||||
|
||||
int Value::toInt32(double number)
|
||||
{
|
||||
const double D32 = 4294967296.0;
|
||||
const double D31 = D32 / 2.0;
|
||||
|
||||
if ((number >= -D31 && number < D31))
|
||||
return static_cast<int>(number);
|
||||
|
||||
|
||||
if (!std::isfinite(number))
|
||||
return 0;
|
||||
|
||||
double d = ::floor(::fabs(number));
|
||||
if (std::signbit(number))
|
||||
d = -d;
|
||||
|
||||
number = ::fmod(d , D32);
|
||||
|
||||
if (number < -D31)
|
||||
number += D32;
|
||||
else if (number >= D31)
|
||||
number -= D32;
|
||||
|
||||
return int(number);
|
||||
}
|
||||
|
||||
unsigned int Value::toUInt32(double number)
|
||||
{
|
||||
const double D32 = 4294967296.0;
|
||||
if ((number >= 0 && number < D32))
|
||||
return static_cast<uint>(number);
|
||||
|
||||
if (!std::isfinite(number))
|
||||
return +0;
|
||||
|
||||
double d = ::floor(::fabs(number));
|
||||
if (std::signbit(number))
|
||||
d = -d;
|
||||
|
||||
number = ::fmod(d , D32);
|
||||
|
||||
if (number < 0)
|
||||
number += D32;
|
||||
|
||||
return unsigned(number);
|
||||
}
|
||||
|
||||
double Value::toInteger(double number)
|
||||
{
|
||||
if (std::isnan(number))
|
||||
return +0;
|
||||
else if (! number || std::isinf(number))
|
||||
return number;
|
||||
const double v = floor(fabs(number));
|
||||
return std::signbit(number) ? -v : v;
|
||||
}
|
||||
|
||||
Object *Value::asObject() const
|
||||
{
|
||||
return isObject() ? objectValue() : 0;
|
||||
}
|
||||
|
||||
FunctionObject *Value::asFunctionObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asFunctionObject() : 0;
|
||||
}
|
||||
|
||||
BooleanObject *Value::asBooleanObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asBooleanObject() : 0;
|
||||
}
|
||||
|
||||
NumberObject *Value::asNumberObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asNumberObject() : 0;
|
||||
}
|
||||
|
||||
StringObject *Value::asStringObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asStringObject() : 0;
|
||||
}
|
||||
|
||||
DateObject *Value::asDateObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asDateObject() : 0;
|
||||
}
|
||||
|
||||
RegExpObject *Value::asRegExpObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asRegExpObject() : 0;
|
||||
}
|
||||
|
||||
ArrayObject *Value::asArrayObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asArrayObject() : 0;
|
||||
}
|
||||
|
||||
ErrorObject *Value::asErrorObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asErrorObject() : 0;
|
||||
}
|
||||
|
||||
ActivationObject *Value::asArgumentsObject() const
|
||||
{
|
||||
return isObject() ? objectValue()->asActivationObject() : 0;
|
||||
}
|
||||
|
||||
Value Value::property(ExecutionContext *ctx, String *name) const
|
||||
{
|
||||
return isObject() ? objectValue()->__get__(ctx, name) : undefinedValue();
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
|
@ -0,0 +1,325 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the V4VM module of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
#ifndef QMLJS_VALUE_H
|
||||
#define QMLJS_VALUE_H
|
||||
|
||||
#include <wtf/Platform.h>
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtCore/qnumeric.h>
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
namespace QQmlJS {
|
||||
namespace VM {
|
||||
|
||||
struct Array;
|
||||
struct String;
|
||||
struct Object;
|
||||
struct BooleanObject;
|
||||
struct NumberObject;
|
||||
struct StringObject;
|
||||
struct ArrayObject;
|
||||
struct DateObject;
|
||||
struct FunctionObject;
|
||||
struct RegExpObject;
|
||||
struct ErrorObject;
|
||||
struct ActivationObject;
|
||||
struct ArgumentsObject;
|
||||
struct ExecutionContext;
|
||||
struct ExecutionEngine;
|
||||
|
||||
typedef uint Bool;
|
||||
|
||||
|
||||
struct Value
|
||||
{
|
||||
union {
|
||||
quint64 val;
|
||||
double dbl;
|
||||
struct {
|
||||
#if Q_BYTE_ORDER != Q_LITTLE_ENDIAN
|
||||
uint tag;
|
||||
#endif
|
||||
union {
|
||||
uint uint_32;
|
||||
int int_32;
|
||||
#if CPU(X86_64)
|
||||
#else
|
||||
Object *o;
|
||||
String *s;
|
||||
#endif
|
||||
};
|
||||
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
|
||||
uint tag;
|
||||
#endif
|
||||
};
|
||||
};
|
||||
|
||||
enum Masks {
|
||||
NotDouble_Mask = 0xfff80000,
|
||||
Type_Mask = 0xffff0000,
|
||||
Immediate_Mask = NotDouble_Mask | 0x00040000,
|
||||
Tag_Shift = 32
|
||||
};
|
||||
enum ValueType {
|
||||
Undefined_Type = Immediate_Mask | 0x00000,
|
||||
Null_Type = Immediate_Mask | 0x10000,
|
||||
Boolean_Type = Immediate_Mask | 0x20000,
|
||||
Integer_Type = Immediate_Mask | 0x30000,
|
||||
Object_Type = NotDouble_Mask | 0x00000,
|
||||
String_Type = NotDouble_Mask | 0x10000
|
||||
};
|
||||
|
||||
enum ImmediateFlags {
|
||||
ConvertibleToInt = Immediate_Mask | (0x1 << 15)
|
||||
};
|
||||
|
||||
enum ValueTypeInternal {
|
||||
_Undefined_Type = Undefined_Type,
|
||||
_Null_Type = Null_Type | ConvertibleToInt,
|
||||
_Boolean_Type = Boolean_Type | ConvertibleToInt,
|
||||
_Integer_Type = Integer_Type | ConvertibleToInt,
|
||||
_Object_Type = Object_Type,
|
||||
_String_Type = String_Type
|
||||
|
||||
};
|
||||
|
||||
inline ValueType type() const {
|
||||
return (ValueType)(tag & Type_Mask);
|
||||
}
|
||||
|
||||
inline bool isUndefined() const { return tag == _Undefined_Type; }
|
||||
inline bool isNull() const { return tag == _Null_Type; }
|
||||
inline bool isBoolean() const { return tag == _Boolean_Type; }
|
||||
inline bool isInteger() const { return tag == _Integer_Type; }
|
||||
inline bool isDouble() const { return (tag & NotDouble_Mask) != NotDouble_Mask; }
|
||||
inline bool isNumber() const { return tag == _Integer_Type || (tag & NotDouble_Mask) != NotDouble_Mask; }
|
||||
#if CPU(X86_64)
|
||||
inline bool isString() const { return (tag & Type_Mask) == String_Type; }
|
||||
inline bool isObject() const { return (tag & Type_Mask) == Object_Type; }
|
||||
#else
|
||||
inline bool isString() const { return tag == String_Type; }
|
||||
inline bool isObject() const { return tag == Object_Type; }
|
||||
#endif
|
||||
inline bool isConvertibleToInt() const { return (tag & ConvertibleToInt) == ConvertibleToInt; }
|
||||
|
||||
Bool booleanValue() const {
|
||||
return int_32;
|
||||
}
|
||||
double doubleValue() const {
|
||||
return dbl;
|
||||
}
|
||||
void setDouble(double d) {
|
||||
dbl = d;
|
||||
}
|
||||
double asDouble() const {
|
||||
if (tag == _Integer_Type)
|
||||
return int_32;
|
||||
return dbl;
|
||||
}
|
||||
int integerValue() const {
|
||||
return int_32;
|
||||
}
|
||||
|
||||
#if CPU(X86_64)
|
||||
String *stringValue() const {
|
||||
return (String *)(val & ~(quint64(Type_Mask) << Tag_Shift));
|
||||
}
|
||||
Object *objectValue() const {
|
||||
return (Object *)(val & ~(quint64(Type_Mask) << Tag_Shift));
|
||||
}
|
||||
#else
|
||||
String *stringValue() const {
|
||||
return s;
|
||||
}
|
||||
Object *objectValue() const {
|
||||
return o;
|
||||
}
|
||||
#endif
|
||||
|
||||
quint64 rawValue() const {
|
||||
return val;
|
||||
}
|
||||
|
||||
static Value undefinedValue();
|
||||
static Value nullValue();
|
||||
static Value fromBoolean(Bool b);
|
||||
static Value fromDouble(double d);
|
||||
static Value fromInt32(int i);
|
||||
static Value fromString(String *s);
|
||||
static Value fromObject(Object *o);
|
||||
|
||||
#ifndef QMLJS_LLVM_RUNTIME
|
||||
static Value fromString(ExecutionContext *ctx, const QString &fromString);
|
||||
#endif
|
||||
|
||||
static double toInteger(double fromNumber);
|
||||
static int toInt32(double value);
|
||||
static unsigned int toUInt32(double value);
|
||||
|
||||
int toUInt16(ExecutionContext *ctx);
|
||||
int toInt32(ExecutionContext *ctx);
|
||||
unsigned int toUInt32(ExecutionContext *ctx);
|
||||
Bool toBoolean(ExecutionContext *ctx) const;
|
||||
double toInteger(ExecutionContext *ctx) const;
|
||||
double toNumber(ExecutionContext *ctx) const;
|
||||
String *toString(ExecutionContext *ctx) const;
|
||||
Value toObject(ExecutionContext *ctx) const;
|
||||
|
||||
inline bool isPrimitive() const { return !isObject(); }
|
||||
#if CPU(X86_64)
|
||||
static inline bool integerCompatible(Value a, Value b) {
|
||||
const quint64 mask = quint64(ConvertibleToInt) << 32;
|
||||
return ((a.val & b.val) & mask) == mask;
|
||||
}
|
||||
static inline bool bothDouble(Value a, Value b) {
|
||||
const quint64 mask = quint64(NotDouble_Mask) << 32;
|
||||
return ((a.val | b.val) & mask) != mask;
|
||||
}
|
||||
#else
|
||||
static inline bool integerCompatible(Value a, Value b) {
|
||||
return ((a.tag & b.tag) & ConvertibleToInt) == ConvertibleToInt;
|
||||
}
|
||||
static inline bool bothDouble(Value a, Value b) {
|
||||
return ((a.tag | b.tag) & NotDouble_Mask) != NotDouble_Mask;
|
||||
}
|
||||
#endif
|
||||
inline bool tryIntegerConversion() {
|
||||
bool b = isConvertibleToInt();
|
||||
if (b)
|
||||
tag = _Integer_Type;
|
||||
return b;
|
||||
}
|
||||
|
||||
Object *asObject() const;
|
||||
FunctionObject *asFunctionObject() const;
|
||||
BooleanObject *asBooleanObject() const;
|
||||
NumberObject *asNumberObject() const;
|
||||
StringObject *asStringObject() const;
|
||||
DateObject *asDateObject() const;
|
||||
RegExpObject *asRegExpObject() const;
|
||||
ArrayObject *asArrayObject() const;
|
||||
ErrorObject *asErrorObject() const;
|
||||
ActivationObject *asArgumentsObject() const;
|
||||
|
||||
Value property(ExecutionContext *ctx, String *name) const;
|
||||
|
||||
// Section 9.12
|
||||
bool sameValue(Value other);
|
||||
};
|
||||
|
||||
inline Value Value::undefinedValue()
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = quint64(_Undefined_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _Undefined_Type;
|
||||
v.int_32 = 0;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::nullValue()
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = quint64(_Null_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _Null_Type;
|
||||
v.int_32 = 0;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromBoolean(Bool b)
|
||||
{
|
||||
Value v;
|
||||
v.tag = _Boolean_Type;
|
||||
v.int_32 = (bool)b;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromDouble(double d)
|
||||
{
|
||||
Value v;
|
||||
v.dbl = d;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromInt32(int i)
|
||||
{
|
||||
Value v;
|
||||
v.tag = _Integer_Type;
|
||||
v.int_32 = i;
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromString(String *s)
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = (quint64)s;
|
||||
v.val |= quint64(_String_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _String_Type;
|
||||
v.s = s;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
inline Value Value::fromObject(Object *o)
|
||||
{
|
||||
Value v;
|
||||
#if CPU(X86_64)
|
||||
v.val = (quint64)o;
|
||||
v.val |= quint64(_Object_Type) << Tag_Shift;
|
||||
#else
|
||||
v.tag = _Object_Type;
|
||||
v.o = o;
|
||||
#endif
|
||||
return v;
|
||||
}
|
||||
|
||||
} // namespace VM
|
||||
} // namespace QQmlJS
|
||||
|
||||
#endif
|
2
v4.pro
2
v4.pro
|
@ -17,6 +17,7 @@ SOURCES += main.cpp \
|
|||
qmljs_environment.cpp \
|
||||
qmljs_runtime.cpp \
|
||||
qmljs_objects.cpp \
|
||||
qmljs_value.cpp \
|
||||
qv4syntaxchecker.cpp \
|
||||
qv4ecmaobjects.cpp \
|
||||
qv4array.cpp \
|
||||
|
@ -31,6 +32,7 @@ HEADERS += \
|
|||
qmljs_runtime.h \
|
||||
qmljs_objects.h \
|
||||
qmljs_math.h \
|
||||
qmljs_value.h \
|
||||
qv4syntaxchecker_p.h \
|
||||
qv4ecmaobjects_p.h \
|
||||
qv4array_p.h \
|
||||
|
|
Loading…
Reference in New Issue