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(); }
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("}"); }
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("}"); }
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("};"); }