#include "pch.h" class NameSpaceInfo : public INameSpaceInfo { private: INameSpace* m_pns; ZString m_str; public: NameSpaceInfo(INameSpace* pns, const ZString& str) : m_pns(pns), m_str(str) { } INameSpace* GetNameSpace() { return m_pns; } const ZString& GetName() { return m_str; } }; TRef CreateNameSpaceInfo(INameSpace* pns, const ZString& str) { return new NameSpaceInfo(pns, str); } ////////////////////////////////////////////////////////////////////////////// // // NameSpace // ////////////////////////////////////////////////////////////////////////////// class NameSpaceImpl : public INameSpace { private: ////////////////////////////////////////////////////////////////////////////// // // types // ////////////////////////////////////////////////////////////////////////////// class SymbolData { public: ZString m_strName; TRef m_pobject; SymbolData(){} SymbolData(const ZString& strName, TRef pobject) : m_strName(strName), m_pobject(pobject) { } SymbolData(const SymbolData& data) : m_strName(data.m_strName), m_pobject(data.m_pobject) { } }; typedef TList SymbolList; class TypeData { public: ZString m_strName; TRef m_ptype; }; typedef TList TypeList; ////////////////////////////////////////////////////////////////////////////// // // data members // ////////////////////////////////////////////////////////////////////////////// ZString m_strName; INameSpaceList m_listParents; SymbolList m_listSymbols; TypeList m_listTypes; ////////////////////////////////////////////////////////////////////////////// // // methods // ////////////////////////////////////////////////////////////////////////////// public: NameSpaceImpl(const ZString& strName) : m_strName(strName) { } NameSpaceImpl(const ZString& strName, INameSpace* pnsParent) : m_strName(strName) { m_listParents.PushFront(pnsParent); } NameSpaceImpl(const ZString& strName, INameSpaceList& parents) : m_strName(strName), m_listParents(parents) { // !!! should make an ordered list of parents so we don't search // any parent more than once. } ////////////////////////////////////////////////////////////////////////////// // // INameSpace methods // ////////////////////////////////////////////////////////////////////////////// const ZString& GetName() { return m_strName; } void AddMember(const ZString& strName, IObject* pobject) { ZAssert(FindMemberLocal(strName) == NULL); m_listSymbols.PushEnd(SymbolData(strName, pobject)); // // !!! this is a total hack, only do this on Debug builds since it // requires dynamic casting. MDLC is always built debug so it's // ok. // #if defined(_DEBUG) && !defined(DREAMCAST) Value* pvalue = dynamic_cast(pobject); if (pvalue != NULL) { pvalue->SetNameSpaceInfo(CreateNameSpaceInfo(this, strName)); } #endif } IObject* FindMemberLocal(const ZString& str) { SymbolList::Iterator iter(m_listSymbols); while (!iter.End()) { const SymbolData& data = iter.Value(); if (data.m_strName == str) { return data.m_pobject; } iter.Next(); } return NULL; } IObject* FindMemberAndNameSpace(const ZString& str, INameSpace*& pns) { IObject* pobject = FindMemberLocal(str); if (pobject != NULL) { pns = this; return pobject; } INameSpaceList::Iterator iter(m_listParents); while (!iter.End()) { pobject = iter.Value()->FindMemberAndNameSpace(str, pns); if (pobject != NULL) { return pobject; } iter.Next(); } return NULL; } IObject* FindMember(const ZString& str) { INameSpace* pns; return FindMemberAndNameSpace(str, pns); } ////////////////////////////////////////////////////////////////////////////// // // Types // ////////////////////////////////////////////////////////////////////////////// void AddType(const ZString& strName, MDLType* ptype) { ZAssert(FindTypeLocal(strName) == NULL); m_listTypes.PushEnd(); m_listTypes.GetEnd().m_strName = strName; m_listTypes.GetEnd().m_ptype = ptype; } MDLType* FindTypeLocal(const ZString& strName) { TypeList::Iterator iter(m_listTypes); while (!iter.End()) { const TypeData& data = iter.Value(); if (data.m_strName == strName) { return data.m_ptype; } iter.Next(); } return NULL; } MDLType* FindTypeAndNameSpace(const ZString& str, NameSpaceImpl*& pns) { MDLType* ptype = FindTypeLocal(str); if (ptype != NULL) { pns = this; return ptype; } INameSpaceList::Iterator iter(m_listParents); while (!iter.End()) { NameSpaceImpl* pnsImpl; CastTo(pnsImpl, iter.Value()); ptype = pnsImpl->FindTypeAndNameSpace(str, pns); if (ptype != NULL) { return ptype; } iter.Next(); } return NULL; } MDLType* FindType(const ZString& strName) { NameSpaceImpl* pns; return FindTypeAndNameSpace(strName, pns); } void WriteTypeHeader(ZFile* pfile) { TypeList::Iterator iter(m_listTypes); while (!iter.End()) { const TypeData& data = iter.Value(); iter.Next(); if (data.m_ptype->IsStruct()) { pfile->Write(GetStructHeader(data.m_ptype, data.m_strName)); if (!iter.End()) { pfile->Write(ZString("\n")); } } } } ////////////////////////////////////////////////////////////////////////////// // // Binary File Writer // ////////////////////////////////////////////////////////////////////////////// class MDLBinaryFile : public IMDLBinaryFile { private: class ImportData { public: DWORD m_indexNameSpaceTable; ZString m_str; }; TVector > m_pnss; TVector m_importDatas; TRef m_pns; TRef m_pfile; public: MDLBinaryFile(NameSpaceImpl* pns, ZFile* pfile) : m_pns(pns), m_pfile(pfile) { } int FindImport(const ZString& str) { int count = m_importDatas.GetCount(); for (int index = 0; index < count; index++) { if (m_importDatas[index].m_str == str) { return index; } } return -1; } void AddImport(const ZString& str, INameSpace* pns) { int count = m_pnss.GetCount(); for (int index = 0; index < count; index++) { if (m_pnss[index] == pns) { break; } } // // Do we need to add a new namespace to the namespace import list? // if (index == count) { m_pnss.PushEnd(pns); } // // Add the new import symbol // m_importDatas.PushEnd(); ImportData& data = m_importDatas.GetEnd(); data.m_indexNameSpaceTable = index; data.m_str = str; } void AddImport(const ZString& str) { int index = FindImport(str); if (index == -1) { INameSpace* pns; IObject* pobject = m_pns->FindMemberAndNameSpace(str, pns); ZAssert(pobject != NULL); if (pns == m_pns) { return; } AddImport(str, pns); } } // // return true if this is really an import // or false if it's in our own namespace. // bool AddImport(INameSpaceInfo* pnsInfo) { ZString str = pnsInfo->GetName(); int index = FindImport(pnsInfo->GetName()); if (index == -1) { // // Didn't find it search local // IObject* pobject = m_pns->FindMemberLocal(pnsInfo->GetName()); if (pobject == NULL) { AddImport(str, pnsInfo->GetNameSpace()); return true; } return false; } return true; } void WriteString(const ZString& str) { m_pfile->Write(ObjectString); m_pfile->WriteAlignedString(str); } void WriteReference(const ZString& str) { int index = FindImport(str); if (index == -1) { index = 0; SymbolList::Iterator iter(m_pns->m_listSymbols); while (!iter.End()) { if (str == iter.Value().m_strName) { m_pfile->Write(ObjectReference); m_pfile->Write(index); return; } index++; iter.Next(); } ZError("WriteReference: can't find " + str); } else { m_pfile->Write(ObjectImport); m_pfile->Write(index); } } void WriteApply() { m_pfile->Write(ObjectApply); } ZFile* WriteBinary() { m_pfile->Write(ObjectBinary); return m_pfile; } void WriteList(DWORD count) { m_pfile->Write(ObjectList); m_pfile->Write(count); } void WriteNumber(float value) { m_pfile->Write(ObjectFloat); m_pfile->Write(value); } void WriteBoolean(bool value) { if (value) { m_pfile->Write(ObjectTrue); } else { m_pfile->Write(ObjectFalse); } } void WritePair() { m_pfile->Write(ObjectPair); } void WriteEnd() { m_pfile->Write(ObjectEnd); } void CreateImportTable() { m_importDatas.SetCount(0); SymbolList::Iterator iter(m_pns->m_listSymbols); DWORD index = 0; while (!iter.End()) { Value* pvalue; CastTo(pvalue, iter.Value().m_pobject); pvalue->FillImportTable(this); iter.Next(); } } void Write() { CreateImportTable(); // // write out the header // m_pfile->Write(MDLMagic ); m_pfile->Write(MDLVersion ); m_pfile->Write(m_pnss.GetCount() ); // imported libraries m_pfile->Write(m_importDatas.GetCount() ); // imported symbols m_pfile->Write(m_pns->m_listSymbols.GetCount()); // exported symbols m_pfile->Write(0 ); // other defined objects // // write out used libraries // { int count = m_pnss.GetCount(); for (int index = 0; index < count; index++) { const ZString& str = m_pnss[index]->GetName(); m_pfile->WriteAlignedString(str); } } // // write out imported symbols // { int count = m_importDatas.GetCount(); for (int index = 0; index < count; index++) { const ImportData& data = m_importDatas[index]; m_pfile->Write(data.m_indexNameSpaceTable); m_pfile->WriteAlignedString(data.m_str); } } // // write out exported symbols // { SymbolList::Iterator iter(m_pns->m_listSymbols); while (!iter.End()) { const ZString& str = iter.Value().m_strName; m_pfile->WriteAlignedString(str); iter.Next(); } } // // write out definitions // { SymbolList::Iterator iter(m_pns->m_listSymbols); DWORD index = 0; while (!iter.End()) { Value* pvalue; CastTo(pvalue, iter.Value().m_pobject); m_pfile->Write(index); pvalue->Write(this); m_pfile->Write(ObjectEnd); index++; iter.Next(); } } } }; friend class MDLBinaryFile; void WriteToBinaryFile(ZFile* pfile) { TRef pmdlFile = new MDLBinaryFile(this, pfile); pmdlFile->Write(); } ////////////////////////////////////////////////////////////////////////////// // // Functions for writing to a text file // ////////////////////////////////////////////////////////////////////////////// void WriteToTextFile(int indent, ZFile* pfile) { // // write out used libraries // { INameSpaceList::Iterator iter(m_listParents); while (!iter.End()) { INameSpace* pns = iter.Value(); pfile->Write( Value::Indent(indent ) + "use \"" + pns->GetName() + "\";\n" ); iter.Next(); } if (!m_listParents.IsEmpty()) { pfile->Write("\n"); } } // // write out definitions // { SymbolList::Iterator iter(m_listSymbols); while (!iter.End()) { const SymbolData& data = iter.Value(); Value* pvalue; CastTo(pvalue, (IObject*)data.m_pobject); pfile->Write( Value::Indent(indent ) + data.m_strName + " = \n" + Value::Indent(indent + 1) + pvalue->GetString(indent + 1) + ";\n\n" ); iter.Next(); } } } }; ////////////////////////////////////////////////////////////////////////////// // // Constructors // ////////////////////////////////////////////////////////////////////////////// TRef CreateNameSpace(const ZString& strName) { return new NameSpaceImpl(strName); } TRef CreateNameSpace(const ZString& strName, INameSpace* pnsParent) { return new NameSpaceImpl(strName, pnsParent); } TRef CreateNameSpace(const ZString& strName, INameSpaceList& parents) { return new NameSpaceImpl(strName, parents); }