Mercurial > projects > qtd
diff d2/qtd/meta/Runtime.d @ 368:185df9220ea7
Fixed startsWith. Implemented meta-object members as ranges. Freed QMetaObject from stuff that belongs to MetaClass
author | Max Samukha <maxter@maxter.com> |
---|---|
date | Mon, 28 Jun 2010 21:29:32 +0300 |
parents | 958e8b9a89bd |
children | a032df77b6ab |
line wrap: on
line diff
--- a/d2/qtd/meta/Runtime.d Thu Jun 24 13:47:30 2010 +0300 +++ b/d2/qtd/meta/Runtime.d Mon Jun 28 21:29:32 2010 +0300 @@ -4,21 +4,25 @@ License: Boost Software License 1.0 **************************************************************************/ module qtd.meta.Runtime; -//TODO: Probably replace switch dispatch with pointer dispatch -//and leave switch dispatch only in C interface import qtd.meta.Compiletime, std.typetuple, std.conv, - std.variant, - core.sync.rwmutex; + std.stdio, + std.traits, + std.variant; -private __gshared ReadWriteMutex lock; +import std.range : isForwardRange, isRandomAccessRange; + +/** + Object to lock on when accessing thread-shared meta-objects. + */ +immutable Object metaLock; shared static this() { - lock = new ReadWriteMutex; + metaLock = cast(immutable)new Object; } /** @@ -87,13 +91,14 @@ } } -abstract class Meta +abstract class MetaBase { alias typeof(this) This; string name; MetaAttribute[] attributes; - Meta[] members; + + protected MetaBase[] members_; template createImpl(M : This) { @@ -125,35 +130,91 @@ protected void construct(alias symbol)() { + name = symbol.stringof; createAttrs!symbol; } + + static struct MembersRange + { + private MetaBase[] members_; + + @property + MetaBase front() + { + return members_[0]; + } + + @property + bool empty() + { + return members_.length == 0; + } + + @property + MembersRange save() + { + return this; + } + + @property + MetaBase back() + { + return members_[$ - 1]; + } + + void popFront() + { + members_ = members_[1..$]; + } + + void popBack() + { + members_ = members_[0..$ - 1]; + } + + MetaBase opIndex(size_t i) + { + return members_[i]; + } + + @property + size_t length() + { + return members_.length; + } + } + + /** + Returns a random access range of members of the class described by this meta-object. + */ + @property + MembersRange members() + { + return MembersRange(members_); + } } +version (QtdUnittest) unittest +{ + static assert(isRandomAccessRange!(MetaBase.MembersRange)); +} + /** - Base class for run time attributes. + Base class for run-time attributes. */ abstract class MetaAttribute { - alias typeof(this) This; - string name; AttributeOptions options; - This create(string name, AttributeOptions opts, A...)() - { - auto ma = new This; - ma.construct!(name, opts, A)(); - return ma; - } - - void construct(string name, AttributeOptions opts)() + this(string name, AttributeOptions opts) { this.name = name; options = opts; } } -abstract class MetaType : Meta +abstract class MetaType : MetaBase { } @@ -164,7 +225,148 @@ class MetaClass : MetaAggregate { alias typeof(this) This; + + private + { + This base_; + This firstDerived_; + This next_; + ClassInfo classInfo_; + } + alias createImpl!This create; + + static struct AllMembersRange + { + public //private + { + This metaClass_; + MetaBase[] members_; + + void skipEmpty() + { + while (!metaClass_.members_.length) + { + metaClass_ = metaClass_.base_; + if (!metaClass_) + { + members_ = null; + return; + } + } + + members_ = metaClass_.members_; + } + } + + this(This metaClass) + { + metaClass_ = metaClass; + skipEmpty(); + } + + @property + MetaBase front() + { + return members_[0]; + } + + @property + bool empty() + { + return members_.length == 0; + } + + @property + AllMembersRange save() + { + return this; + } + + void popFront() + { + members_ = members_[1..$]; + if (!members_.length) + { + metaClass_ = metaClass_.base_; + if (metaClass_) + skipEmpty(); + } + } + } + + /** + Returns a forward range of members of the class described by this meta-object, + including base class members. + */ + @property + AllMembersRange allMembers() + { + return AllMembersRange(this); + } + + /** + Returns the meta-object of the base class. + */ + @property + This base() + { + return base_; + } + + /** + Returns the next meta-object on this level of the inheritance hierarchy. + */ + @property + This next() + { + return next_; + } + + /** + Returns the meta-object for the first derived class. + */ + @property + This firstDerived() + { + return firstDerived_; + } + + /** + D class info. + */ + @property + ClassInfo classInfo() + { + return classInfo_; + } + + + /* internal */ void construct(T : Object)() + { + super.construct!T(); + static if (!is(T == Object)) + { + alias BaseClassesTuple!(T)[0] Base; + base_ = meta!Base; + + next_ = base_.firstDerived_; + base_.firstDerived_ = this; + } + classInfo_ = T.classinfo; + } + + /** + */ + override string toString() const + { + return "MetaClass for " ~ classInfo_.name; + } +} + +version (QtdUnittest) unittest +{ + static assert (isForwardRange!(MetaClass.AllMembersRange)); } class MetaStruct : MetaAggregate @@ -173,58 +375,72 @@ alias createImpl!This create; } +/** + */ @property -auto meta(alias symbol, M : Meta)() +M meta(alias symbol, M : MetaBase)() { - __gshared static M m; + __gshared static M sharedM; + static M m; + if (!m) { - lock.reader.lock; - scope(exit) - lock.reader.unlock; - if (m) - return m; + synchronized(metaLock) + { + if (!sharedM) + sharedM = M.create!symbol; + } + m = sharedM; } - lock.writer.lock; - scope(exit) - lock.writer.unlock; - - if (!m) - m = M.create!symbol; + assert (m is sharedM); return m; } +version (QtdUnittest) unittest +{ + class A + { + } + + auto m = meta!A; + assert(m is meta!A); +} + +/** + */ // only classes and structs for now @property auto meta(T)() { - static if (is(typeof(T.staticMetaObject))) - return T.staticMetaObject; + static if (is(T.Meta)) + return meta!(T, T.Meta); else static if (is(T == class)) return meta!(T, MetaClass); else static if (is(T == struct)) return meta!(T, MetaStruct); else - static assert(false, "No meta object for symbol " ~ T.stringof); + static assert(false, "No meta-object for symbol " ~ T.stringof); } /** - A run time attribute implementation that stores the attribute data in an + A run-time attribute implementation that stores the attribute data in an array of variants. */ class MetaVariantAttribute : MetaAttribute { + alias typeof(this) This; + Variant[] values; - private this() + private this(string name, AttributeOptions opts) { + super(name, opts); } - static MetaVariantAttribute create(string category, AttributeOptions opts, A...)() + static MetaVariantAttribute create(string name, AttributeOptions opts, A...)() { - auto ret = new MetaVariantAttribute; - ret.construct!(category, opts)(); + auto ret = new This(name, opts); foreach(i, _; A) { static if (__traits(compiles, { ret.values ~= Variant(A[i]); } )) @@ -235,7 +451,7 @@ } /** - A run time attribute implementation that stores the attribute data in an + A run-time attribute implementation that stores the attribute data in an assiciative array of variants. */ class MetaVariantDictAttribute : MetaAttribute @@ -243,14 +459,14 @@ Variant[string] values; alias typeof(this) This; - private this() + private this(string name, AttributeOptions opts) { + super(name, opts); } - static This create(string category, AttributeOptions opts, A...)() + static This create(string name, AttributeOptions opts, A...)() { - auto ret = new This; - ret.construct!(category, opts)(); + auto ret = new This(name, opts); foreach(i, _; A) { static if (i % 2 == 0 && __traits(compiles, { ret.values[A[i]] = Variant(A[i + 1]); } )) @@ -260,33 +476,30 @@ } } -version (QtdUnittest) +version(QtdUnittest) unittest { - unittest + static void foo() {} + + static class C { - static void foo() {} + mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33); + mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute, + //"a", "33", // PHOBOS BUG: variant is unusable with AAs + "b", foo + //"c", 44 + ); + } - static class C - { - mixin InnerAttribute!("variantAttribute", MetaVariantAttribute, "22", foo, 33); - mixin InnerAttribute!("variantDictAttribute", MetaVariantDictAttribute, - //"a", "33", // PHOBOS BUG: variant is unusable with AAs - "b", foo - //"c", 44 - ); - } + auto attrs = meta!(C).attributes; + assert(attrs.length == 2); + auto attr = cast(MetaVariantAttribute)attrs[0]; - auto attrs = meta!(C).attributes; - assert(attrs.length == 2); - auto attr = cast(MetaVariantAttribute)attrs[0]; + assert(attr.name == "variantAttribute"); + assert(attr.values[0] == "22"); + assert(attr.values[1] == 33); - assert(attr.name == "variantAttribute"); - assert(attr.values[0] == "22"); - assert(attr.values[1] == 33); - - auto attr2 = cast(MetaVariantDictAttribute) attrs[1]; - assert(attr2.name == "variantDictAttribute"); - //assert(attr2.values["a"] == "33"); - //assert(attr2.values["c"] == 44); - } -} \ No newline at end of file + auto attr2 = cast(MetaVariantDictAttribute) attrs[1]; + assert(attr2.name == "variantDictAttribute"); + //assert(attr2.values["a"] == "33"); + //assert(attr2.values["c"] == 44); +}