diff --git a/src/qmljsc/ir/ir.h b/src/qmljsc/ir/ir.h --- a/src/qmljsc/ir/ir.h +++ b/src/qmljsc/ir/ir.h @@ -26,9 +26,18 @@ #include #include +/* ongoing renames + * + * Object -> ObjectSpec + * Component -> QmlComponent + * Property::type -> qmltype + * + */ + namespace QQmlJS { namespace AST { class ExpressionNode; + class FunctionBody; } } @@ -49,12 +58,22 @@ Kind_List, Kind_Class, Kind_Component, - Kind_Object + Kind_Object, + Kind_RootObject, + Kind_Document, + Kind_PropertyValue, + Kind_ObjectRef, + Kind_ObjectList, + Kind_JsValue, + Kind_ValueAssignment }; + Node() : m_kind(Kind_Invalid) {} + Node(Kind arg_kind) : m_kind(arg_kind) { } + template T *as() { - if (T::kind == kind) { + if (T::kind == m_kind) { return reinterpret_cast(this); } return 0; @@ -62,7 +81,10 @@ virtual void accept(Visitor *visitor) = 0; - Kind kind; + Kind m_kind; + + Kind kind() { return m_kind; } + void setKind( Kind k ) { m_kind = k; } }; class Property; @@ -81,7 +103,7 @@ public: Type(); - Kind kind(); + //Kind kind(); const QString &name(); Property *property(const QString &name); Method *method(const QString &name); @@ -99,8 +121,8 @@ virtual void accept(Visitor *visitor) override; -protected: - Kind m_kind; +//protected: +// Kind m_kind; protected: QString m_name; @@ -119,30 +141,90 @@ friend class TestIR; }; -class Class : public Type +//////////////////////////////////////// property values +struct PropertyValue : public Node { public: - Class(); + PropertyValue(Kind arg_kind = Kind_PropertyValue) : Node(arg_kind) { /* property = 0; */ } + //PropertyValue(Property *property); + //Property *property; // are we in need to keep ref to our property? + virtual void accept(Visitor *visitor) = 0; + + //Property *property; +}; + +class Class; +class Object; + +struct ObjectRef : public PropertyValue +{ +public: + ObjectRef( Object *argtarget = 0 ) : PropertyValue(Kind_ObjectRef), target(argtarget) { } virtual void accept(Visitor *visitor) override; + Object *target; +}; -private: - Type *m_attached; +struct JsValue : public PropertyValue +{ +public: + JsValue() : PropertyValue(Kind_JsValue), target(0) {} + JsValue(QQmlJS::AST::ExpressionNode * argtarget) : target(argtarget) {} + QQmlJS::AST::ExpressionNode *target; + virtual void accept(Visitor *visitor) override; +}; - friend class TestIR; +struct ObjectList : public PropertyValue +{ +public: + ObjectList( QVector *argtarget = 0 ) : PropertyValue(Kind_ObjectList) { + if (argtarget) target = *argtarget; + } + + virtual void accept(Visitor *visitor) override; + QVector target; }; -class Object; +//////////////////////////////////////////////////////// end of property values struct ValueAssignment : public Node { - ValueAssignment(); + ValueAssignment(Property *argproperty = 0 ) : Node(Kind_ValueAssignment),property(argproperty),value(0) { } - ValueAssignment(Property *property, Object *objectValue, QQmlJS::AST::ExpressionNode *jsValue); + template // + ValueAssignment(Property *argproperty, T* theval ) : ValueAssignment(argproperty) { + assignValue( theval ); + } - Property *property; - Object *objectValue; - QQmlJS::AST::ExpressionNode *jsValue; + Property *property; + PropertyValue *value; + + //template assignValue( T* newval ); + void assignValue( Object *val ) { + if (value) delete value; + value = new ObjectRef(val); + } + void assignValue( QVector *val ) { + if (value) delete value; + value = new ObjectList(val); + } + void assignValue( QQmlJS::AST::ExpressionNode *val ) { + if (value) delete value; + value = new JsValue(val); + } + + Object* objectValue() { + ObjectRef *t = dynamic_cast(value); + return t ? t->target : 0; + } + QQmlJS::AST::ExpressionNode* jsValue() { + JsValue *t = dynamic_cast(value); + return t ? t->target : 0; + } + QVector* listValue() { + ObjectList *t = dynamic_cast(value); + return t ? &t->target : 0; + } virtual void accept(Visitor *visitor) override; }; @@ -159,13 +241,20 @@ virtual void accept(Visitor *visitor) override; }; +class QmlComponent; +//typedef QmlComponent Component; + class Component; +class Class; class Object : public Type { public: Object(); + Object( Class* objectClass) : Object() { + setSuper( (Type*)objectClass ); + } QVector &valueAssignments(); QVector &bindingAssignments(); @@ -175,6 +264,19 @@ virtual void accept(Visitor *visitor) override; + // Document Tree is defined by File. So if file contains components, they all are in a one component tree + Object *m_parentInDocumentTree; + QList m_childrenInDocumentTree; + + // js id inside document tree of file + QString idAssignedByGeneratorPass; // so we place generator's state inside object.. badf.. + + // Root Object is a top object spec of Document tree, or a top object of some Component + // so if document contains some of components, their inner objects are rootobjects too. + bool m_isRootObject; + bool isRootObject() { return m_isRootObject; } + + protected: QVector m_valueAssignments; QVector m_bindingAssignments; @@ -187,9 +289,36 @@ */ Component *m_component; + + + // also we have m_super which is Class which is Object[Spec] itself + + friend class TestIR; +}; + + +class Class : public Object +{ +public: + Class(); + Class(QString _name) { + setName(_name); + } + + virtual void accept(Visitor *visitor) override; + +private: + Type *m_attached; + friend class TestIR; }; + + + + +// ? do we need it +/* class Component : public Object { public: @@ -207,6 +336,7 @@ friend class TestIR; }; +*/ struct Parameter { QmlJSc::IR::Type *type; @@ -221,6 +351,9 @@ QmlJSc::IR::Type *returnType; QString name; + QVector parameters; + QQmlJS::AST::FunctionBody *body; + virtual void accept(QmlJSc::IR::Visitor *visitor) override; }; @@ -233,23 +366,122 @@ virtual void accept(QmlJSc::IR::Visitor *visitor) override; }; -struct Property : public QmlJSc::IR::Node { - Property(); - Property(const QString &name); - Property(QmlJSc::IR::Type *type, QString name); +struct Property : public QmlJSc::IR::ValueAssignment { + Property(QmlJSc::IR::Type *argtype=0, QString argname="") : ValueAssignment(this) { + m_kind = Kind_Property; + type = argtype; + name = argname; + } + Property(QString argname) : Property(0, argname) { }; - QmlJSc::IR::Type *type; + template + Property(QmlJSc::IR::Type *type, QString name, T* argval) : Property(type,name) { + assignValue( argval ); + } + + + QmlJSc::IR::Type *type; // qml type QString name; - QmlJSc::IR::Object *objectValue; - QQmlJS::AST::ExpressionNode *jsValue; bool readOnly :1; bool constant :1; - bool dummy :6; + bool dummy :5; + bool thedefault: 1; virtual void accept(QmlJSc::IR::Visitor *visitor) override; }; +// it is good to init all classes to some baseclass always. +// so we create singleton for QtObject class +class QtBaseClass : public Class { +public: QtBaseClass() { + setName("QtObject"); + QmlJSc::IR::Type* stringType = new QmlJSc::IR::Type(); + stringType->setKind( Kind_BasicType ); + stringType->setName("string"); + QmlJSc::IR::Property *p = addProperty("objectName"); + p->type = stringType; + } +}; + +extern QtBaseClass qtBaseClass; + +//////////////////////////////////////// RootObject +// are we really need it as separate class?.. maybe boolean flag is enought? + +/* +class RootObject : public Object +{ +public: + RootObject() { + m_kind = Node::Kind_RootObject; + } + + RootObject( Class* objectClass) : Object(objectClass) { + + } + + //same as in object + //virtual void accept(Visitor *visitor) override; + +private: + + friend class TestIR; +};*/ + + + +/////////////////////////////////////// QmlComponent + +class Component : public Class +{ +public: + Component() : m_pRootObject(0) { + m_kind = Node::Kind_Component; + m_pRootObject = &emptyObject; + m_pRootObject->m_isRootObject = true; + } + + Component( Object *rootObject) : Component() { + m_pRootObject = rootObject; + m_pRootObject->m_isRootObject = true; + } + + Object emptyObject; + Object* m_pRootObject; + + virtual void accept(Visitor *visitor) override; + +private: + + friend class TestIR; +}; + + +/* +class Component : public QmlComponent { +};*/ + + +//////////////////////////////////////// QmlFile + +class QmlFile : public Component // public QmlComponent +{ +public: + QmlFile() { //: Node(Node::Kind_Component) { + m_kind = Node::Kind_Document; + } + + virtual void accept(Visitor *visitor) override; + + //RootObject rootObject; + +private: + + friend class TestIR; +}; + + } // namespace IR } // namespace QmlJSc diff --git a/src/qmljsc/ir/ir.cpp b/src/qmljsc/ir/ir.cpp --- a/src/qmljsc/ir/ir.cpp +++ b/src/qmljsc/ir/ir.cpp @@ -30,10 +30,10 @@ { } -Type::Kind Type::kind() +/*Type::Kind Type::kind() { return m_kind; -} +}*/ const QString &Type::name() { @@ -136,10 +136,32 @@ m_super = superType; } -Class::Class() - : Type() +//////////////////////////////////////////////////// + +void ObjectRef::accept(Visitor *visitor) { + visitor->visit(this); + target->accept(visitor); + visitor->endVisit(this); +} + +void JsValue::accept(Visitor *visitor) { + visitor->visit(this); + //target->accept(visitor); + visitor->endVisit(this); +} + +void ObjectList::accept(Visitor *visitor) { + visitor->visit(this); + foreach (Object* obj, target) obj->accept(visitor); + visitor->endVisit(this); +} + +/////////////////////////////////////////////////// + +Class::Class() : Object() { m_kind = Type::Kind_Class; + m_name = "QtObject"; } void Class::accept(Visitor *visitor) { @@ -151,6 +173,9 @@ : Type() { m_kind = Type::Kind_Object; + setSuper(&qtBaseClass); + m_isRootObject = false; + m_parentInDocumentTree = 0; } QVector &Object::valueAssignments() @@ -163,19 +188,22 @@ return m_bindingAssignments; } +/* ValueAssignment::ValueAssignment() : property(0) , objectValue(0) , jsValue(0) { -} +}*/ +/* ValueAssignment::ValueAssignment(Property *property, Object *objectValue, QQmlJS::AST::ExpressionNode *jsValue) : property(property) , objectValue(objectValue) , jsValue(jsValue) { } +*/ ValueAssignment *Object::addValueAssignment() { @@ -185,9 +213,7 @@ void ValueAssignment::accept(Visitor *visitor) { visitor->visit(this); - if (objectValue) { - objectValue->accept(visitor); - } + if (value) value->accept(visitor); visitor->endVisit(this); } @@ -232,6 +258,7 @@ } } +/* Component::Component() : Object() { @@ -262,25 +289,26 @@ i.value()->accept(visitor); } } +*/ Method::Method() : returnType(0) { - kind = Kind_Method; + m_kind = Kind_Method; } Method::Method(const QString &name) : returnType(0) , name(name) { - kind = Kind_Method; + m_kind = Kind_Method; } Method::Method(QmlJSc::IR::Type *returnType, QString name) : returnType(returnType) , name(name) { - kind = Kind_Method; + m_kind = Kind_Method; } void Method::accept(QmlJSc::IR::Visitor *visitor) { @@ -290,13 +318,13 @@ Signal::Signal() { - kind = Kind_Signal; + m_kind = Kind_Signal; } Signal::Signal(QString name) : name(name) { - kind = Kind_Signal; + m_kind = Kind_Signal; } void Signal::accept(QmlJSc::IR::Visitor *visitor) { @@ -304,36 +332,60 @@ visitor->endVisit(this); } -Property::Property() +/*Property::Property() : type(0) - , objectValue(0) - , jsValue(0) { - kind = Kind_Property; + m_kind = Kind_Property; } Property::Property(const QString &name) : type(0) , name(name) - , objectValue(0) - , jsValue(0) { - kind = Kind_Property; + m_kind = Kind_Property; } Property::Property(QmlJSc::IR::Type *type, QString name) : type(type) , name(name) - , objectValue(0) - , jsValue(0) { - kind = Kind_Property; + m_kind = Kind_Property; } +*/ void Property::accept(QmlJSc::IR::Visitor *visitor) { visitor->visit(this); - if (objectValue) { - objectValue->accept(visitor); - } + if (value) value->accept(visitor); visitor->endVisit(this); -} \ No newline at end of file +} + +//////////////////////////// + +void QmlFile::accept(Visitor *visitor) { + + Component::accept(visitor); + //visitor->visit(this); + //rootObject.accept( visitor ); + //visitor->endVisit(this); + +} + +void Component::accept(Visitor *visitor) { + + visitor->visit(this); + if (m_pRootObject) + m_pRootObject->accept( visitor ); + visitor->endVisit(this); + +} + +/* +void RootObject::accept(Visitor *visitor) { + //visitor->visit(this); + //rootObject.accept( visitor ); + //visitor->endVisit(this); +}*/ + +// singleton +QtBaseClass QmlJSc::IR::qtBaseClass; +