summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qmlcompiler.cpp43
-rw-r--r--src/declarative/qml/qmlcompiler_p.h1
-rw-r--r--src/declarative/qml/qmlcustomparser.cpp2
-rw-r--r--src/declarative/qml/qmldom.cpp4
-rw-r--r--src/declarative/qml/qmlparser.cpp92
-rw-r--r--src/declarative/qml/qmlparser_p.h44
-rw-r--r--src/declarative/qml/qmlscriptparser.cpp79
7 files changed, 183 insertions, 82 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index a40b7c8..c547d31 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -192,16 +192,6 @@ bool QmlCompiler::isValidId(const QString &val)
return true;
}
-/*!
- Returns true if \a str is a valid binding string, false otherwise.
-
- Valid binding strings are those enclosed in braces ({}).
-*/
-bool QmlCompiler::isBinding(const QString &str)
-{
- return str.startsWith(QLatin1Char('{')) && str.endsWith(QLatin1Char('}'));
-}
-
/*!
Returns true if property name \a name refers to an attached property, false
otherwise.
@@ -671,7 +661,7 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt)
COMPILE_CHECK(compileComponentFromRoot(root, ctxt));
if (idProp && idProp->values.count()) {
- QString val = idProp->values.at(0)->primitive;
+ QString val = idProp->values.at(0)->primitive();
if (!isValidId(val))
COMPILE_EXCEPTION("Invalid id property value");
@@ -766,13 +756,10 @@ bool QmlCompiler::compileSignal(Property *prop, Object *obj)
return rv;
} else {
- QString script = prop->values.at(0)->primitive.trimmed();
+ QString script = prop->values.at(0)->value.asScript().trimmed();
if (script.isEmpty())
return true;
- if (isBinding(script))
- COMPILE_EXCEPTION("Cannot assign binding to signal property");
-
int idx = output->indexForString(script);
int pr = output->indexForByteArray(prop->name);
@@ -887,7 +874,7 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop,
if (prop->values.count() == 1) {
if (prop->values.at(0)->object)
COMPILE_EXCEPTION("Cannot assign an object as an id");
- QString val = prop->values.at(0)->primitive;
+ QString val = prop->values.at(0)->primitive();
if (!isValidId(val))
COMPILE_EXCEPTION(val << "is not a valid id");
if (ids.contains(val))
@@ -1031,11 +1018,12 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop,
assign.assignObject.property = output->indexForByteArray(prop->name);
assign.assignObject.castValue = 0;
output->bytecode << assign;
- } else if (isBinding(v->primitive)) {
+ } else if (v->value.isScript()) {
if (assignedBinding)
COMPILE_EXCEPTION("Can only assign one binding to lists");
- compileBinding(v->primitive, prop, ctxt, obj->metaObject(), v->location.start.line);
+ compileBinding(v->value.asScript(), prop, ctxt,
+ obj->metaObject(), v->location.start.line);
v->type = Value::PropertyBinding;
} else {
COMPILE_EXCEPTION("Cannot assign primitives to lists");
@@ -1186,9 +1174,10 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
QmlParser::Value *v,
int ctxt)
{
- if (isBinding(v->primitive)) {
+ if (v->value.isScript()) {
- compileBinding(v->primitive, prop, ctxt, obj->metaObject(), v->location.start.line);
+ compileBinding(v->value.asScript(), prop, ctxt, obj->metaObject(),
+ v->location.start.line);
v->type = Value::PropertyBinding;
@@ -1199,8 +1188,9 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
bool doassign = true;
if (prop->index != -1) {
+ QString value = v->primitive();
StoreInstructionResult r =
- generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &v->primitive);
+ generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &value);
if (r == Ok) {
doassign = false;
@@ -1208,10 +1198,10 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
//### we are restricted to a rather generic message here. If we can find a way to move
// the exception into generateStoreInstruction we could potentially have better messages.
// (the problem is that both compile and run exceptions can be generated, though)
- COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name());
+ COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to property" << obj->metaObject()->property(prop->index).name());
doassign = false;
} else if (r == ReadOnly) {
- COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name());
+ COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to the read-only property" << obj->metaObject()->property(prop->index).name());
} else {
doassign = true;
}
@@ -1226,7 +1216,7 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop,
output->indexForByteArray(prop->name);
}
assign.assignConstant.constant =
- output->indexForString(v->primitive);
+ output->indexForString(v->primitive());
}
output->bytecode << assign;
@@ -1335,12 +1325,9 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj)
return true;
}
-void QmlCompiler::compileBinding(const QString &str, QmlParser::Property *prop,
+void QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop,
int ctxt, const QMetaObject *mo, qint64 line)
{
- Q_ASSERT(isBinding(str));
-
- QString bind = str.mid(1, str.length() - 2).trimmed();
QmlBasicScript bs;
bs.compile(bind.toLatin1());
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index b885e7b..b122650 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -118,7 +118,6 @@ public:
QList<QmlError> errors() const;
static bool isValidId(const QString &);
- static bool isBinding(const QString &);
static bool isAttachedProperty(const QByteArray &);
enum StoreInstructionResult { Ok, UnknownType, InvalidData, ReadOnly };
diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp
index 06035b0..e864df9 100644
--- a/src/declarative/qml/qmlcustomparser.cpp
+++ b/src/declarative/qml/qmlcustomparser.cpp
@@ -138,7 +138,7 @@ QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p)
QmlCustomParserNode node = fromObject(v->object);
prop.d->values << QVariant::fromValue(node);
} else {
- prop.d->values << QVariant::fromValue(v->primitive);
+ prop.d->values << QVariant::fromValue(v->primitive());
}
}
diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp
index 4e754a3..09b4a3b 100644
--- a/src/declarative/qml/qmldom.cpp
+++ b/src/declarative/qml/qmldom.cpp
@@ -809,7 +809,7 @@ Rect { x: 10 }
*/
QString QmlDomValueLiteral::literal() const
{
- if (d->value) return d->value->primitive;
+ if (d->value) return d->value->primitive();
else return QString();
}
@@ -878,7 +878,7 @@ Rect { x: Other.x }
QString QmlDomValueBinding::binding() const
{
if (d->value)
- return d->value->primitive.mid(1, d->value->primitive.length() - 2);
+ return d->value->value.asScript();
else
return QString();
}
diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp
index 2bd41e2..bafdb02 100644
--- a/src/declarative/qml/qmlparser.cpp
+++ b/src/declarative/qml/qmlparser.cpp
@@ -233,14 +233,102 @@ void QmlParser::Value::dump(int indent) const
case Value::Id:
type = "Id";
break;
- };
+ }
+
+ QByteArray primType;
+ switch(this->value.type()) {
+ default:
+ case Variant::Invalid:
+ primType = "Invalid";
+ break;
+ case Variant::Boolean:
+ primType = "Boolean";
+ break;
+ case Variant::Number:
+ primType = "Number";
+ break;
+ case Variant::String:
+ primType = "String";
+ break;
+ case Variant::Script:
+ primType = "Script";
+ break;
+ }
QByteArray ba(indent * 4, ' ');
if (object) {
qWarning() << ba.constData() << "Value (" << type << "):";
object->dump(indent + 1);
} else {
- qWarning() << ba.constData() << "Value (" << type << "):" << primitive;
+ qWarning() << ba.constData() << "Value (" << type << "):" << primType.constData() << primitive();
+ }
+}
+
+QmlParser::Variant::Variant()
+: t(Invalid) {}
+
+QmlParser::Variant::Variant(const Variant &o)
+: t(o.t), d(o.d), s(o.s)
+{
+}
+
+QmlParser::Variant::Variant(bool v)
+: t(Boolean), b(v)
+{
+}
+
+QmlParser::Variant::Variant(double v)
+: t(Number), d(v)
+{
+}
+
+QmlParser::Variant::Variant(const QString &v, Type type)
+: t(type), s(v)
+{
+ Q_ASSERT(type == String || type == Script);
+}
+
+QmlParser::Variant &QmlParser::Variant::operator=(const Variant &o)
+{
+ t = o.t;
+ d = o.d;
+ s = o.s;
+ return *this;
+}
+
+QmlParser::Variant::Type QmlParser::Variant::type() const
+{
+ return t;
+}
+
+bool QmlParser::Variant::asBoolean() const
+{
+ return b;
+}
+
+QString QmlParser::Variant::asString() const
+{
+ return s;
+}
+
+double QmlParser::Variant::asNumber() const
+{
+ return d;
+}
+
+QString QmlParser::Variant::asScript() const
+{
+ switch(type()) {
+ default:
+ case Invalid:
+ return QString();
+ case Boolean:
+ return b?QLatin1String("true"):QLatin1String("false");
+ case Number:
+ return QString::number(d);
+ case String:
+ case Script:
+ return s;
}
}
diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h
index 31f8702..d67690b 100644
--- a/src/declarative/qml/qmlparser_p.h
+++ b/src/declarative/qml/qmlparser_p.h
@@ -152,6 +152,45 @@ namespace QmlParser
void dump(int = 0) const;
};
+ class Variant
+ {
+ public:
+ enum Type {
+ Invalid,
+ Boolean,
+ Number,
+ String,
+ Script
+ };
+
+ Variant();
+ Variant(const Variant &);
+ Variant(bool);
+ Variant(double);
+ Variant(const QString &, Type = String);
+ Variant &operator=(const Variant &);
+
+ Type type() const;
+
+ bool isBoolean() const { return type() == Boolean; }
+ bool isNumber() const { return type() == Number; }
+ bool isString() const { return type() == String; }
+ bool isScript() const { return type() == Script; }
+
+ bool asBoolean() const;
+ QString asString() const;
+ double asNumber() const;
+ QString asScript() const;
+
+ private:
+ Type t;
+ union {
+ bool b;
+ double d;
+ };
+ QString s;
+ };
+
class Value : public QmlRefCount
{
public:
@@ -180,8 +219,11 @@ namespace QmlParser
};
Type type;
+ // ### Temporary
+ QString primitive() const { return value.asScript(); }
+
// Primitive value
- QString primitive;
+ Variant value;
// Object value
Object *object;
diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp
index 169e2ea..4de9e40 100644
--- a/src/declarative/qml/qmlscriptparser.cpp
+++ b/src/declarative/qml/qmlscriptparser.cpp
@@ -74,8 +74,8 @@ protected:
AST::SourceLocation typeLocation,
LocationSpan location,
AST::UiObjectInitializer *initializer = 0);
- QString getPrimitive(const QByteArray &propertyName, AST::ExpressionNode *expr);
- void defineProperty(const QString &propertyName, const LocationSpan &location, const QString &primitive);
+
+ QmlParser::Variant getVariant(AST::ExpressionNode *expr);
LocationSpan location(AST::SourceLocation start, AST::SourceLocation end);
LocationSpan location(AST::UiQualifiedId *);
@@ -305,15 +305,22 @@ Object *ProcessAST::defineObjectBinding(int line,
QString propertyName = asString(scriptBinding->qualifiedId);
if (propertyName == QLatin1String("script")) {
QString script;
+
if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) {
- script = getPrimitive("script", stmt->expression);
+ script = getVariant(stmt->expression).asScript();
} else {
script = asString(scriptBinding->statement);
}
LocationSpan l = this->location(scriptBinding->statement->firstSourceLocation(),
scriptBinding->statement->lastSourceLocation());
- defineProperty(QLatin1String("script"), l, script);
+
+ _stateStack.pushProperty(QLatin1String("script"), l);
+ Value *value = new Value;
+ value->value = QmlParser::Variant(script);
+ value->location = l;
+ currentProperty()->addValue(value);
+ _stateStack.pop();
} else {
accept(it->member);
}
@@ -342,16 +349,6 @@ LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation
return rv;
}
-void ProcessAST::defineProperty(const QString &propertyName, const LocationSpan &location, const QString &primitive)
-{
- _stateStack.pushProperty(propertyName, location);
- Value *value = new Value;
- value->primitive = primitive;
- value->location = location;
- currentProperty()->addValue(value);
- _stateStack.pop();
-}
-
// UiProgram: UiImportListOpt UiObjectMemberList ;
bool ProcessAST::visit(AST::UiProgram *node)
{
@@ -436,7 +433,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
Value *value = new Value;
value->location = location(node->expression->firstSourceLocation(),
node->expression->lastSourceLocation());
- value->primitive = getPrimitive("value", node->expression);
+ value->value = getVariant(node->expression);
property.defaultValue->values << value;
}
@@ -480,30 +477,25 @@ bool ProcessAST::visit(AST::UiObjectBinding *node)
return false;
}
-QString ProcessAST::getPrimitive(const QByteArray &propertyName, AST::ExpressionNode *expr)
+QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr)
{
- QString primitive;
+ QmlParser::Variant rv;
- if (isSignalProperty(propertyName)) {
- primitive = asString(expr);
- } else if (propertyName == "id" && expr && expr->kind == AST::Node::Kind_IdentifierExpression) {
- primitive = asString(expr);
- } else if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
+ if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) {
// hack: emulate weird XML feature that string literals are not quoted.
//This needs to be fixed in the qmlcompiler once xml goes away.
- primitive = lit->value->asString();
- } else if (expr->kind == AST::Node::Kind_TrueLiteral
- || expr->kind == AST::Node::Kind_FalseLiteral
- || expr->kind == AST::Node::Kind_NumericLiteral
- ) {
- primitive = asString(expr);
+ rv = QmlParser::Variant(lit->value->asString());
+ } else if (expr->kind == AST::Node::Kind_TrueLiteral) {
+ rv = QmlParser::Variant(true);
+ } else if (expr->kind == AST::Node::Kind_FalseLiteral) {
+ rv = QmlParser::Variant(false);
+ } else if(AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) {
+ rv = QmlParser::Variant(lit->value);
} else {
- // create a binding
- primitive += QLatin1Char('{');
- primitive += asString(expr);
- primitive += QLatin1Char('}');
+ rv = QmlParser::Variant(asString(expr), QmlParser::Variant::Script);
}
- return primitive;
+
+ return rv;
}
@@ -519,25 +511,18 @@ bool ProcessAST::visit(AST::UiScriptBinding *node)
}
Property *prop = currentProperty();
- QString primitive;
+
+ QmlParser::Variant primitive;
if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) {
- primitive = getPrimitive(prop->name, stmt->expression);
- } else if (isSignalProperty(prop->name)) {
- if (AST::Block *block = AST::cast<AST::Block *>(node->statement)) {
- const int start = block->lbraceToken.offset + block->rbraceToken.length;
- primitive += _contents.mid(start, block->rbraceToken.offset - start);
- } else {
- primitive += asString(node->statement);
- }
+ primitive = getVariant(stmt->expression);
} else { // do binding
- primitive += QLatin1Char('{');
- primitive += asString(node->statement);
- primitive += QLatin1Char('}');
+ primitive = QmlParser::Variant(asString(node->statement),
+ QmlParser::Variant::Script);
}
Value *v = new Value;
- v->primitive = primitive;
+ v->value = primitive;
v->location = location(node->statement->firstSourceLocation(),
node->statement->lastSourceLocation());
@@ -616,7 +601,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node)
Value *value = new Value;
value->location = location(node->firstSourceLocation(),
node->lastSourceLocation());
- value->primitive = source;
+ value->value = QmlParser::Variant(source);
obj->getDefaultProperty()->addValue(value);
}