示例#1
0
        public string GenerateSourceCode()
        {
            TextOut output = new TextOut();
            output.AppendLine("");
            output.AppendLine("// This source file was generated by hierarchy_test_util");
            output.AppendLine("");
            output.AppendLine("// incudes");
            output.AppendLine(@"#include <string>");
            output.AppendLine(@"#include <iostream>");
            output.AppendLine(@"#include <cstdlib>");
            output.AppendLine(@"#include ""..\sources\reflective.h""");
            output.AppendLine(@"");
            output.AppendLine(@"");

            output.AppendLine(" /******** Configuration ");
            output.AppendLine(" * hierarchy name: " + m_settings.HierarchyName);
            output.AppendLine(" * class count: " + m_settings.ClassCount.ToString() );
            output.AppendLine(" * derivation factor: " + m_settings.DerivationFactor.ToString());
            output.AppendLine(" * virtual table chance: " + ((int)(m_settings.VTableChance * 100)).ToString() + "%");
            output.AppendLine(" * virtual base chance: " + ((int)(m_settings.VBaseChance * 100)).ToString() + "%");
            output.AppendLine(" * allow multiple inheritance: " + m_settings.AllowMultipleInheritance.ToString() + "");
            output.AppendLine(" * most-derived-type function chance: " + ((int)(m_settings.MostDerivedTypeFuncChance * 100)).ToString() + "%");
            output.AppendLine(" * test count: " + m_settings.TestCount.ToString());
            output.AppendLine(" * emit type checks: " + m_settings.EmitTypeChecks.ToString());
            output.AppendLine(" * random seed: " + m_settings.RandomSeed.ToString());

            output.AppendLine(" ********/");

            output.AppendLine("namespace reflective");
            output.AppendLine("{");
            output.Tab();

            output.AppendLine("namespace details");
            output.AppendLine("{");
            output.Tab();

            output.AppendLine("namespace " + m_settings.HierarchyName);
            output.AppendLine("{");
            output.Tab();

            foreach ( ClassEntry classEntry in m_classes)
            {
                classEntry.WriteDefinition(output, m_settings.EmitTypeChecks);
            }

            output.Untab();
            output.AppendLine("}");

            output.Untab();
            output.AppendLine("}");

            output.AppendLine("");
            foreach (ClassEntry classEntry in m_classes)
            {
                classEntry.WriteReflection(output);
            }
            output.Untab();
            output.AppendLine("};");

            GenerateTest(output);

            return output.ToString();
        }
示例#2
0
        public void WriteReflection(TextOut i_output)
        {
            i_output.Append("void setup_type(TypeSetupContext<" + FullName + "> & i_context)");
            i_output.NewLine();
            i_output.AppendLine("{");
            i_output.Tab();
            i_output.AppendLine("using ThisClass = " + FullName + ";");

            // bases
            ClassEntry[] bases = m_bases.ToArray();
            int baseCount = bases.Length;

            if (baseCount > 0)
            {
                i_output.AppendLine("i_context.type()->set_base_types( {");
                i_output.Tab();

                for (int baseIndex = 0; baseIndex < baseCount; baseIndex++)
                {
                    ClassEntry baseClass = bases[baseIndex];
                    string term;
                    if (baseIndex + 1 < baseCount)
                        term = ",";
                    else
                        term = " });";
                    if( m_virtualBases.Contains( baseClass) )
                        i_output.AppendLine("BaseType::from_types_virtual<ThisClass, " + baseClass.FullName + ">()" + term);
                    else
                        i_output.AppendLine("BaseType::from_types<ThisClass, " + baseClass.FullName + ">()" + term);
                }
                i_output.Untab();
            }

            // gmdt function
            i_output.AppendLine("i_context.type()->set_most_derived_type_func(&ThisClass::static_get_type);");

            // test base_types container
            i_output.AppendLine("");
            i_output.AppendLine("// test base_types container");
            i_output.AppendLine("std::vector<const reflective::Type*> test_bases = {");
            for (int baseIndex = 0; baseIndex < baseCount; baseIndex++)
            {
                i_output.AppendLine("&reflective::get_naked_type<" + bases[baseIndex].FullName + ">(), ");
            }
            i_output.AppendLine("};");
            i_output.AppendLine("for( const auto & base : i_context.type()->base_types() )");
            i_output.AppendLine("{");
            i_output.Tab();
            i_output.AppendLine("auto it = reflective::Ext::find_if(test_bases, ");
            i_output.Tab();
            i_output.AppendLine("[&base] (const reflective::Type * i_s) { return i_s == base.base_type(); } );");
            i_output.Untab();
            i_output.AppendLine("REFLECTIVE_INTERNAL_ASSERT( it != test_bases.end() );");
            i_output.AppendLine("test_bases.erase(it);");
            i_output.Untab();
            i_output.AppendLine("}");
            i_output.AppendLine("REFLECTIVE_INTERNAL_ASSERT( test_bases.size() == 0 );");

            i_output.Untab();
            i_output.AppendLine("}");
        }
