diff --git a/druntime/mak/COPY b/druntime/mak/COPY index 5fa84398d0..992a813e9d 100644 --- a/druntime/mak/COPY +++ b/druntime/mak/COPY @@ -15,6 +15,7 @@ COPY=\ $(IMPDIR)\core\cpuid.d \ $(IMPDIR)\core\demangle.d \ $(IMPDIR)\core\exception.d \ + $(IMPDIR)\core\factory.d \ $(IMPDIR)\core\int128.d \ $(IMPDIR)\core\lifetime.d \ $(IMPDIR)\core\math.d \ diff --git a/druntime/mak/DOCS b/druntime/mak/DOCS index 0093bd2e9f..1697fd80f3 100644 --- a/druntime/mak/DOCS +++ b/druntime/mak/DOCS @@ -12,6 +12,7 @@ DOCS=\ $(DOCDIR)\core_attribute.html \ $(DOCDIR)\core_cpuid.html \ $(DOCDIR)\core_demangle.html \ + $(DOCDIR)\core_factory.html \ $(DOCDIR)\core_lifetime.html \ $(DOCDIR)\core_memory.html \ $(DOCDIR)\core_runtime.html \ diff --git a/druntime/mak/SRCS b/druntime/mak/SRCS index 126567cd76..c06ba6f96a 100644 --- a/druntime/mak/SRCS +++ b/druntime/mak/SRCS @@ -9,6 +9,7 @@ SRCS=\ src\core\cpuid.d \ src\core\demangle.d \ src\core\exception.d \ + src\core\factory.d \ src\core\int128.d \ src\core\lifetime.d \ src\core\math.d \ diff --git a/druntime/src/core/factory.d b/druntime/src/core/factory.d new file mode 100644 index 0000000000..f45a04ea91 --- /dev/null +++ b/druntime/src/core/factory.d @@ -0,0 +1,68 @@ +/* Create classes from their modules and names. + * + * Copyright: Copyright (C) D Language Foundation 2023 + * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0) + * Authors: Walter Bright, Steven Schveighoffer + * Source: $(DRUNTIMESRC core/_factory.d) + */ + +module core.factory; + +/** + * Create instance of class specified by the module symbol and a string + * representing the name of the class. + * The class must either have no constructors or have + * a default constructor. + * Params: + * mod = symbol representing the module that the class is in + * classname = string representing the name of the class + * Returns: + * null if failed + * Example: + * --- + * module foo.bar; + * + * class C + * { + * this() { x = 10; } + * int x; + * } + * + * void main() + * { + * auto c = cast(C)factory!(foo.bar)("C"); + * assert(c !is null && c.x == 10); + * } + * --- + */ +Object factory(alias mod)(string classname) +{ + foreach(cl; _getModuleClasses!mod) + { + if (cl.stringof == classname) + return cl.classinfo.create(); + } + return null; +} + +@system unittest +{ + Object valid_obj = factory!object("Object"); + Object invalid_obj = factory!object("__this_class_doesnt_exist__"); + + assert(valid_obj !is null); + assert(invalid_obj is null); +} + +/************************************** + * Retrieve as a tuple all the types of the top level classes in the module mod. + */ +private template _getModuleClasses(alias mod) { + alias result = _AliasSeq!(); + static foreach(m; __traits(allMembers, mod)) + static if(is(__traits(getMember, mod, m) == class)) + result = _AliasSeq!(result, __traits(getMember, mod, m)); + alias _getModuleClasses = result; +} + +private template _AliasSeq(TList...) { alias _AliasSeq = TList; }