示例#3
0
        private void GenerateTest(TextOut i_output)
        {
            i_output.AppendLine("namespace reflective");
            i_output.AppendLine("{");
            i_output.Tab();

            if (m_settings.EmitTypeChecks)
            {
                foreach (ClassEntry currClass in m_classes)
                {
                    i_output.AppendLine("template <> inline void dbg_object_validate(const " + currClass.FullName + " & i_object)");
                    i_output.AppendLine("{");
                    i_output.Tab();
                    i_output.AppendLine("REFLECTIVE_INTERNAL_ASSERT(i_object.type_name == \"" + currClass.Name + "\");");
                    i_output.Untab();
                    i_output.AppendLine("}");
                }
            }

            i_output.AppendLine("namespace details");
            i_output.AppendLine("{");
            i_output.Tab();

            i_output.AppendLine("namespace " + m_settings.HierarchyName);
            i_output.AppendLine("{");
            i_output.Tab();

            i_output.AppendLine("struct Stats { int m_test_count = 0; int m_failed_cast_count = 0; };");
            i_output.AppendLine("");

            for (int i = 0; i < m_settings.TestCount; i++)
            {
                i_output.AppendLine("void test_" + m_settings.HierarchyName + "_" + i.ToString() + "(Stats & io_stats)");
                i_output.AppendLine("{");
                i_output.Tab();

                ClassEntry completeClassObj = RandClass();
                ClassEntry baseClass = completeClassObj.GetRandomBaseOrThis(m_rand);
                ClassEntry destClass = RandClass();

                i_output.AppendLine("// upcasting from " + completeClassObj.Name + " to " + baseClass.Name + ", and then dynamic casting to " + destClass.Name);

                // complete object
                i_output.AppendLine(completeClassObj.Name + " complete_object;");
                i_output.AppendLine(completeClassObj.Name + " * native_complete_ptr = &complete_object;");
                i_output.AppendLine("ObjPtr ref_complete_ptr = &complete_object;");

                // upcast
                i_output.AppendLine("");
                i_output.AppendLine(baseClass.Name + " * native_base_ptr = native_complete_ptr;");
                i_output.AppendLine("ObjPtr ref_base_ptr = ref_complete_ptr.upcast_to(get_type<" + baseClass.Name + ">());");
                i_output.AppendLine("REFLECTIVE_INTERNAL_ASSERT(" +
                    "native_base_ptr == static_cast<" + baseClass.Name + "*>( ref_base_ptr.object() ) );");
                i_output.AppendLine("reflective::dbg_object_validate(*ref_base_ptr.get_if_type_matches<" + baseClass.Name + ">());");

                // dynamic_cast
                i_output.AppendLine("");
                i_output.AppendLine(destClass.Name + " * native_dyn_ptr = " + "dynamic_cast<" + destClass.Name + "*>(native_base_ptr);");
                i_output.AppendLine("ObjPtr ref_dyn_ptr = ref_base_ptr.cast_to(get_type<" + destClass.Name + ">());");
                i_output.AppendLine("REFLECTIVE_INTERNAL_ASSERT( native_dyn_ptr == " +
                    "static_cast<" + destClass.Name + "*>( ref_dyn_ptr.object() ) );");
                i_output.AppendLine("if( !ref_dyn_ptr.empty() )");
                i_output.AppendLine("{");
                i_output.Tab();
                i_output.AppendLine("reflective::dbg_object_validate(*ref_dyn_ptr.get_if_type_matches<" + destClass.Name + ">());");
                i_output.Untab();
                i_output.AppendLine("}");

                i_output.AppendLine("");
                i_output.AppendLine("io_stats.m_test_count++;");
                i_output.AppendLine("if(native_dyn_ptr == nullptr)");
                i_output.Tab();
                i_output.AppendLine("io_stats.m_failed_cast_count++;");
                i_output.Untab();

                i_output.Untab();
                i_output.AppendLine("}");
            }

            i_output.AppendLine("void test_" + m_settings.HierarchyName + "()");
            i_output.AppendLine("{");
            i_output.Tab();

            i_output.AppendLine("Stats stats;");
            for (int i = 0; i < m_settings.TestCount; i++)
            {
                i_output.AppendLine("test_" + m_settings.HierarchyName + "_" + i.ToString() + "(stats);");
            }

            i_output.Untab();
            i_output.AppendLine("}");

            i_output.Untab();
            i_output.AppendLine("}");

            i_output.Untab();
            i_output.AppendLine("}");

            i_output.Untab();
            i_output.AppendLine("}");
        }
示例#4
0
        public void WriteDefinition(TextOut i_output, bool i_emitTypeChecks)
        {
            i_output.Append("class " + Name);

            bool first = true;
            foreach( ClassEntry baseEntry in m_bases )
            {
                if( first )
                {
                    i_output.Append( " : public " );
                }
                else
                {
                    i_output.Append(", public ");
                }
                if( m_virtualBases.Contains(baseEntry) )
                {
                    i_output.Append("virtual ");
                }
                i_output.Append(baseEntry.Name);
                first = false;
            }
            i_output.NewLine();
            i_output.AppendLine("{");
            i_output.Tab();

            i_output.AppendLine("public:");

            // vtable
            if (m_hasVTable)
            {
                i_output.AppendLine("virtual ~" + Name + "() {}");
                i_output.AppendLine("virtual int vfunct_" + Name + "() { return 42; }");
            }

            if (i_emitTypeChecks)
            {
                i_output.AppendLine("std::string type_name = \"" + Name + "\";");
            }

            if(m_hasMDTFunc)
            {
                i_output.AppendLine("virtual const reflective::Type & virtual_get_type() const");
                i_output.AppendLine("\t{ return reflective::get_naked_type<" +Name + ">(); }");
                i_output.AppendLine("");
                i_output.AppendLine("static const reflective::Type & static_get_type(const void * i_object)");
                i_output.AppendLine("\t{ return static_cast<const " + Name + " *>(i_object)->virtual_get_type(); }");
            }

            // properties
            foreach (ClassProperty prop in m_properties)
            {
                i_output.AppendLine(prop.Type + " " + prop.Name + ";" );
            }

            i_output.Untab();
            i_output.AppendLine("};");
        }