1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-24 18:48:01 +02:00

Show comptime emits as embedded sourceviews

This commit is contained in:
Brian Fiete 2022-04-16 06:27:54 -07:00
parent ee27f6fd02
commit 4d1e14a1c3
65 changed files with 3360 additions and 633 deletions

View file

@ -5,14 +5,18 @@
#include "DebugTarget.h"
#include "DebugManager.h"
#include "DWARFInfo.h"
#include "BeefySysLib/Util/PerfTimer.h"
#include "BeefySysLib/Util/Dictionary.h"
#include "BeefySysLib/Util/BeefPerf.h"
#include "BeefySysLib/util/PerfTimer.h"
#include "BeefySysLib/util/Dictionary.h"
#include "BeefySysLib/util/BeefPerf.h"
#include "BeefySysLib/util/BeefPerf.h"
#include "BeefySysLib/util/ZipFile.h"
#include "BeefySysLib/util/Hash.h"
#include "BeefySysLib/platform/PlatformHelper.h"
#include "WinDebugger.h"
#include "MiniDumpDebugger.h"
#include "Linker/BlHash.h"
#include "Backend/BeLibManger.h"
#include "Compiler/BfUtil.h"
#include <shlobj.h>
#include "BeefySysLib/util/AllocDebug.h"
@ -262,6 +266,7 @@ COFF::COFF(DebugTarget* debugTarget) : DbgModule(debugTarget)
mPrevScanName = NULL;
mProcSymCount = 0;
mCvSrcSrvStream = -1;
mCvEmitStream = -1;
mIsFastLink = false;
mHotThunkCurAddr = 0;
mHotThunkDataLeft = 0;
@ -270,6 +275,7 @@ COFF::COFF(DebugTarget* debugTarget) : DbgModule(debugTarget)
mDbgSymRequest = NULL;
mWantsAutoLoadDebugInfo = false;
mPDBLoaded = false;
mEmitSourceFile = NULL;
}
COFF::~COFF()
@ -3605,8 +3611,17 @@ CvCompileUnit* COFF::ParseCompileUnit(CvModuleInfo* moduleInfo, CvCompileUnit* c
GET_INTO(uint, fileTableOfs);
const char* fileName = mStringTable.mStrTable + fileTableOfs;
if ((fileName[0] == '\\') && (fileName[1] == '$'))
fileName++;
DbgSrcFile* srcFile = NULL;
if ((fileName[0] == '/') || (fileName[0] == '\\') ||
if (fileName[0] == '$')
{
srcFile = AddSrcFile(compileUnit, fileName);
}
else if ((fileName[0] == '/') || (fileName[0] == '\\') ||
((fileName[0] != 0) && (fileName[1] == ':')))
{
srcFile = AddSrcFile(compileUnit, fileName);
@ -4642,6 +4657,8 @@ void COFF::ScanCompileUnit(int compileUnitId)
else
{
const char* fileName = mStringTable.mStrTable + fileTableOfs;
if ((fileName[0] == '\\') && (fileName[1] == '$'))
fileName++;
srcFile = AddSrcFile(NULL, fileName);
mSrcFileDeferredRefs.Add(srcFile);
*srcFilePtr = srcFile;
@ -4967,6 +4984,8 @@ bool COFF::CvParseHeader(uint8 wantGuid[16], int32 wantAge)
mStringTable.mStream = streamNum;
if (strcmp(tableName, "srcsrv") == 0)
mCvSrcSrvStream = streamNum;
if (strcmp(tableName, "emit") == 0)
mCvEmitStream = streamNum;
/*if (tableIdx == nameTableIdx)
{
@ -6095,6 +6114,9 @@ void COFF::ClosePDB()
delete kv.mValue;
mHotLibMap.Clear();
mHotLibSymMap.Clear();
delete mEmitSourceFile;
mEmitSourceFile = NULL;
}
bool COFF::LoadPDB(const String& pdbPath, uint8 wantGuid[16], int32 wantAge)
@ -6669,6 +6691,60 @@ String COFF::GetOldSourceCommand(const StringImpl& path)
return "";
}
bool COFF::GetEmitSource(const StringImpl& filePath, String& outText)
{
if (!filePath.StartsWith("$Emit"))
return false;
if (mEmitSourceFile == NULL)
{
mEmitSourceFile = new ZipFile();
String zipPath = mPDBPath;
int dotPos = zipPath.LastIndexOf('.');
zipPath.RemoveToEnd(dotPos);
zipPath.Append("__emit.zip");
if (!mEmitSourceFile->Open(zipPath))
{
if (mCvEmitStream == -1)
return "";
int outSize;
uint8* data = CvReadStream(mCvEmitStream, &outSize);
FileStream fileStream;
fileStream.Open(zipPath, "wb");
fileStream.Write(data, outSize);
fileStream.Close();
delete data;
mEmitSourceFile->Open(zipPath);
}
}
if (mEmitSourceFile->IsOpen())
{
String usePath = filePath;
if (usePath.StartsWith("$Emit"))
{
int dollarPos = usePath.IndexOf('$', 1);
usePath.Remove(0, dollarPos + 1);
}
usePath = EncodeFileName(usePath);
usePath.Append(".bf");
Array<uint8> data;
if (mEmitSourceFile->Get(usePath, data))
{
outText.Insert(outText.mLength, (char*)data.mVals, data.mSize);
return true;
}
}
return false;
}
bool COFF::HasPendingDebugInfo()
{
if (mDbgSymRequest == NULL)
@ -7016,7 +7092,7 @@ addr_target COFF::LocateSymbol(const StringImpl& name)
delete dbgModule;
return 0;
}
mDebugger->mDebugTarget->mDbgModules.push_back(dbgModule);
mDebugger->mDebugTarget->AddDbgModule(dbgModule);
auto symbolEntry = mSymbolNameMap.Find(name.c_str());
if (symbolEntry != NULL)

View file

@ -13,6 +13,7 @@ namespace Beefy
class DataStream;
class MemStream;
class SafeMemStream;
class ZipFile;
}
struct CV_LVAR_ADDR_RANGE;
@ -214,6 +215,7 @@ public:
};
public:
ZipFile* mEmitSourceFile;
uint8 mWantPDBGuid[16];
int mWantAge;
@ -262,6 +264,7 @@ public:
int mCvPublicSymbolInfoStream;
int mCvSymbolRecordStream;
int mCvSrcSrvStream;
int mCvEmitStream;
int mCvNewFPOStream;
Array<CvModuleInfo*> mCvModuleInfo;
Dictionary<int, DbgSrcFile*> mCVSrcFileRefCache;
@ -320,6 +323,7 @@ public:
virtual intptr EvaluateLocation(DbgSubprogram* dwSubprogram, const uint8* locData, int locDataLen, WdStackFrame* stackFrame, DbgAddrType* outAddrType, DbgEvalLocFlags flags = DbgEvalLocFlag_None) override;
virtual bool CanGetOldSource() override;
virtual String GetOldSourceCommand(const StringImpl& path) override;
virtual bool GetEmitSource(const StringImpl& filePath, String& outText) override;
virtual bool HasPendingDebugInfo() override;
virtual void PreCacheImage() override;
virtual void PreCacheDebugInfo() override;

View file

@ -276,10 +276,15 @@ int BfAutoComplete::GetCursorIdx(BfAstNode* node)
if (node == NULL)
return -1;
if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// return -1;
if (node->IsTemporary())
return false;
auto bfParser = node->GetSourceData()->ToParser();
if (bfParser == NULL)
return -1;
auto bfParser = node->GetSourceData()->ToParser();
if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
return -1;
@ -291,10 +296,14 @@ bool BfAutoComplete::IsAutocompleteNode(BfAstNode* node, int lengthAdd, int star
if (node == NULL)
return false;
if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
return false;
// if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// return false;
if (node->IsTemporary())
return false;
auto bfParser = node->GetSourceData()->ToParser();
if (bfParser == NULL)
return false;
if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
return false;
@ -313,10 +322,14 @@ bool BfAutoComplete::IsAutocompleteNode(BfAstNode* startNode, BfAstNode* endNode
if ((startNode == NULL) || (endNode == NULL))
return false;
if (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser))
return false;
// if (!startNode->IsFromParser(mCompiler->mResolvePassData->mParser))
// return false;
if (startNode->IsTemporary())
return false;
auto bfParser = startNode->GetSourceData()->ToParser();
if (bfParser == NULL)
return false;
if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
return false;
@ -335,10 +348,14 @@ bool BfAutoComplete::IsAutocompleteLineNode(BfAstNode* node)
if (node == NULL)
return false;
if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
return false;
// if (!node->IsFromParser(mCompiler->mResolvePassData->mParser))
// return false;
if (node->IsTemporary())
return false;
auto bfParser = node->GetSourceData()->ToParser();
if (bfParser == NULL)
return false;
if ((bfParser->mParserFlags & ParserFlag_Autocomplete) == 0)
return false;
@ -414,7 +431,7 @@ BfTypedValue BfAutoComplete::LookupTypeRefOrIdentifier(BfAstNode* node, bool* is
{
// This keeps the classifier from colorizing properties - this causes 'flashing' when we go back over this with a resolve pass
// that wouldn't catch this
SetAndRestoreValue<BfSourceClassifier*> prevClassifier(mModule->mCompiler->mResolvePassData->mSourceClassifier, NULL);
SetAndRestoreValue<bool> prevClassifier(mModule->mCompiler->mResolvePassData->mIsClassifying, false);
BfExprEvaluator exprEvaluator(mModule);
auto fieldResult = exprEvaluator.LookupField(qualifiedTypeRef->mRight, leftValue, rightNamedTypeRef->mNameNode->ToString());
@ -1271,11 +1288,17 @@ BfProject* BfAutoComplete::GetActiveProject()
auto activeTypeDef = mModule->GetActiveTypeDef();
if (activeTypeDef != NULL)
bfProject = activeTypeDef->mProject;
else
bfProject = mCompiler->mResolvePassData->mParser->mProject;
else if (!mCompiler->mResolvePassData->mParsers.IsEmpty())
bfProject = mCompiler->mResolvePassData->mParsers[0]->mProject;
return bfProject;
}
bool BfAutoComplete::WantsEntries()
{
return (mResolveType == BfResolveType_Autocomplete) ||
(mResolveType == BfResolveType_Autocomplete_HighPri);
}
void BfAutoComplete::AddTopLevelNamespaces(BfAstNode* identifierNode)
{
String filter;
@ -1419,8 +1442,8 @@ void BfAutoComplete::AddTopLevelTypes(BfAstNode* identifierNode, bool onlyAttrib
else
{
BfProject* curProject = NULL;
if (mModule->mCompiler->mResolvePassData->mParser != NULL)
curProject = mModule->mCompiler->mResolvePassData->mParser->mProject;
if (!mModule->mCompiler->mResolvePassData->mParsers.IsEmpty())
curProject = mModule->mCompiler->mResolvePassData->mParsers[0]->mProject;
String prevName;
for (auto typeDef : mModule->mSystem->mTypeDefs)
@ -1468,14 +1491,6 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
}
}
}
//bool isUsingDirective = false;
//bool isUsingDirective = (identifierNode != NULL) && (identifierNode->mParent != NULL) && (identifierNode->mParent->IsA<BfUsingDirective>());
if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
{
//TODO: Color around dots
//mCompiler->mResolvePassData->mSourceClassifier->SetElementType(identifierNode, BfSourceElementType_Namespace);
}
if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(identifierNode))
{
@ -1483,10 +1498,6 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
return;
}
//bool isInExpression = true;
// if (identifierNode != NULL)
// isInExpression = IsInExpression(identifierNode);
AddTopLevelNamespaces(identifierNode);
if (isUsingDirective)
return; // Only do namespaces
@ -1759,6 +1770,9 @@ String BfAutoComplete::GetFilter(BfAstNode* node)
bool BfAutoComplete::CheckMemberReference(BfAstNode* target, BfAstNode* dotToken, BfAstNode* memberName, bool onlyShowTypes, BfType* expectingType, bool isUsingDirective, bool onlyAttribute)
{
if (!WantsEntries())
return false;
BfAttributedIdentifierNode* attrIdentifier = NULL;
bool isAutocompletingName = false;
if ((attrIdentifier = BfNodeDynCast<BfAttributedIdentifierNode>(memberName)))

View file

@ -208,6 +208,7 @@ public:
public:
BfProject* GetActiveProject();
bool WantsEntries();
bool CheckProtection(BfProtection protection, BfTypeDef* typeDef, bool allowProtected, bool allowPrivate);
String GetFilter(BfAstNode* node);
const char* GetTypeName(BfType* type);

View file

@ -27,6 +27,7 @@
#include "BfAutoComplete.h"
#include "BfResolvePass.h"
#include "BeefySysLib/util/BeefPerf.h"
#include "BeefySysLib/util/ZipFile.h"
#include "../LLVMUtils.h"
#include "BfNamespaceVisitor.h"
#include "CeMachine.h"
@ -2276,7 +2277,7 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork)
bool madeFullPass = true;
if (mCanceling)
madeFullPass = false;
if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
if ((mResolvePassData != NULL) && (!mResolvePassData->mParsers.IsEmpty()))
madeFullPass = false;
SetAndRestoreValue<bool> prevAssertOnPopulateType(mContext->mAssertOnPopulateType, deleteUnusued && madeFullPass);
@ -3736,19 +3737,19 @@ void BfCompiler::VisitAutocompleteExteriorIdentifiers()
if (mResolvePassData->mAutoComplete != NULL)
mResolvePassData->mAutoComplete->CheckIdentifier(checkIdentifier, false, isUsingDirective);
if ((checkIdentifier->IsFromParser(mResolvePassData->mParser)) && (mResolvePassData->mSourceClassifier != NULL))
if (auto sourceClassifier = mResolvePassData->GetSourceClassifier(checkIdentifier))
{
if (isUsingDirective)
{
while (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkIdentifier))
{
mResolvePassData->mSourceClassifier->SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace);
sourceClassifier->SetElementType(qualifiedNameNode->mRight, BfSourceElementType_Namespace);
checkIdentifier = qualifiedNameNode->mLeft;
}
if (checkIdentifier != NULL)
mResolvePassData->mSourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
sourceClassifier->SetElementType(checkIdentifier, BfSourceElementType_Namespace);
}
}
}
@ -3903,9 +3904,10 @@ void BfCompiler::VisitSourceExteriorNodes()
parser->mParserData->mExteriorNodesCheckIdx = mSystem->mTypeMapVersion;
};
if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL))
if (mResolvePassData != NULL)
{
_CheckParser(mResolvePassData->mParser);
for (auto parser : mResolvePassData->mParsers)
_CheckParser(parser);
}
else
{
@ -3936,18 +3938,21 @@ void BfCompiler::ProcessAutocompleteTempType()
if (autoComplete->mResolveType == BfResolveType_GetNavigationData)
{
for (auto node : mResolvePassData->mParser->mSidechannelRootNode->mChildArr)
for (auto parser : mResolvePassData->mParsers)
{
if (auto preprocNode = BfNodeDynCast<BfPreprocessorNode>(node))
for (auto node : parser->mSidechannelRootNode->mChildArr)
{
if (preprocNode->mCommand->Equals("region"))
if (auto preprocNode = BfNodeDynCast<BfPreprocessorNode>(node))
{
if (!autoCompleteResultString.empty())
autoCompleteResultString += "\n";
autoCompleteResultString += "#";
preprocNode->mArgument->ToString(autoCompleteResultString);
mContext->mScratchModule->UpdateSrcPos(preprocNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
autoCompleteResultString += StrFormat("\tregion\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
if (preprocNode->mCommand->Equals("region"))
{
if (!autoCompleteResultString.empty())
autoCompleteResultString += "\n";
autoCompleteResultString += "#";
preprocNode->mArgument->ToString(autoCompleteResultString);
mContext->mScratchModule->UpdateSrcPos(preprocNode, (BfSrcPosFlags)(BfSrcPosFlag_NoSetDebugLoc | BfSrcPosFlag_Force));
autoCompleteResultString += StrFormat("\tregion\t%d\t%d", module->mCurFilePosition.mCurLine, module->mCurFilePosition.mCurColumn);
}
}
}
}
@ -4041,7 +4046,7 @@ void BfCompiler::ProcessAutocompleteTempType()
if (autoComplete->mResolveType == BfResolveType_GetCurrentLocation)
{
for (auto tempTypeDef : mResolvePassData->mAutoCompleteTempTypes)
{
{
String typeName = tempTypeDef->mNamespace.ToString();
if (!typeName.empty())
typeName += ".";
@ -4049,16 +4054,21 @@ void BfCompiler::ProcessAutocompleteTempType()
autoCompleteResultString = typeName;
int cursorPos = mResolvePassData->mParser->mCursorIdx;
for (auto methodDef : tempTypeDef->mMethods)
{
BfAstNode* defNode = methodDef->mMethodDeclaration;
if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
defNode = propertyDeclaration;
if (defNode == NULL)
continue;
auto parser = defNode->GetParser();
if ((parser == NULL) || (parser->mCursorIdx == -1))
continue;
if ((defNode != NULL) &&
(defNode->Contains(cursorPos)))
(defNode->Contains(parser->mCursorIdx)))
{
String methodText = methodDef->ToString();
if (typeName != "@")
@ -4070,6 +4080,53 @@ void BfCompiler::ProcessAutocompleteTempType()
}
}
if (mResolvePassData->mAutoCompleteTempTypes.IsEmpty())
{
for (auto& kv : mResolvePassData->mEmitEmbedEntries)
{
if (kv.mValue.mCursorIdx < 0)
continue;
String typeName = kv.mKey;
auto type = GetType(typeName);
if (type == NULL)
continue;
auto typeInst = type->ToTypeInstance();
if (typeInst == NULL)
continue;
if (mResolvePassData->mParsers.IsEmpty())
break;
autoCompleteResultString = mContext->mScratchModule->TypeToString(typeInst);
for (auto methodDef : typeInst->mTypeDef->mMethods)
{
BfAstNode* defNode = methodDef->mMethodDeclaration;
if (auto propertyDeclaration = methodDef->GetPropertyDeclaration())
defNode = propertyDeclaration;
if (defNode == NULL)
continue;
if ((defNode != NULL) &&
(defNode->Contains(kv.mValue.mCursorIdx)))
{
auto defParser = defNode->GetParser();
if (defParser == NULL)
continue;
if (!defParser->mIsEmitted)
continue;
autoCompleteResultString += ".";
autoCompleteResultString += methodDef->ToString();
break;
}
}
}
}
module->CleanupFileInstances();
return;
}
@ -4094,59 +4151,58 @@ void BfCompiler::ProcessAutocompleteTempType()
BfAstNode* conflictStart = NULL;
BfAstNode* conflictSplit = NULL;
auto src = mResolvePassData->mParser->mSrc;
for (int checkIdx = 0; checkIdx < (int)mResolvePassData->mParser->mSidechannelRootNode->mChildArr.mSize; checkIdx++)
for (auto parser : mResolvePassData->mParsers)
{
auto sideNode = mResolvePassData->mParser->mSidechannelRootNode->mChildArr.mVals[checkIdx];
if (autoComplete->CheckFixit(sideNode))
auto src = parser->mSrc;
for (int checkIdx = 0; checkIdx < (int)parser->mSidechannelRootNode->mChildArr.mSize; checkIdx++)
{
if (src[sideNode->mSrcStart] == '<')
auto sideNode = parser->mSidechannelRootNode->mChildArr.mVals[checkIdx];
if (autoComplete->CheckFixit(sideNode))
{
conflictStart = sideNode;
conflictSplit = NULL;
}
}
else
{
if (src[sideNode->mSrcStart] == '<')
{
conflictStart = NULL;
conflictSplit = NULL;
}
else if (src[sideNode->mSrcStart] == '=')
{
if (conflictStart != NULL)
conflictSplit = sideNode;
}
else if (src[sideNode->mSrcStart] == '>')
{
if (conflictSplit != NULL)
if (src[sideNode->mSrcStart] == '<')
{
conflictStart = sideNode;
conflictSplit = NULL;
}
}
else
{
if (src[sideNode->mSrcStart] == '<')
{
autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept First\tdelete|%s-%d|\x01""delete|%s-%d|",
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictSplit->mSrcStart).c_str(), sideNode->mSrcEnd - conflictSplit->mSrcStart + 1,
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Second\tdelete|%s-%d|\x01""delete|%s-%d|",
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Both\tdelete|%s-%d|\x01""delete|%s-%d|\x01""delete|%s-%d|",
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictSplit->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictSplit->mSrcStart + 1,
autoComplete->FixitGetLocation(mResolvePassData->mParser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
conflictStart = NULL;
conflictSplit = NULL;
}
else if (src[sideNode->mSrcStart] == '=')
{
if (conflictStart != NULL)
conflictSplit = sideNode;
}
else if (src[sideNode->mSrcStart] == '>')
{
if (conflictSplit != NULL)
{
autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept First\tdelete|%s-%d|\x01""delete|%s-%d|",
autoComplete->FixitGetLocation(parser->mParserData, conflictSplit->mSrcStart).c_str(), sideNode->mSrcEnd - conflictSplit->mSrcStart + 1,
autoComplete->FixitGetLocation(parser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Second\tdelete|%s-%d|\x01""delete|%s-%d|",
autoComplete->FixitGetLocation(parser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
autoComplete->FixitGetLocation(parser->mParserData, conflictStart->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
autoComplete->AddEntry(AutoCompleteEntry("fixit", StrFormat("Accept Both\tdelete|%s-%d|\x01""delete|%s-%d|\x01""delete|%s-%d|",
autoComplete->FixitGetLocation(parser->mParserData, sideNode->mSrcStart).c_str(), sideNode->mSrcEnd - sideNode->mSrcStart + 1,
autoComplete->FixitGetLocation(parser->mParserData, conflictSplit->mSrcStart).c_str(), conflictSplit->mSrcEnd - conflictSplit->mSrcStart + 1,
autoComplete->FixitGetLocation(parser->mParserData, conflictStart->mSrcStart).c_str(), conflictStart->mSrcEnd - conflictStart->mSrcStart + 1).c_str()));
conflictStart = NULL;
conflictSplit = NULL;
}
}
}
}
}
for (auto sideNode : mResolvePassData->mParser->mSidechannelRootNode->mChildArr)
{
}
}
if (autoComplete->mResolveType == BfResolveType_GetSymbolInfo)
@ -4154,7 +4210,8 @@ void BfCompiler::ProcessAutocompleteTempType()
BfNamespaceVisitor namespaceVisitor;
namespaceVisitor.mResolvePassData = mResolvePassData;
namespaceVisitor.mSystem = mSystem;
namespaceVisitor.Visit(mResolvePassData->mParser->mRootNode);
for (auto parser : mResolvePassData->mParsers)
namespaceVisitor.Visit(parser->mRootNode);
}
auto _FindAcutalTypeDef = [&](BfTypeDef* tempTypeDef)
@ -4204,6 +4261,9 @@ void BfCompiler::ProcessAutocompleteTempType()
mContext->HandleChangedTypeDef(checkTempType, true);
}
auto sourceClassifier = mResolvePassData->GetSourceClassifier(checkTempType->mTypeDeclaration->mNameNode);
if (sourceClassifier == NULL)
continue;
BfSourceElementType elemType = BfSourceElementType_Type;
if (checkTempType->mTypeCode == BfTypeCode_Interface)
elemType = BfSourceElementType_Interface;
@ -4211,11 +4271,32 @@ void BfCompiler::ProcessAutocompleteTempType()
elemType = BfSourceElementType_RefType;
else if (checkTempType->mTypeCode == BfTypeCode_Struct)
elemType = BfSourceElementType_Struct;
mResolvePassData->mSourceClassifier->SetElementType(checkTempType->mTypeDeclaration->mNameNode, elemType);
sourceClassifier->SetElementType(checkTempType->mTypeDeclaration->mNameNode, elemType);
}
if (tempTypeDef == NULL)
{
if ((autoComplete != NULL) && (autoComplete->mResolveType == BfResolveType_GoToDefinition))
{
for (auto& kv : mResolvePassData->mEmitEmbedEntries)
{
String typeName = kv.mKey;
auto type = GetType(typeName);
if (type == NULL)
continue;
auto typeInst = type->ToTypeInstance();
if (typeInst == NULL)
continue;
mContext->RebuildType(typeInst);
if (!typeInst->mModule->mIsModuleMutable)
typeInst->mModule->StartNewRevision(BfModule::RebuildKind_All, true);
mContext->mScratchModule->PopulateType(typeInst, Beefy::BfPopulateType_Full_Force);
}
DoWorkLoop();
}
GenerateAutocompleteInfo();
BfLogSysM("ProcessAutocompleteTempType - no tempTypeDef\n");
return;
@ -4319,10 +4400,11 @@ void BfCompiler::ProcessAutocompleteTempType()
return;
}
auto sourceClassifier = mResolvePassData->GetSourceClassifier(tempTypeDef->mTypeDeclaration);
if (tempTypeDef->mTypeCode == BfTypeCode_Extension)
mResolvePassData->mSourceClassifier->SetElementType(tempTypeDef->mTypeDeclaration->mNameNode, actualTypeDef->mTypeCode);
sourceClassifier->SetElementType(tempTypeDef->mTypeDeclaration->mNameNode, actualTypeDef->mTypeCode);
if (tempTypeDef->mTypeDeclaration->mAttributes != NULL)
mResolvePassData->mSourceClassifier->VisitChild(tempTypeDef->mTypeDeclaration->mAttributes);
sourceClassifier->VisitChild(tempTypeDef->mTypeDeclaration->mAttributes);
BfTypeInstance* typeInst;
{
@ -4750,10 +4832,16 @@ BfType* BfCompiler::CheckSymbolReferenceTypeRef(BfModule* module, BfTypeReferenc
void BfCompiler::AddToRebuildTypeList(BfTypeInstance* typeInst, HashSet<BfTypeInstance*>& rebuildTypeInstList)
{
if (mResolvePassData->mParser != NULL)
if (!mResolvePassData->mParsers.IsEmpty())
{
// Only find references within the current file
if (!typeInst->mTypeDef->GetDefinition()->HasSource(mResolvePassData->mParser))
bool found = false;
for (auto parser : mResolvePassData->mParsers)
{
// Only find references within the current file
if (typeInst->mTypeDef->GetDefinition()->HasSource(parser))
found = true;
}
if (!found)
return;
}
@ -4922,7 +5010,17 @@ void BfCompiler::GetSymbolReferences()
for (auto checkTypeDef : typeDef->mPartials)
{
auto nameNode = checkTypeDef->mTypeDeclaration->mNameNode;
if ((mResolvePassData->mParser == NULL) || (nameNode->IsFromParser(mResolvePassData->mParser)))
for (auto parser : mResolvePassData->mParsers)
{
if (nameNode->IsFromParser(parser))
{
mResolvePassData->HandleTypeReference(nameNode, typeDef);
break;
}
}
if (mResolvePassData->mParsers.IsEmpty())
mResolvePassData->HandleTypeReference(nameNode, typeDef);
if (checkTypeDef->IsExtension())
@ -5365,9 +5463,7 @@ bool BfCompiler::IsDataResolvePass()
bool BfCompiler::WantsClassifyNode(BfAstNode* node)
{
return ((mResolvePassData != NULL) &&
(node->IsFromParser(mResolvePassData->mParser)) &&
(mResolvePassData->mSourceClassifier != NULL));
return (mResolvePassData != NULL) && (mResolvePassData->GetSourceClassifier(node) != NULL);
}
BfAutoComplete* BfCompiler::GetAutoComplete()
@ -6673,7 +6769,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mHasComptimeRebuilds = false;
int revision = mRevision;
BfLogSysM("Compile Start. Revision: %d. HasParser:%d AutoComplete:%d\n", revision,
(mResolvePassData != NULL) && (mResolvePassData->mParser != NULL),
(mResolvePassData != NULL) && (!mResolvePassData->mParsers.IsEmpty()),
(mResolvePassData != NULL) && (mResolvePassData->mAutoComplete != NULL));
if (mOptions.mCompileOnDemandKind == BfCompileOnDemandKind_AlwaysInclude)
@ -6785,7 +6881,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
BfTypeDef* typeDef;
BfLogSysM("UpdateRevisedTypes Revision %d. ResolvePass:%d CursorIdx:%d\n", mRevision, mIsResolveOnly,
((mResolvePassData == NULL) || (mResolvePassData->mParser == NULL)) ? - 1 : mResolvePassData->mParser->mCursorIdx);
((mResolvePassData == NULL) || (mResolvePassData->mParsers.IsEmpty())) ? - 1 : mResolvePassData->mParsers[0]->mCursorIdx);
mCompileState = CompileState_Normal;
UpdateRevisedTypes();
@ -7455,7 +7551,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
}
else
{
bool isTargeted = (mResolvePassData != NULL) && (mResolvePassData->mParser != NULL);
bool isTargeted = (mResolvePassData != NULL) && (!mResolvePassData->mParsers.IsEmpty());
if (!isTargeted)
{
for (auto bfModule : mContext->mModules)
@ -7477,7 +7573,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
//CompileLog("%d object files written: %s\n", numModulesWritten, moduleListStr.c_str());
//printf("Compile done, waiting for finish\n");
while (true)
{
if (mCanceling)
@ -7543,7 +7639,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
libManager->mErrors.Clear();
}
#endif
int numObjFilesWritten = 0;
for (auto& fileEntry : mCodeGen.mCodeGenFiles)
{
@ -7588,7 +7684,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
String compileInfo;
if (mIsResolveOnly)
compileInfo += StrFormat("ResolveOnly ResolveType:%d Parser:%d\n", mResolvePassData->mResolveType, mResolvePassData->mParser != NULL);
compileInfo += StrFormat("ResolveOnly ResolveType:%d Parser:%d\n", mResolvePassData->mResolveType, !mResolvePassData->mParsers.IsEmpty());
compileInfo += StrFormat("TotalTypes:%d\nTypesPopulated:%d\nMethodsDeclared:%d\nMethodsProcessed:%d\nCanceled? %d\n", mStats.mTotalTypes, mStats.mTypesPopulated, mStats.mMethodDeclarations, mStats.mMethodsProcessed, mCanceling);
compileInfo += StrFormat("TypesPopulated:%d\n", mStats.mTypesPopulated);
compileInfo += StrFormat("MethodDecls:%d\nMethodsProcessed:%d\nModulesStarted:%d\nModulesFinished:%d\n", mStats.mMethodDeclarations, mStats.mMethodsProcessed, mStats.mModulesFinished);
@ -7854,8 +7950,11 @@ void BfCompiler::GenerateAutocompleteInfo()
if (autoComplete->mInsertEndIdx > 0)
{
if (mResolvePassData->mParser->mSrc[autoComplete->mInsertEndIdx - 1] == '!')
autoComplete->mInsertEndIdx--;
if (!mResolvePassData->mParsers.IsEmpty())
{
if (mResolvePassData->mParsers[0]->mSrc[autoComplete->mInsertEndIdx - 1] == '!')
autoComplete->mInsertEndIdx--;
}
}
}
@ -9065,17 +9164,75 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
return result;
}
int BfCompiler::GetTypeId(const StringImpl& typeName)
{
auto type = GetType(typeName);
if (type != NULL)
return type->mTypeId;
return -1;
}
BfType* BfCompiler::GetType(const StringImpl& fullTypeName)
{
AutoCrit autoCrit(mSystem->mSystemLock);
BfPassInstance passInstance(mSystem);
BfProject* activeProject = NULL;
String typeName = fullTypeName;
int colonPos = (int)typeName.IndexOf(':');
if (colonPos != -1)
{
activeProject = mSystem->GetProject(typeName.Substring(0, colonPos));
typeName.Remove(0, colonPos + 1);
}
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mActiveProject = activeProject;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
BfParser parser(mSystem);
parser.SetSource(typeName.c_str(), (int)typeName.length());
parser.Parse(&passInstance);
BfReducer reducer;
reducer.mAlloc = parser.mAlloc;
reducer.mPassInstance = &passInstance;
if (parser.mRootNode->mChildArr.mSize == 0)
return NULL;
auto firstNode = parser.mRootNode->mChildArr[0];
auto endIdx = parser.mRootNode->mSrcEnd;
reducer.mVisitorPos = BfReducer::BfVisitorPos(parser.mRootNode);
reducer.mVisitorPos.MoveNext();
auto typeRef = reducer.CreateTypeRef(firstNode);
if (typeRef == NULL)
return NULL;
BfResolvePassData resolvePass;
SetAndRestoreValue<bool> prevIgnoreError(mContext->mScratchModule->mIgnoreErrors, true);
SetAndRestoreValue<bool> prevIgnoreWarnings(mContext->mScratchModule->mIgnoreWarnings, true);
SetAndRestoreValue<BfResolvePassData*> prevResolvePass(mResolvePassData, &resolvePass);
auto type = mContext->mScratchModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_AllowUnboundGeneric));
if (type != NULL)
return type;
return NULL;
}
int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
{
int lastDollarPos = (int)fileName.LastIndexOf('$');
if (lastDollarPos == -1)
return -1;
int dotPos = (int)fileName.LastIndexOf('.');
if (dotPos == -1)
return -1;
String typeIdStr = fileName.Substring(lastDollarPos + 1, dotPos - lastDollarPos - 1);
int typeId = (int)atoi(typeIdStr.c_str());
String typeName = fileName.Substring(lastDollarPos + 1);
int typeId = GetTypeId(typeName);
if ((typeId <= 0) || (typeId >= mContext->mTypes.mSize))
return -1;
@ -9097,6 +9254,96 @@ int BfCompiler::GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer)
return typeInst->mRevision;
}
String BfCompiler::GetEmitLocation(const StringImpl& typeName, int emitLine, int& outEmbedLine, int& outEmbedLineChar)
{
outEmbedLine = 0;
int typeId = GetTypeId(typeName);
if (typeId <= 0)
return "";
auto bfType = mContext->FindTypeById(typeId);
if (bfType == NULL)
return "";
auto typeInst = bfType->ToTypeInstance();
if (typeInst == NULL)
return "";
if (typeInst->mCeTypeInfo == NULL)
return "";
for (auto& kv : typeInst->mCeTypeInfo->mEmitSourceMap)
{
int partialIdx = (int)(kv.mKey >> 32);
int charIdx = (int)(kv.mKey & 0xFFFFFFFF);
auto typeDef = typeInst->mTypeDef;
if (partialIdx > 0)
typeDef = typeDef->mPartials[partialIdx];
auto origParser = typeDef->GetDefinition()->GetLastSource()->ToParser();
if (origParser == NULL)
continue;
auto emitParser = typeInst->mTypeDef->GetLastSource()->ToParser();
if (emitParser == NULL)
continue;
int startLine = 0;
int startLineChar = 0;
emitParser->GetLineCharAtIdx(kv.mValue.mSrcStart, startLine, startLineChar);
int endLine = 0;
int endLineChar = 0;
emitParser->GetLineCharAtIdx(kv.mValue.mSrcEnd - 1, endLine, endLineChar);
if ((emitLine >= startLine) && (emitLine <= endLine))
{
origParser->GetLineCharAtIdx(charIdx, outEmbedLine, outEmbedLineChar);
return origParser->mFileName;
}
}
return "";
}
bool BfCompiler::WriteEmitData(const StringImpl& filePath, BfProject* project)
{
ZipFile zipFile;
for (auto type : mContext->mResolvedTypes)
{
auto typeInst = type->ToTypeInstance();
if (typeInst == NULL)
continue;
if (typeInst->mTypeDef->mEmitParent == NULL)
continue;
if (!project->ContainsReference(typeInst->mTypeDef->mProject))
continue;
auto bfParser = typeInst->mTypeDef->GetLastSource()->ToParser();
String name = bfParser->mFileName;
if (name.StartsWith("$Emit$"))
name.Remove(0, 6);
String path = EncodeFileName(name);
path.Append(".bf");
if (!zipFile.IsOpen())
{
if (!zipFile.Create(filePath))
return false;
}
zipFile.Add(path, Span<uint8>((uint8*)bfParser->mSrc, bfParser->mSrcLength));
}
if (zipFile.IsOpen())
return zipFile.Close();
return true;
}
//////////////////////////////////////////////////////////////////////////
PerfManager* BfGetPerfManager(BfParser* bfParser);
@ -9122,57 +9369,33 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ClearResults(BfCompiler* bfCompiler)
bfCompiler->ClearResults();
}
BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfParser* bfParser, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
BF_EXPORT bool BF_CALLTYPE BfCompiler_ClassifySource(BfCompiler* bfCompiler, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData)
{
BP_ZONE("BfCompiler_ClassifySource");
BfSourceClassifier bfSourceClassifier(bfParser, charData);
bfSourceClassifier.mClassifierPassId = bfPassInstance->mClassifierPassId;
String& autoCompleteResultString = *gTLStrReturn.Get();
autoCompleteResultString.clear();
bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
bfSourceClassifier.mEnabled = doClassifyPass;
// Full classifier pass?
bfSourceClassifier.mSkipMethodInternals = true;
bfSourceClassifier.mSkipTypeDeclarations = true;
if (charData != NULL)
{
resolvePassData->mSourceClassifier = &bfSourceClassifier;
if (doClassifyPass)
bfSourceClassifier.Visit(bfParser->mRootNode);
}
bfSourceClassifier.mSkipTypeDeclarations = false;
bfSourceClassifier.mSkipMethodInternals = false;
bfPassInstance->mFilterErrorsTo = bfParser;
bfPassInstance->mCompiler = bfCompiler;
for (auto parser : resolvePassData->mParsers)
bfPassInstance->mFilterErrorsTo.Add(parser->mSourceData);
bfPassInstance->mTrimMessagesToCursor = true;
SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, bfPassInstance);
bool canceled = false;
if (resolvePassData->mAutoComplete != NULL)
{
if ((resolvePassData->mAutoComplete != NULL) && (!resolvePassData->mParsers.IsEmpty()))
{
bfCompiler->ProcessAutocompleteTempType();
}
else
canceled = !bfCompiler->Compile("");
resolvePassData->mSourceClassifier = NULL;
canceled = !bfCompiler->Compile("");
if ((charData != NULL) && (doClassifyPass))
{
bfSourceClassifier.mIsSideChannel = false;
bfSourceClassifier.Visit(bfParser->mErrorRootNode);
bfSourceClassifier.mIsSideChannel = true;
bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);
}
return !canceled;
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCompiler, BfParser* bfParser)
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCompiler, BfParser* bfParser, BfResolvePassData* resolvePassData, char* explicitEmitTypeNames)
{
String& outString = *gTLStrReturn.Get();
outString.Clear();
@ -9515,6 +9738,112 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetCollapseRegions(BfCompiler* bfCo
collapseVisitor.FlushSeries();
Array<BfTypeInstance*> explicitEmitTypes;
String checkStr = explicitEmitTypeNames;
for (auto& typeName : checkStr.Split('\n'))
{
if (typeName.IsEmpty())
continue;
auto bfType = bfCompiler->GetType(typeName);
if ((bfType != NULL) && (bfType->IsTypeInstance()))
explicitEmitTypes.Add(bfType->ToTypeInstance());
}
// Embed emit info
BfPassInstance bfPassInstance(bfCompiler->mSystem);
SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, resolvePassData);
SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &bfPassInstance);
Dictionary<int, int> foundTypeIds;
for (auto typeDef : bfParser->mTypeDefs)
{
auto useTypeDef = typeDef;
if (useTypeDef->mIsPartial)
{
useTypeDef = bfCompiler->mSystem->GetCombinedPartial(useTypeDef);
if (useTypeDef == NULL)
continue;
}
auto type = bfCompiler->mContext->mScratchModule->ResolveTypeDef(useTypeDef);
if (type == NULL)
continue;
if (auto typeInst = type->ToTypeInstance())
{
auto origTypeInst = typeInst;
if (typeInst->mCeTypeInfo == NULL)
continue;
for (auto checkIdx = explicitEmitTypes.mSize - 1; checkIdx >= 0; checkIdx--)
{
auto checkType = explicitEmitTypes[checkIdx];
if (checkType->mTypeDef->GetDefinition()->GetLatest() == typeInst->mTypeDef->GetDefinition()->GetLatest())
{
typeInst = checkType;
bfCompiler->mContext->mScratchModule->PopulateType(typeInst);
break;
}
}
for (auto& kv : typeInst->mCeTypeInfo->mEmitSourceMap)
{
int partialIdx = (int)(kv.mKey >> 32);
int charIdx = (int)(kv.mKey & 0xFFFFFFFF);
auto typeDef = typeInst->mTypeDef;
if (partialIdx > 0)
typeDef = typeDef->mPartials[partialIdx];
auto parser = typeDef->GetDefinition()->GetLastSource()->ToParser();
if (parser == NULL)
continue;
if (!FileNameEquals(parser->mFileName, bfParser->mFileName))
continue;
auto emitParser = typeInst->mTypeDef->GetLastSource()->ToParser();
if (emitParser == NULL)
continue;
int startLine = 0;
int startLineChar = 0;
emitParser->GetLineCharAtIdx(kv.mValue.mSrcStart, startLine, startLineChar);
int srcEnd = kv.mValue.mSrcEnd - 1;
while (srcEnd >= kv.mValue.mSrcStart)
{
char c = emitParser->mSrc[srcEnd];
if (!::isspace((uint8)c))
break;
srcEnd--;
}
int endLine = 0;
int endLineChar = 0;
emitParser->GetLineCharAtIdx(srcEnd, endLine, endLineChar);
int dollarPos = (int)emitParser->mFileName.LastIndexOf('$');
if (dollarPos == -1)
continue;
int* keyPtr = NULL;
int* valuePtr = NULL;
if (foundTypeIds.TryAdd(typeInst->mTypeId, &keyPtr, &valuePtr))
{
*valuePtr = foundTypeIds.mCount - 1;
outString += "+";
outString += emitParser->mFileName.Substring(dollarPos + 1);
outString += "\n";
}
outString += (kv.mValue.mKind == BfCeTypeEmitSourceKind_Method) ? 'm' : 't';
outString += StrFormat("%d,%d,%d,%d,%d,%d\n", *valuePtr, typeInst->mRevision, partialIdx, charIdx, startLine, endLine + 1);
}
}
}
return outString.c_str();
}
@ -9587,7 +9916,7 @@ BF_EXPORT bool BF_CALLTYPE BfCompiler_VerifyTypeName(BfCompiler* bfCompiler, cha
resolvePassData.mAutoComplete->mCompiler = bfCompiler;
resolvePassData.mAutoComplete->mModule = bfCompiler->mContext->mScratchModule;
}
resolvePassData.mParser = &parser;
resolvePassData.mParsers.Add(&parser);
SetAndRestoreValue<BfResolvePassData*> prevCompilerResolvePassData(bfCompiler->mResolvePassData, &resolvePassData);
SetAndRestoreValue<BfPassInstance*> prevPassInstance(bfCompiler->mPassInstance, &passInstance);
@ -9733,6 +10062,11 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefInfo(BfCompiler* bfCompil
return outString.c_str();
}
BF_EXPORT int BF_CALLTYPE BfCompiler_GetTypeId(BfCompiler* bfCompiler, const char* name)
{
return bfCompiler->GetTypeId(name);
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler, const char* name)
{
String& outString = *gTLStrReturn.Get();
@ -9820,6 +10154,40 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler,
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGenericTypeInstances(BfCompiler* bfCompiler, const char* typeName)
{
String& outString = *gTLStrReturn.Get();
outString = "";
auto lookupType = bfCompiler->GetType(typeName);
if (lookupType == NULL)
return "";
auto lookupTypeInst = lookupType->ToTypeInstance();
if (lookupTypeInst == NULL)
return "";
for (auto type : bfCompiler->mContext->mResolvedTypes)
{
auto typeInst = type->ToTypeInstance();
if (typeInst == NULL)
continue;
if (typeInst->IsUnspecializedTypeVariation())
continue;
if (typeInst->mTypeDef->GetDefinition()->GetLatest() == lookupTypeInst->mTypeDef->GetDefinition()->GetLatest())
{
outString += typeInst->mTypeDef->mProject->mName;
outString += ":";
outString += bfCompiler->mContext->mScratchModule->TypeToString(typeInst, BfTypeNameFlags_None);
outString += "\n";
}
}
return outString.c_str();
}
enum BfUsedOutputFlags
{
BfUsedOutputFlags_None = 0,
@ -10236,3 +10604,16 @@ BF_EXPORT int32 BF_CALLTYPE BfCompiler_GetEmitSourceVersion(BfCompiler* bfCompil
{
return bfCompiler->GetEmitSource(fileName, NULL);
}
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetEmitLocation(BfCompiler* bfCompiler, char* typeName, int line, int& outEmbedLine, int& outEmbedLineChar)
{
String& outString = *gTLStrReturn.Get();
outString.clear();
outString = bfCompiler->GetEmitLocation(typeName, line, outEmbedLine, outEmbedLineChar);
return outString.c_str();
}
BF_EXPORT bool BF_CALLTYPE BfCompiler_WriteEmitData(BfCompiler* bfCompiler, char* filePath, BfProject* project)
{
return bfCompiler->WriteEmitData(filePath, project);
}

View file

@ -543,7 +543,11 @@ public:
String GetTypeDefMatches(const StringImpl& searchSrc);
void GetTypeDefs(const StringImpl& typeName, Array<BfTypeDef*>& typeDefs);
String GetTypeDefInfo(const StringImpl& typeName);
int GetTypeId(const StringImpl& typeName);
BfType* GetType(const StringImpl& typeName);
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
String GetEmitLocation(const StringImpl& typeName, int line, int& outEmbedLine, int& outEmbedLineChar);
bool WriteEmitData(const StringImpl& filePath, BfProject* project);
void CompileLog(const char* fmt ...);
void ReportMemory(MemReporter* memReporter);

View file

@ -355,8 +355,8 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
while (!mCompiler->mCanceling)
{
BfParser* resolveParser = NULL;
if (mCompiler->mResolvePassData != NULL)
resolveParser = mCompiler->mResolvePassData->mParser;
if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
resolveParser = mCompiler->mResolvePassData->mParsers[0];
bool didWork = false;
@ -549,8 +549,16 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
BF_ASSERT(!module->mAwaitingFinish);
if ((resolveParser != NULL) && (methodInstance->mMethodDef->mDeclaringType != NULL) && (methodInstance->mMethodDef->mDeclaringType->GetDefinition()->mSource != resolveParser))
{
continue;
{
bool allow = false;
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mHasCursorIdx))
{
auto parser = methodInstance->mMethodDef->mDeclaringType->GetLastSource()->ToParser();
if ((parser != NULL) && (parser->mCursorIdx >= 0))
allow = true;
}
if (!allow)
continue;
}
hasBeenProcessed = methodInstance->mHasBeenProcessed;
@ -722,7 +730,7 @@ bool BfContext::ProcessWorkList(bool onlyReifiedTypes, bool onlyReifiedMethods)
BP_ZONE("PWL_CheckIncompleteGenerics");
for (auto type : mResolvedTypes)
{
{
if ((type->IsIncomplete()) && (type->HasBeenReferenced()))
{
// The only reason a type instance wouldn't have already been in the work list is
@ -759,12 +767,13 @@ void BfContext::HandleChangedTypeDef(BfTypeDef* typeDef, bool isAutoCompleteTemp
{
BF_ASSERT(typeDef->mEmitParent == NULL);
if ((mCompiler->mResolvePassData == NULL) || (!typeDef->HasSource(mCompiler->mResolvePassData->mParser)))
if ((mCompiler->mResolvePassData == NULL) || (mCompiler->mResolvePassData->mParsers.IsEmpty()) ||
(!typeDef->HasSource(mCompiler->mResolvePassData->mParsers[0])))
return;
if (typeDef->mDefState != BfTypeDef::DefState_Defined)
{
if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
if (mCompiler->mResolvePassData->mIsClassifying)
{
auto _CheckSource = [&](BfTypeDef* checkTypeDef)
{
@ -774,12 +783,11 @@ void BfContext::HandleChangedTypeDef(BfTypeDef* typeDef, bool isAutoCompleteTemp
if (typeDecl == NULL)
return;
if (typeDecl->GetSourceData() == mCompiler->mResolvePassData->mParser->mSourceData)
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(typeDecl))
{
SetAndRestoreValue<bool> prevSkipTypeDeclaration(mCompiler->mResolvePassData->mSourceClassifier->mSkipTypeDeclarations, true);
auto classifier = mCompiler->mResolvePassData->mSourceClassifier;
classifier->mSkipMethodInternals = isAutoCompleteTempType;
classifier->Handle(typeDecl);
SetAndRestoreValue<bool> prevSkipTypeDeclaration(sourceClassifier->mSkipTypeDeclarations, true);
sourceClassifier->mSkipMethodInternals = isAutoCompleteTempType;
sourceClassifier->Handle(typeDecl);
}
};

View file

@ -156,6 +156,7 @@ public:
BfFieldDef* mCurFieldDef;
BfTypeDef* mCurTypeDef;
BfTypeDef* mForceActiveTypeDef;
BfProject* mActiveProject;
ResolveKind mResolveKind;
BfAstNode* mCurVarInitializer;
int mArrayInitializerSize;
@ -174,6 +175,7 @@ public:
mCurAttributeTypeRef = NULL;
mCurTypeDef = NULL;
mForceActiveTypeDef = NULL;
mActiveProject = NULL;
mCurVarInitializer = NULL;
mArrayInitializerSize = -1;
mResolveKind = ResolveKind_None;

View file

@ -153,8 +153,12 @@ void BfDefBuilder::Visit(BfIdentifierNode* identifier)
// already been handled, so we need to ignore that space while determining if we're "inside" this method or not during
// autocompletion
bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int addLen)
{
if ((mResolvePassData == NULL) || (mResolvePassData->mParser->mCursorIdx == -1))
{
if ((mResolvePassData == NULL) || (!mResolvePassData->mHasCursorIdx))
return true;
auto parser = wholeNode->GetParser();
if (parser->mCursorIdx == -1)
return true;
// We need to get all nodes when we get fixits because the cursor could be either before or after fields with
@ -163,9 +167,9 @@ bool BfDefBuilder::WantsNode(BfAstNode* wholeNode, BfAstNode* startNode, int add
//return true;
addLen++;
if ((mResolvePassData->mParser->mCursorIdx >= wholeNode->GetSrcStart()) && (mResolvePassData->mParser->mCursorIdx < wholeNode->GetSrcEnd() + addLen))
if ((parser->mCursorIdx >= wholeNode->GetSrcStart()) && (parser->mCursorIdx < wholeNode->GetSrcEnd() + addLen))
{
if ((startNode == NULL) || (mResolvePassData->mParser->mCursorIdx >= startNode->GetSrcStart()))
if ((startNode == NULL) || (parser->mCursorIdx >= startNode->GetSrcStart()))
return true;
}
return false;
@ -1417,13 +1421,20 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration)
{
isAutoCompleteTempType = (mResolvePassData->mAutoComplete != NULL);
int cursorIdx = mResolvePassData->mParser->mCursorIdx;
if (typeDeclaration->Contains(cursorIdx, 1, 0))
if (mResolvePassData->mHasCursorIdx)
{
// Within bounds
auto parser = typeDeclaration->GetParser();
if (parser != NULL)
{
int cursorIdx = parser->mCursorIdx;
if (typeDeclaration->Contains(cursorIdx, 1, 0))
{
// Within bounds
}
else if (cursorIdx != -1)
return;
}
}
else if (cursorIdx != -1)
return;
}
int curLine = 0;

View file

@ -4260,7 +4260,8 @@ BfTypedValue BfExprEvaluator::LookupIdentifier(BfAstNode* refNode, const StringI
if ((resolvingFieldDef != NULL) &&
(mModule->mCompiler->mResolvePassData != NULL) &&
(mModule->mCompiler->mResolvePassData->mParser == resolvingFieldDef->mFieldDeclaration->GetParser()) &&
(!mModule->mCompiler->mResolvePassData->mParsers.IsEmpty()) &&
(mModule->mCompiler->mResolvePassData->mParsers[0] == resolvingFieldDef->mFieldDeclaration->GetParser()) &&
(GetAutoComplete() != NULL))
{
return mModule->GetDefaultTypedValue(mModule->mCurTypeInstance);
@ -8805,7 +8806,7 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
auto autoComplete = GetAutoComplete();
if ((autoComplete != NULL) && (autoComplete->mIsCapturingMethodMatchInfo))
{
if ((!targetSrc->IsFromParser(mModule->mCompiler->mResolvePassData->mParser)) ||
if ((!targetSrc->IsFromParser(mModule->mCompiler->mResolvePassData->mParsers[0])) ||
((autoComplete->mMethodMatchInfo->mInvocationSrcIdx != -1) && (autoComplete->mMethodMatchInfo->mInvocationSrcIdx != targetSrc->GetSrcStart())))
{
autoComplete->mIsCapturingMethodMatchInfo = false;
@ -9247,10 +9248,13 @@ BfTypedValue BfExprEvaluator::MatchMethod(BfAstNode* targetSrc, BfMethodBoundExp
}
if (enumResult)
{
if (mModule->mCompiler->WantsClassifyNode(targetSrc))
{
if (mModule->mCompiler->mResolvePassData != NULL)
{
mModule->mCompiler->mResolvePassData->mSourceClassifier->SetElementType(targetSrc, BfSourceElementType_Normal);
if (auto sourceClassifier = mModule->mCompiler->mResolvePassData->GetSourceClassifier(targetSrc))
{
sourceClassifier->SetElementType(targetSrc, BfSourceElementType_Normal);
}
}
return enumResult;
}
@ -14444,7 +14448,7 @@ void BfExprEvaluator::CheckObjectCreateTypeRef(BfType* expectingType, BfAstNode*
{
auto autoComplete = GetAutoComplete();
if ((autoComplete != NULL) && (afterNode != NULL) && (autoComplete->mIsAutoComplete) &&
(afterNode->IsFromParser(mModule->mCompiler->mResolvePassData->mParser)) &&
(afterNode->IsFromParser(mModule->mCompiler->mResolvePassData->mParsers[0])) &&
(afterNode->GetParser()->mCursorIdx == afterNode->GetSrcEnd() + 1))
{
BfType* expectingType = mExpectingType;

View file

@ -2874,11 +2874,10 @@ bool BfModule::CheckProtection(BfProtectionCheckFlags& flags, BfTypeInstance* me
void BfModule::SetElementType(BfAstNode* astNode, BfSourceElementType elementType)
{
if ((mCompiler->mResolvePassData != NULL) &&
(mCompiler->mResolvePassData->mSourceClassifier != NULL) &&
(astNode->IsFromParser(mCompiler->mResolvePassData->mParser)))
if (mCompiler->mResolvePassData != NULL)
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(astNode, elementType);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(astNode))
sourceClassifier->SetElementType(astNode, elementType);
}
}
@ -4441,10 +4440,13 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
}
else
{
if ((mCompiler->mIsResolveOnly) && (mCompiler->mResolvePassData->mSourceClassifier != NULL) && (initializer->IsFromParser(mCompiler->mResolvePassData->mParser)))
if (mCompiler->mIsResolveOnly)
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(initializer, BfSourceElementType_Normal);
mCompiler->mResolvePassData->mSourceClassifier->VisitChildNoRef(initializer);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(initializer))
{
sourceClassifier->SetElementType(initializer, BfSourceElementType_Normal);
sourceClassifier->VisitChildNoRef(initializer);
}
}
if ((mCurTypeInstance->IsPayloadEnum()) && (fieldDef->IsEnumCaseEntry()))
@ -11631,10 +11633,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
if (!mCompiler->mHasRequiredTypes)
return;
if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) &&
(attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL))
{
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(attributesDirective);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(attributesDirective))
sourceClassifier->VisitChild(attributesDirective);
}
SetAndRestoreValue<bool> prevIsCapturingMethodMatchInfo;
@ -11644,6 +11646,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
BfTypeInstance* baseAttrTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompiler->mAttributeTypeDef)->ToTypeInstance();
BfAttributeTargets targetOverride = (BfAttributeTargets)0;
BfTypeDef* activeTypeDef = GetActiveTypeDef();
BfAutoComplete* autoComplete = NULL;
if (mCompiler->mResolvePassData != NULL)
autoComplete = mCompiler->mResolvePassData->mAutoComplete;
@ -11674,6 +11677,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
BfCustomAttribute customAttribute;
customAttribute.mAwaitingValidation = true;
customAttribute.mDeclaringType = activeTypeDef;
customAttribute.mRef = attributesDirective;
if (attributesDirective->mAttrOpenToken != NULL)
@ -12109,7 +12113,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
}
if (success)
{
{
customAttributes->mAttributes.push_back(customAttribute);
}
}
@ -13446,10 +13450,10 @@ BfModule* BfModule::GetOrCreateMethodModule(BfMethodInstance* methodInstance)
if (methodDecl != NULL)
{
auto attributesDirective = methodDecl->mAttributes;
if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) &&
(attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL))
{
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(attributesDirective);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(attributesDirective))
sourceClassifier->VisitChild(attributesDirective);
}
}
}
@ -16239,7 +16243,7 @@ bool BfModule::IsInterestedInMethod(BfTypeInstance* typeInstance, BfMethodDef* m
if (methodDeclaration == NULL)
checkNode = methodDef->mBody;
if ((mCompiler->mResolvePassData->mParser != NULL) && (typeDef->mTypeDeclaration->IsFromParser(mCompiler->mResolvePassData->mParser)))
if ((!mCompiler->mResolvePassData->mParsers.IsEmpty()) && (typeDef->mTypeDeclaration->IsFromParser(mCompiler->mResolvePassData->mParsers[0])))
{
if (mCompiler->mResolvePassData->mAutoComplete == NULL)
return true;
@ -16650,10 +16654,10 @@ void BfModule::CreateStaticCtor()
{
if (fieldDef->mInitializer != NULL)
{
if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDef->mInitializer))
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer);
sourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
sourceClassifier->VisitChild(fieldDef->mInitializer);
}
BfType* wantType = NULL;
if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) && (!BfNodeIsA<BfLetTypeReference>(fieldDef->mTypeRef)))
@ -16835,10 +16839,13 @@ void BfModule::EmitDtorBody()
while (fieldDtor != NULL)
{
if (mCompiler->WantsClassifyNode(fieldDtor))
if (mCompiler->mResolvePassData != NULL)
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDtor);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDtor))
{
sourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
sourceClassifier->VisitChild(fieldDtor);
}
}
UpdateSrcPos(fieldDtor);
@ -16910,7 +16917,7 @@ void BfModule::EmitDtorBody()
for (auto fieldDef : tempTypeDef->mFields)
{
if ((fieldDef->mIsStatic == methodDef->mIsStatic) && (fieldDef->mFieldDeclaration != NULL) &&
(fieldDef->mFieldDeclaration->mFieldDtor != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
(fieldDef->mFieldDeclaration->mFieldDtor != NULL) && (mCompiler->mResolvePassData->mIsClassifying))
{
BfType* fieldType = NULL;
@ -16943,8 +16950,11 @@ void BfModule::EmitDtorBody()
while (fieldDtor != NULL)
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDtor);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDtor))
{
sourceClassifier->SetElementType(fieldDtor, BfSourceElementType_Normal);
sourceClassifier->VisitChild(fieldDtor);
}
UpdateSrcPos(fieldDtor);
VisitEmbeddedStatement(fieldDtor->mBody);
@ -17659,10 +17669,13 @@ void BfModule::EmitCtorBody(bool& skipBody)
{
for (auto fieldDef : tempTypeDef->mFields)
{
if ((!fieldDef->mIsStatic) && (fieldDef->mInitializer != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
if ((!fieldDef->mIsStatic) && (fieldDef->mInitializer != NULL) && (mCompiler->mResolvePassData->mIsClassifying))
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(fieldDef->mInitializer))
{
sourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
sourceClassifier->VisitChild(fieldDef->mInitializer);
}
BfType* wantType = NULL;
if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) &&
@ -19300,12 +19313,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
BF_ASSERT(!methodInstance->mIRFunction.IsFake() || (methodInstance->GetImportCallKind() != BfImportCallKind_None));
}
SetAndRestoreValue<BfSourceClassifier*> prevSourceClassifier;
SetAndRestoreValue<bool> prevIsClassifying;
if (((methodInstance->mMethodDef->mMethodType == BfMethodType_CtorCalcAppend) || (methodInstance->mIsForeignMethodDef) || (methodInstance->IsSpecializedGenericMethod())) &&
(mCompiler->mResolvePassData != NULL))
{
// Don't classify on the CtorCalcAppend, just on the actual Ctor
prevSourceClassifier.Init(mCompiler->mResolvePassData->mSourceClassifier, NULL);
prevIsClassifying.Init(mCompiler->mResolvePassData->mIsClassifying, false);
}
if (methodInstance->mHasBeenProcessed)
@ -19573,10 +19586,10 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup,
if ((mCurMethodState == NULL) && (!IsInSpecializedSection())) // Only do initial classify for the 'outer' method state, not any local methods or lambdas
{
if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()) &&
(methodDef->mBody->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL))
if ((mCompiler->mIsResolveOnly) && (!mIsComptimeModule) && (methodDef->mBody != NULL) && (!mCurTypeInstance->IsBoxed()))
{
mCompiler->mResolvePassData->mSourceClassifier->VisitChildNoRef(methodDef->mBody);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(methodDef->mBody))
sourceClassifier->VisitChildNoRef(methodDef->mBody);
}
}

View file

@ -34,6 +34,7 @@ class BfResolvedType;
class BfExprEvaluator;
class CeEmitContext;
class CeDbgState;
enum BfCeTypeEmitSourceKind;
enum BfPopulateType
{
@ -1780,8 +1781,8 @@ public:
BfModuleOptions GetModuleOptions();
BfCheckedKind GetDefaultCheckedKind();
void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src);
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode);
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& src, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind);
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& ctxString, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind);
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfFieldInstance* fieldInstance, BfCustomAttributes* customAttributes, Dictionary<BfTypeInstance*, BfIRValue>& foundAttributes, bool underlyingTypeDeferred);
void CEMixin(BfAstNode* refNode, const StringImpl& src);
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);

View file

@ -2023,7 +2023,7 @@ void BfModule::SetTypeOptions(BfTypeInstance* typeInstance)
typeInstance->mTypeOptionsIdx = GenerateTypeOptions(typeInstance->mCustomAttributes, typeInstance, true);
}
BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src)
BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& src, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind)
{
BfCEParseContext ceParseContext;
ceParseContext.mFailIdx = mCompiler->mPassInstance->mFailedIdx;
@ -2034,6 +2034,21 @@ BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const Strin
BfParser* emitParser = NULL;
int64 emitSourceMapKey = ((int64)declaringType->mPartialIdx << 32) | refNode->mSrcStart;
if (typeInstance->mCeTypeInfo == NULL)
typeInstance->mCeTypeInfo = new BfCeTypeInfo();
auto ceTypeInfo = typeInstance->mCeTypeInfo;
if (ceTypeInfo->mNext != NULL)
ceTypeInfo = ceTypeInfo->mNext;
BfCeTypeEmitSource* ceEmitSource = NULL;
ceTypeInfo->mEmitSourceMap.TryAdd(emitSourceMapKey, NULL, &ceEmitSource);
ceEmitSource->mKind = emitSourceKind;
int emitSrcStart = 0;
BfEmitEmbedEntry* emitEmbedEntry = NULL;
if (typeInstance->mTypeDef->mEmitParent == NULL)
{
BF_ASSERT(typeInstance->mTypeDef->mNextRevision == NULL);
@ -2048,21 +2063,38 @@ BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const Strin
createdParser = true;
emitParser = new BfParser(mSystem, typeInstance->mTypeDef->mProject);
emitParser->mIsEmitted = true;
emitParser->mFileName = typeInstance->mTypeDef->mName->ToString();
BfLogSys(mSystem, "Emit typeDef for type %p created %p parser %p typeDecl %p\n", typeInstance, emitTypeDef, emitParser, emitTypeDef->mTypeDeclaration);
if (mCompiler->mIsResolveOnly)
emitParser->mFileName += "$EmitR$";
else
emitParser->mFileName += "$Emit$";
String typeName;
typeName += typeInstance->mTypeDef->mProject->mName;
typeName += ":";
typeName += TypeToString(typeInstance, BfTypeNameFlags_None);
if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mEmitEmbedEntries.IsEmpty()))
mCompiler->mResolvePassData->mEmitEmbedEntries.TryGetValue(typeName, &emitEmbedEntry);
emitParser->mFileName = "$Emit$";
emitParser->mFileName += typeName;
emitParser->mFileName += StrFormat("%d", typeInstance->mTypeId);
emitParser->mFileName += StrFormat(".bf|%d", typeInstance->mRevision);
emitTypeDef->mSource = emitParser;
emitParser->mRefCount++;
emitParser->SetSource(src.c_str(), src.mLength);
if (emitEmbedEntry != NULL)
{
emitEmbedEntry->mRevision = typeInstance->mRevision;
emitEmbedEntry->mParser = emitParser;
emitEmbedEntry->mParser->mSourceClassifier = new BfSourceClassifier(emitEmbedEntry->mParser, NULL);
mCompiler->mPassInstance->mFilterErrorsTo.Add(emitEmbedEntry->mParser->mParserData);
if (emitEmbedEntry->mCursorIdx != -1)
{
emitParser->SetCursorIdx(emitEmbedEntry->mCursorIdx);
emitParser->mParserFlags = (BfParserFlag)(emitParser->mParserFlags | ParserFlag_Autocomplete | ParserFlag_Classifying);
}
}
// If we emit only from method attributes then we will already have method instances created
auto _FixMethod = [&](BfMethodInstance* methodInstance)
{
@ -2082,19 +2114,57 @@ BfCEParseContext BfModule::CEEmitParse(BfTypeInstance* typeInstance, const Strin
};
}
else
{
{
emitParser = typeInstance->mTypeDef->mSource->ToParser();
int idx = emitParser->AllocChars(src.mLength + 1);
memcpy((uint8*)emitParser->mSrc + idx, src.c_str(), src.mLength + 1);
if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mEmitEmbedEntries.IsEmpty()))
{
int dollarPos = (int)emitParser->mFileName.LastIndexOf('$');
if (dollarPos != -1)
mCompiler->mResolvePassData->mEmitEmbedEntries.TryGetValue(emitParser->mFileName.Substring(dollarPos + 1), &emitEmbedEntry);
}
int idx = emitParser->AllocChars(2 + src.mLength + 1);
emitSrcStart = idx + 2;
memcpy((uint8*)emitParser->mSrc + idx, "\n\n", 2);
memcpy((uint8*)emitParser->mSrc + idx + 2, src.c_str(), src.mLength + 1);
emitParser->mSrcIdx = idx;
emitParser->mSrcLength = idx + src.mLength;
emitParser->mSrcLength = idx + src.mLength + 2;
emitParser->mParserData->mSrcLength = emitParser->mSrcLength;
emitParser->mOrigSrcLength = emitParser->mSrcLength;
}
if (ceEmitSource->mSrcStart == -1)
{
ceEmitSource->mSrcStart = emitSrcStart;
ceEmitSource->mSrcEnd = emitParser->mSrcLength;
}
else
{
ceEmitSource->mSrcStart = BF_MIN(ceEmitSource->mSrcStart, emitSrcStart);
ceEmitSource->mSrcEnd = BF_MAX(ceEmitSource->mSrcEnd, emitParser->mSrcLength);
}
emitParser->Parse(mCompiler->mPassInstance);
emitParser->FinishSideNodes();
if (emitEmbedEntry != NULL)
{
int prevStart = emitEmbedEntry->mCharData.mSize;
emitEmbedEntry->mCharData.GrowUninitialized(emitParser->mSrcLength - emitEmbedEntry->mCharData.mSize);
auto charDataPtr = emitEmbedEntry->mCharData.mVals;
for (int i = prevStart; i < emitParser->mSrcLength; i++)
{
charDataPtr[i].mChar = emitParser->mSrc[i];
charDataPtr[i].mDisplayPassId = 0;
charDataPtr[i].mDisplayTypeId = 0;
charDataPtr[i].mDisplayFlags = 0;
}
emitEmbedEntry->mParser->mSourceClassifier->mCharData = emitEmbedEntry->mCharData.mVals;
}
if (createdParser)
{
AutoCrit crit(mSystem->mDataLock);
@ -2117,7 +2187,7 @@ void BfModule::FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInst
}
}
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode)
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfTypeDef* declaringType, const StringImpl& ctxString, BfAstNode* refNode, BfCeTypeEmitSourceKind emitSourceKind)
{
for (int ifaceTypeId : ceEmitContext->mInterfaces)
typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId);
@ -2127,16 +2197,16 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
String src;
if (typeInstance->mTypeDef->mEmitParent != NULL)
src += "\n\n";
// if (typeInstance->mTypeDef->mEmitParent != NULL)
// src += "\n\n";
src += "// Code emission in ";
src += ctxString;
src += "\n\n";
// src += "// Code emission in ";
// src += ctxString;
// src += "\n\n";
src += ceEmitContext->mEmitData;
ceEmitContext->mEmitData.Clear();
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, src);
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, declaringType, src, refNode, emitSourceKind);
auto emitParser = typeInstance->mTypeDef->mSource->ToParser();
auto typeDeclaration = emitParser->mAlloc->Alloc<BfTypeDeclaration>();
@ -2167,6 +2237,13 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
FinishCEParseContext(refNode, typeInstance, &ceParseContext);
if (emitParser->mSourceClassifier != NULL)
{
emitParser->mSourceClassifier->VisitChild(emitParser->mRootNode);
emitParser->mSourceClassifier->VisitChild(emitParser->mSidechannelRootNode);
emitParser->mSourceClassifier->VisitChild(emitParser->mErrorRootNode);
}
if (typeInstance->mTypeDef->mEmitParent != NULL)
{
// Remove generated fields like the 'underlying type' enum field
@ -2347,7 +2424,8 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
ctxStr += TypeToString(typeInstance);
ctxStr += " ";
ctxStr += customAttribute.mRef->LocationToString();
UpdateCEEmit(ceEmitContext, typeInstance, ctxStr, customAttribute.mRef);
UpdateCEEmit(ceEmitContext, typeInstance, customAttribute.mDeclaringType, ctxStr, customAttribute.mRef, BfCeTypeEmitSourceKind_Type);
}
}
@ -2361,11 +2439,11 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
//auto emitParser = activeTypeDef->mEmitParser;
String src;
if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
src += "\n\n";
src += "// Code emission in ";
src += MethodToString(mCurMethodInstance);
src += "\n";
// if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
// src += "\n\n";
// src += "// Code emission in ";
// src += MethodToString(mCurMethodInstance);
// src += "\n";
src += code;
BfReducer bfReducer;
@ -2380,7 +2458,7 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
bool wantsDIData = (mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo);
mBfIRBuilder->SaveDebugLocation();
BfCEParseContext ceParseContext = CEEmitParse(mCurTypeInstance, src);
BfCEParseContext ceParseContext = CEEmitParse(mCurTypeInstance, activeTypeDef, src, refNode, BfCeTypeEmitSourceKind_Method);
auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
bfReducer.mSource = emitParser;
bfReducer.mAlloc = emitParser->mAlloc;
@ -2503,6 +2581,11 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
if (methodDeclaration->mAttributes == NULL)
continue;
BfTypeState typeState;
typeState.mPrevState = mContext->mCurTypeState;
typeState.mForceActiveTypeDef = methodDef->mDeclaringType;
SetAndRestoreValue<BfTypeState*> prevTypeState(mContext->mCurTypeState, &typeState);
bool wantsAttributes = false;
BfAttributeDirective* checkAttributes = methodDeclaration->mAttributes;
while (checkAttributes != NULL)
@ -2607,7 +2690,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
ctxStr += MethodToString(methodInstance);
ctxStr += " ";
ctxStr += methodInstance->mMethodDef->GetRefNode()->LocationToString();
UpdateCEEmit(ceEmitContext, typeInstance, ctxStr, methodInstance->mMethodDef->GetRefNode());
UpdateCEEmit(ceEmitContext, typeInstance, methodDef->mDeclaringType, ctxStr, methodInstance->mMethodDef->GetRefNode(), BfCeTypeEmitSourceKind_Type);
}
}
@ -2751,13 +2834,13 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
if ((!ceEmitContext.mEmitData.IsEmpty()) || (!ceEmitContext.mExitEmitData.IsEmpty()))
{
String src;
src += "// Code emission in comptime ApplyToMethod of ";
src += TypeToString(attrType);
src += " to ";
src += MethodToString(methodInstance);
src += " ";
src += customAttribute.mRef->LocationToString();
src += "\n";
// src += "// Code emission in comptime ApplyToMethod of ";
// src += TypeToString(attrType);
// src += " to ";
// src += MethodToString(methodInstance);
// src += " ";
// src += customAttribute.mRef->LocationToString();
// src += "\n";
//auto emitTypeDef = typeInstance->mCeTypeInfo->mNext->mTypeDef;
//auto emitParser = emitTypeDef->mSource->ToParser();
@ -2771,16 +2854,29 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
bfReducer.mCurTypeDecl = activeTypeDef->mTypeDeclaration;
bfReducer.mCurMethodDecl = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration);
BfAstNode* bodyNode = NULL;
if (auto methodDecl = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration))
bodyNode = methodDecl->mBody;
if (!ceEmitContext.mEmitData.IsEmpty())
{
SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef);
SetAndRestoreValue<BfAstNode*> prevCustomAttribute(mCurMethodState->mEmitRefNode, customAttribute.mRef);
String entrySrc = src;
if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
entrySrc += "\n\n";
// if (mCurTypeInstance->mTypeDef->mEmitParent != NULL)
// entrySrc += "\n\n";
entrySrc += src;
entrySrc += ceEmitContext.mEmitData;
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, entrySrc);
BfAstNode* refNode = customAttribute.mRef;
if (bodyNode != NULL)
{
refNode = bodyNode;
if (auto blockNode = BfNodeDynCast<BfBlock>(bodyNode))
if (blockNode->mOpenBrace != NULL)
refNode = blockNode->mOpenBrace;
}
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, methodInstance->mMethodDef->mDeclaringType, entrySrc, refNode, BfCeTypeEmitSourceKind_Type);
auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
bfReducer.mSource = emitParser;
bfReducer.mAlloc = emitParser->mAlloc;
@ -2796,7 +2892,18 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance)
exitSrc += "\n\n";
exitSrc += src;
exitSrc += ceEmitContext.mExitEmitData;
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, exitSrc);
BfAstNode* refNode = customAttribute.mRef;
if (bodyNode != NULL)
{
refNode = bodyNode;
if (auto blockNode = BfNodeDynCast<BfBlock>(bodyNode))
if (blockNode->mCloseBrace != NULL)
refNode = blockNode->mCloseBrace;
}
BfCEParseContext ceParseContext = CEEmitParse(typeInstance, methodInstance->mMethodDef->mDeclaringType, exitSrc, refNode, BfCeTypeEmitSourceKind_Type);
auto emitParser = mCurTypeInstance->mTypeDef->mSource->ToParser();
bfReducer.mSource = emitParser;
bfReducer.mAlloc = emitParser->mAlloc;
@ -4540,7 +4647,14 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (typeInstance->mCeTypeInfo->mNext != NULL)
{
auto ceInfo = typeInstance->mCeTypeInfo->mNext;
HashContext hashCtx;
hashCtx.Mixin(ceInfo->mEmitSourceMap.mCount);
for (auto& kv : ceInfo->mEmitSourceMap)
{
hashCtx.Mixin(kv.mKey);
hashCtx.Mixin(kv.mValue);
}
hashCtx.Mixin(ceInfo->mOnCompileMap.mCount);
for (auto& kv : ceInfo->mOnCompileMap)
{
@ -4559,15 +4673,26 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if (!typeInstance->mCeTypeInfo->mNext->mFailed)
{
if ((typeInstance->mCeTypeInfo->mHash != typeInstance->mCeTypeInfo->mNext->mHash) && (!typeInstance->mCeTypeInfo->mHash.IsZero()))
mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
typeInstance->mCeTypeInfo->mEmitSourceMap = typeInstance->mCeTypeInfo->mNext->mEmitSourceMap;
typeInstance->mCeTypeInfo->mOnCompileMap = typeInstance->mCeTypeInfo->mNext->mOnCompileMap;
typeInstance->mCeTypeInfo->mTypeIFaceMap = typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap;
typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash;
typeInstance->mCeTypeInfo->mHash = typeInstance->mCeTypeInfo->mNext->mHash;
}
delete typeInstance->mCeTypeInfo->mNext;
typeInstance->mCeTypeInfo->mNext = NULL;
}
else
{
// Removed emissions
if (!typeInstance->mCeTypeInfo->mHash.IsZero())
mContext->RebuildDependentTypes_MidCompile(typeInstance, "comptime hash changed");
typeInstance->mCeTypeInfo->mEmitSourceMap.Clear();
typeInstance->mCeTypeInfo->mOnCompileMap.Clear();
typeInstance->mCeTypeInfo->mTypeIFaceMap.Clear();
typeInstance->mCeTypeInfo->mHash = Val128();
}
}
if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty()))
@ -5312,16 +5437,19 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
if ((typeDeclaration != NULL) && (typeDeclaration->mNameNode != NULL))
{
auto typeRefSource = typeDeclaration->mNameNode->GetParserData();
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL) && (typeRefSource != NULL) && (typeRefSource == mCompiler->mResolvePassData->mParser->mSourceData))
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mIsClassifying) && (typeRefSource != NULL))
{
BfSourceElementType elemType = BfSourceElementType_Type;
if (typeInstance->IsInterface())
elemType = BfSourceElementType_Interface;
else if (typeInstance->IsObject())
elemType = BfSourceElementType_RefType;
else if (typeInstance->IsStruct() || (typeInstance->IsTypedPrimitive() && !typeInstance->IsEnum()))
elemType = BfSourceElementType_Struct;
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(typeDeclaration->mNameNode, elemType);
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(typeDeclaration->mNameNode))
{
BfSourceElementType elemType = BfSourceElementType_Type;
if (typeInstance->IsInterface())
elemType = BfSourceElementType_Interface;
else if (typeInstance->IsObject())
elemType = BfSourceElementType_RefType;
else if (typeInstance->IsStruct() || (typeInstance->IsTypedPrimitive() && !typeInstance->IsEnum()))
elemType = BfSourceElementType_Struct;
sourceClassifier->SetElementType(typeDeclaration->mNameNode, elemType);
}
}
}
};
@ -8775,11 +8903,17 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
else
typeRefSource = typeRef->GetSourceData();
bool wantsFileNamespaceInfo = (((mCompiler->mResolvePassData->mSourceClassifier != NULL) || (isGetDefinition) || (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace)) &&
(typeRefSource != NULL) && (mCompiler->mResolvePassData->mParser != NULL) &&
(typeRefSource == mCompiler->mResolvePassData->mParser->mSourceData));
BfSourceClassifier* sourceClassifier = NULL;
if ((mCompiler->mResolvePassData->mIsClassifying) && (typeRefSource != NULL))
{
auto parser = typeRefSource->ToParser();
if (parser != NULL)
sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(parser);
}
bool wantsAllNamespaceInfo = (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace) && (mCompiler->mResolvePassData->mParser == NULL);
bool wantsFileNamespaceInfo = ((sourceClassifier != NULL) || (isGetDefinition) || (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace));
bool wantsAllNamespaceInfo = (mCompiler->mResolvePassData->mGetSymbolReferenceKind == BfGetSymbolReferenceKind_Namespace) && (mCompiler->mResolvePassData->mParsers.IsEmpty());
if (wantsFileNamespaceInfo || wantsAllNamespaceInfo)
{
@ -8841,14 +8975,14 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
while (auto qualifiedTypeRef = BfNodeDynCast<BfQualifiedTypeReference>(checkTypeRef))
{
if ((mCompiler->mResolvePassData->mSourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(qualifiedTypeRef->mRight, elemType);
if ((sourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
sourceClassifier->SetElementType(qualifiedTypeRef->mRight, elemType);
StringView leftString = qualifiedTypeRef->mLeft->ToStringView();
BfSizedAtomComposite leftComposite;
bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite);
if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
mCompiler->mResolvePassData->mSourceClassifier->SetHighestElementType(qualifiedTypeRef->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
if (sourceClassifier != NULL)
sourceClassifier->SetHighestElementType(qualifiedTypeRef->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
if (resolvedTypeInstance == NULL)
{
if ((isValid) && (mCompiler->mSystem->ContainsNamespace(leftComposite, mCurTypeInstance->mTypeDef->mProject)))
@ -8874,16 +9008,16 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
auto checkNameNode = namedTypeRef->mNameNode;
bool setType = false;
if ((mCompiler->mResolvePassData->mSourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
if ((sourceClassifier != NULL) && (checkTypeRef == headTypeRef) && (elemType != BfSourceElementType_Type))
{
if (auto qualifiedNameNode = BfNodeDynCast<BfQualifiedNameNode>(checkNameNode))
{
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(qualifiedNameNode->mRight, elemType);
sourceClassifier->SetElementType(qualifiedNameNode->mRight, elemType);
}
else
{
setType = true;
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(checkNameNode, elemType);
sourceClassifier->SetElementType(checkNameNode, elemType);
}
}
@ -8892,8 +9026,8 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
StringView leftString = qualifiedNameNode->mLeft->ToStringView();
BfSizedAtomComposite leftComposite;
bool isValid = mSystem->ParseAtomComposite(leftString, leftComposite);
if (mCompiler->mResolvePassData->mSourceClassifier != NULL)
mCompiler->mResolvePassData->mSourceClassifier->SetHighestElementType(qualifiedNameNode->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
if (sourceClassifier != NULL)
sourceClassifier->SetHighestElementType(qualifiedNameNode->mRight, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
if (resolvedTypeInstance == NULL)
{
if ((isValid) && (mCompiler->mSystem->ContainsNamespace(leftComposite, mCurTypeInstance->mTypeDef->mProject)))
@ -8913,9 +9047,9 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
}
checkNameNode = qualifiedNameNode->mLeft;
}
if ((mCompiler->mResolvePassData->mSourceClassifier != NULL) &&
if ((sourceClassifier != NULL) &&
((!setType) || (checkNameNode != namedTypeRef->mNameNode)))
mCompiler->mResolvePassData->mSourceClassifier->SetHighestElementType(checkNameNode, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
sourceClassifier->SetHighestElementType(checkNameNode, isNamespace ? BfSourceElementType_Namespace : BfSourceElementType_Type);
}
}
@ -8964,6 +9098,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy
else
break;
}
if ((baseNode != NULL) && (autoComplete->IsAutocompleteNode(baseNode)))
{
// We didn't have this mDefType check before - why? We always want to catch the FIRST definition,
@ -9348,8 +9483,10 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric
if ((typeInstance == NULL) && (useTypeDef == NULL))
{
BfProject* project = NULL;
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mParser != NULL))
project = mCompiler->mResolvePassData->mParser->mProject;
if ((mContext->mCurTypeState != NULL) && (mContext->mCurTypeState->mActiveProject != NULL))
project = mContext->mCurTypeState->mActiveProject;
else if ((mCompiler->mResolvePassData != NULL) && (!mCompiler->mResolvePassData->mParsers.IsEmpty()))
project = mCompiler->mResolvePassData->mParsers[0]->mProject;
BP_ZONE("System.FindTypeDef_2");
Array<BfAtomComposite> namespaceSearch;
@ -9535,7 +9672,7 @@ void BfModule::CheckTypeRefFixit(BfAstNode* typeRef, const char* appendName)
std::set<String> fixitNamespaces;
//TODO: Do proper value for numGenericArgs
mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParser->mProject, fixitNamespaces);
mSystem->FindFixitNamespaces(typeName, -1, mCompiler->mResolvePassData->mParsers[0]->mProject, fixitNamespaces);
int insertLoc = 0;
@ -9810,8 +9947,11 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
if (genericParamResult != NULL)
{
auto typeRefSource = identifierNode->GetSourceData();
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mSourceClassifier != NULL) && (typeRefSource != NULL) && (typeRefSource == mCompiler->mResolvePassData->mParser->mSourceData))
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(identifierNode, BfSourceElementType_GenericParam);
if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mIsClassifying) && (typeRefSource != NULL))
{
if (auto sourceClassifier = mCompiler->mResolvePassData->GetSourceClassifier(identifierNode))
sourceClassifier->SetElementType(identifierNode, BfSourceElementType_GenericParam);
}
if (genericParamResult->IsConstExprValue())
{

View file

@ -345,6 +345,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
gParserCount++;
mEmbedKind = BfSourceEmbedKind_None;
mUsingCache = false;
mParserData = NULL;
mAwaitingDelete = false;
@ -354,7 +355,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
mJumpTable = NULL;
mProject = bfProject;
mPassInstance = NULL;
mPassInstance = NULL;
mSourceClassifier = NULL;
mPrevRevision = NULL;
mNextRevision = NULL;
mOrigSrcLength = 0;
@ -375,7 +376,7 @@ BfParser::BfParser(BfSystem* bfSystem, BfProject* bfProject) : BfSource(bfSystem
mCompatMode = false;
mQuickCompatMode = false;
mLiteral.mWarnType = 0;
mDataId = -1;
mDataId = -1;
mTriviaStart = 0;
mParsingFailed = false;
@ -3820,6 +3821,11 @@ BF_EXPORT void BF_CALLTYPE BfParser_SetIsClassifying(BfParser* bfParser)
bfParser->mParserFlags = (BfParserFlag)(bfParser->mParserFlags | ParserFlag_Classifying);
}
BF_EXPORT void BF_CALLTYPE BfParser_SetEmbedKind(BfParser* bfParser, BfSourceEmbedKind embedKind)
{
bfParser->mEmbedKind = embedKind;
}
BF_EXPORT void BF_CALLTYPE BfParser_SetAutocomplete(BfParser* bfParser, int cursorIdx)
{
BF_ASSERT(bfParser->mParserData->mRefCount == -1);
@ -3972,7 +3978,8 @@ BF_EXPORT BfResolvePassData* BF_CALLTYPE BfParser_CreateResolvePassData(BfParser
{
auto bfResolvePassData = new BfResolvePassData();
bfResolvePassData->mResolveType = resolveType;
bfResolvePassData->mParser = bfParser;
if (bfParser != NULL)
bfResolvePassData->mParsers.Add(bfParser);
if ((bfParser != NULL) && ((bfParser->mParserFlags & ParserFlag_Autocomplete) != 0))
bfResolvePassData->mAutoComplete = new BfAutoComplete(resolveType, doFuzzyAutoComplete);
return bfResolvePassData;
@ -3980,6 +3987,9 @@ BF_EXPORT BfResolvePassData* BF_CALLTYPE BfParser_CreateResolvePassData(BfParser
BF_EXPORT bool BF_CALLTYPE BfParser_BuildDefs(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, bool fullRefresh)
{
if (bfParser->mCursorIdx != -1)
resolvePassData->mHasCursorIdx = true;
BP_ZONE("BfParser_BuildDefs");
int startFailIdx = bfPassInstance->mFailedIdx;
BfDefBuilder defBuilder(bfParser->mSystem);
@ -4007,6 +4017,51 @@ BF_EXPORT void BF_CALLTYPE BfParser_ClassifySource(BfParser* bfParser, BfSourceC
bfSourceClassifier.Visit(bfParser->mSidechannelRootNode);
}
BF_EXPORT void BF_CALLTYPE BfParser_CreateClassifier(BfParser* bfParser, BfPassInstance* bfPassInstance, BfResolvePassData* resolvePassData, BfSourceClassifier::CharData* charData)
{
resolvePassData->mIsClassifying = true;
bfParser->mSourceClassifier = new BfSourceClassifier(bfParser, charData);
bfParser->mSourceClassifier->mClassifierPassId = bfPassInstance->mClassifierPassId;
if ((resolvePassData->mParsers.IsEmpty()) || (bfParser != resolvePassData->mParsers[0]))
resolvePassData->mParsers.Add(bfParser);
bool doClassifyPass = (charData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
bfParser->mSourceClassifier->mEnabled = doClassifyPass;
bfParser->mSourceClassifier->mSkipMethodInternals = true;
bfParser->mSourceClassifier->mSkipTypeDeclarations = true;
if (charData != NULL)
{
if ((doClassifyPass) && (bfParser->mRootNode != NULL))
bfParser->mSourceClassifier->Visit(bfParser->mRootNode);
}
bfParser->mSourceClassifier->mSkipTypeDeclarations = false;
bfParser->mSourceClassifier->mSkipMethodInternals = false;
}
BF_EXPORT void BF_CALLTYPE BfParser_FinishClassifier(BfParser* bfParser, BfResolvePassData* resolvePassData)
{
if (bfParser->mSourceClassifier == NULL)
return;
bool doClassifyPass = (bfParser->mSourceClassifier->mCharData != NULL) && (resolvePassData->mResolveType <= BfResolveType_Autocomplete_HighPri);
if (doClassifyPass)
{
bfParser->mSourceClassifier->mIsSideChannel = false;
if (bfParser->mErrorRootNode != NULL)
bfParser->mSourceClassifier->Visit(bfParser->mErrorRootNode);
bfParser->mSourceClassifier->mIsSideChannel = true;
if (bfParser->mSidechannelRootNode != NULL)
bfParser->mSourceClassifier->Visit(bfParser->mSidechannelRootNode);
}
delete bfParser->mSourceClassifier;
bfParser->mSourceClassifier = NULL;
}
BF_EXPORT void BF_CALLTYPE BfParser_GenerateAutoCompletionFrom(BfParser* bfParser, int srcPosition)
{
BP_ZONE("BfParser_GenerateAutoCompletionFrom");

View file

@ -14,6 +14,7 @@ NS_BF_BEGIN
class BfPassInstance;
class BfProject;
class BfSourceClassifier;
enum BfSyntaxToken
{
@ -136,13 +137,20 @@ public:
void ReportMemory(MemReporter* memReporter);
};
enum BfDefineState
enum BfDefineState : int8
{
BfDefineState_FromProject,
BfDefineState_ManualSet,
BfDefineState_ManualUnset
};
enum BfSourceEmbedKind : int8
{
BfSourceEmbedKind_None,
BfSourceEmbedKind_Type,
BfSourceEmbedKind_Method
};
class BfParser : public BfSource
{
public:
@ -150,7 +158,9 @@ public:
bool mUsingCache;
BfPassInstance* mPassInstance;
BfSourceClassifier* mSourceClassifier;
String mFileName;
BfSourceEmbedKind mEmbedKind;
bool mAwaitingDelete;
bool mCompatMode; // Does C++ compatible parsing

View file

@ -6781,7 +6781,8 @@ BfAstNode* BfReducer::ReadTypeMember(BfAstNode* node, bool declStarted, int dept
// if (depth == 0)
// prevTypeMemberNodeStart.Set();
AssertCurrentNode(node);
if (mCurTypeDecl != NULL)
AssertCurrentNode(node);
BfTokenNode* refToken = NULL;
@ -8239,6 +8240,58 @@ BfAstNode* BfReducer::HandleTopLevel(BfBlock* node)
bool hadPrevFail = false;
bool isDone = !mVisitorPos.MoveNext();
auto parser = mSource->ToParser();
if ((parser != NULL) && (parser->mEmbedKind == BfSourceEmbedKind_Type))
{
while (!isDone)
{
auto node = mVisitorPos.GetCurrent();
if (node == prevNode)
{
// If we're stuck on an error and can't process any more nodes
break;
}
prevNode = node;
BfAstNode* typeMember = BfNodeDynCast<BfMemberDeclaration>(node);
if (typeMember == NULL)
{
SetAndRestoreValue<BfAstNode*> prevTypeMemberNodeStart(mTypeMemberNodeStart, node);
typeMember = ReadTypeMember(node);
}
//methodDeclaration->mDocumentation = FindDocumentation(methodDeclaration);
isDone = !mVisitorPos.MoveNext();
if (typeMember != NULL)
{
mVisitorPos.Write(typeMember);
}
}
}
if ((parser != NULL) && (parser->mEmbedKind == BfSourceEmbedKind_Method))
{
bool allowEndingExpression = false;
BfAstNode* nextNode = NULL;
while (!isDone)
{
BfAstNode* node = mVisitorPos.GetCurrent();
CreateStmtFlags flags = (CreateStmtFlags)(CreateStmtFlags_FindTrailingSemicolon | CreateStmtFlags_AllowLocalFunction);
if (allowEndingExpression)
flags = (CreateStmtFlags)(flags | CreateStmtFlags_AllowUnterminatedExpression);
auto statement = CreateStatement(node, flags);
if ((statement == NULL) && (mSource != NULL))
statement = mSource->CreateErrorNode(node);
isDone = !mVisitorPos.MoveNext();
if (statement != NULL)
mVisitorPos.Write(statement);
}
}
while (!isDone)
{
@ -10246,7 +10299,7 @@ void BfReducer::HandleTypeDeclaration(BfTypeDeclaration* typeDecl, BfAttributeDi
MEMBER_SET(typeDecl, mAttributes, attributes);
}
if (!IsNodeRelevant(deferredHeadNode, typeDecl))
if ((!IsNodeRelevant(deferredHeadNode, typeDecl)) && (!typeDecl->IsTemporary()))
{
typeDecl->mIgnoreDeclaration = true;
return;

View file

@ -18,9 +18,24 @@ BfResolvePassData::BfResolvePassData()
mSymbolTypeGenericParamIdx = -1;
mAutoComplete = NULL;
mSourceClassifier = NULL;
mResolveType = BfResolveType_None;
mParser = NULL;
mIsClassifying = false;
mHasCursorIdx = false;
}
BfResolvePassData::~BfResolvePassData()
{
for (auto& emitEntryKV : mEmitEmbedEntries)
{
auto parser = emitEntryKV.mValue.mParser;
if (parser != NULL)
{
delete parser->mSourceClassifier;
parser->mSourceClassifier = NULL;
parser->mParserFlags = ParserFlag_None;
parser->mCursorCheckIdx = -1;
}
}
}
void BfResolvePassData::RecordReplaceNode(BfParserData* parser, int srcStart, int srcLen)
@ -179,3 +194,20 @@ void BfResolvePassData::HandleNamespaceReference(BfAstNode* node, const BfAtomCo
RecordReplaceNode(baseNode);
}
}
BfSourceClassifier* BfResolvePassData::GetSourceClassifier(BfAstNode* astNode)
{
if (!mIsClassifying)
return NULL;
auto parser = astNode->GetParser();
if (parser == NULL)
return NULL;
return parser->mSourceClassifier;
}
BfSourceClassifier* BfResolvePassData::GetSourceClassifier(BfParser* parser)
{
if (!mIsClassifying)
return NULL;
return parser->mSourceClassifier;
}

View file

@ -2,6 +2,7 @@
#include "BfSystem.h"
#include "BfResolvedTypeUtils.h"
#include "BfSourceClassifier.h"
NS_BF_BEGIN
@ -40,17 +41,33 @@ enum BfGetSymbolReferenceKind
BfGetSymbolReferenceKind_Namespace
};
class BfEmitEmbedEntry
{
public:
int mCursorIdx;
int mRevision;
BfParser* mParser;
Array<BfSourceClassifier::CharData> mCharData;
public:
BfEmitEmbedEntry()
{
mCursorIdx = -1;
mRevision = -1;
mParser = NULL;
}
};
class BfResolvePassData
{
public:
BfResolveType mResolveType;
BfParser* mParser;
Array<BfParser*> mParsers;
BfAutoComplete* mAutoComplete;
Array<BfTypeDef*> mAutoCompleteTempTypes; // Contains multiple values when we have nested types
Dictionary<BfTypeDef*, BfStaticSearch> mStaticSearchMap;
Dictionary<BfTypeDef*, BfInternalAccessSet> mInternalAccessMap;
BfSourceClassifier* mSourceClassifier;
Dictionary<BfTypeDef*, BfInternalAccessSet> mInternalAccessMap;
Array<BfAstNode*> mExteriorAutocompleteCheckNodes;
BfGetSymbolReferenceKind mGetSymbolReferenceKind;
@ -64,11 +81,15 @@ public:
int mSymbolReferencePropertyIdx;
int mSymbolMethodGenericParamIdx;
int mSymbolTypeGenericParamIdx;
bool mIsClassifying;
bool mHasCursorIdx;
typedef Dictionary<BfParserData*, String> FoundSymbolReferencesParserDataMap;
FoundSymbolReferencesParserDataMap mFoundSymbolReferencesParserData;
//std::vector<BfIdentifierNode*> mSymbolReferenceIdentifiers;
Dictionary<String, BfEmitEmbedEntry> mEmitEmbedEntries;
public:
void RecordReplaceNode(BfParserData* parser, int srcStart, int srcLen);
void RecordReplaceNode(BfAstNode* node);
@ -76,6 +97,7 @@ public:
public:
BfResolvePassData();
~BfResolvePassData();
void HandleLocalReference(BfIdentifierNode* identifier, BfTypeDef* typeDef, BfMethodDef* methodDef, int localVarIdx);
void HandleLocalReference(BfIdentifierNode* identifier, BfIdentifierNode* origNameNode, BfTypeDef* typeDef, BfMethodDef* methodDef, int localVarIdx);
@ -87,6 +109,8 @@ public:
void HandleTypeReference(BfAstNode* node, BfTypeDef* typeDef);
void HandleNamespaceReference(BfAstNode* node, const BfAtomComposite& namespaceName);
BfSourceClassifier* GetSourceClassifier(BfAstNode* astNode);
BfSourceClassifier* GetSourceClassifier(BfParser* parser);
//void ReplaceIdentifiers();
};

View file

@ -57,7 +57,7 @@ enum BfTypeNameFlags : uint16
BfTypeNameFlag_InternalName = 0x100, // Use special delimiters to remove ambiguities (ie: '+' for inner types)
BfTypeNameFlag_HideGlobalName = 0x200,
BfTypeNameFlag_ExtendedInfo = 0x400,
BfTypeNameFlag_ShortConst = 0x800
BfTypeNameFlag_ShortConst = 0x800
};
enum BfMethodNameFlags : uint8
@ -1886,12 +1886,6 @@ public:
void ReportMemory(MemReporter* memReporter);
};
class BfCeTypeEmitEntry
{
public:
String mEmitData;
};
class BfCeTypeInfo;
// Instance of struct or class
@ -2543,6 +2537,7 @@ class BfCustomAttribute
{
public:
BfAttributeDirective* mRef;
BfTypeDef* mDeclaringType;
BfTypeInstance* mType;
BfMethodDef* mCtor;
Array<BfIRValue> mCtorArgs;

View file

@ -30,9 +30,19 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
static BfpFile* fp[10] = { NULL };
static bool openedLog[10] = { false };
static int64 logSize[10] = { 0 };
static int logCount[10] = { 0 };
if (logSize[fileIdx] >= 1 * 1024 * 1024 * 1024)
{
BfpFile_Release(fp[fileIdx]);
openedLog[fileIdx] = false;
}
if (!openedLog[fileIdx])
{
openedLog[fileIdx] = true;
logSize[fileIdx] = 0;
char exeName[512];
int len = 512;
@ -42,10 +52,16 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
int dotPos = (int)dbgName.IndexOf('.');
if (dotPos != -1)
dbgName.RemoveToEnd(dotPos);
dbgName += StrFormat("_%d.txt", fileIdx);
dbgName += StrFormat("_%d", fileIdx);
if (logCount[fileIdx] > 0)
dbgName += 'B';
dbgName += ".txt";
fp[fileIdx] = BfpFile_Create(dbgName.c_str(), BfpFileCreateKind_CreateAlways, (BfpFileCreateFlags)(BfpFileCreateFlag_Write | BfpFileCreateFlag_NoBuffering | BfpFileCreateFlag_ShareRead), BfpFileAttribute_Normal, NULL);
onNewLine[fileIdx] = true;
logCount[fileIdx]++;
}
if (fp[fileIdx] == NULL)
return;
@ -74,6 +90,8 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
{
if (strOfs + numChars > 0)
{
logSize[fileIdx] += strOfs + numChars;
BfpFile_Write(fp[fileIdx], lineStr, strOfs + numChars, -1, NULL);
if (lineStr[strOfs + numChars - 1] == '\n')
onNewLine[fileIdx] = true;
@ -98,6 +116,7 @@ void Beefy::DoBfLog(int fileIdx, const char* fmt ...)
else
onNewLine[fileIdx] = false;
logSize[fileIdx] += aResult.length();
BfpFile_Write(fp[fileIdx], aResult.c_str(), aResult.length(), -1, NULL);
}
@ -1137,8 +1156,9 @@ bool BfPassInstance::PopOutString(String* outString)
bool BfPassInstance::WantsRangeRecorded(BfSourceData* bfSource, int srcIdx, int srcLen, bool isWarning, bool isDeferred)
{
if ((mFilterErrorsTo != NULL) && (bfSource != mFilterErrorsTo->mSourceData))
if ((!mFilterErrorsTo.IsEmpty()) && (!mFilterErrorsTo.Contains(bfSource)))
return false;
if (bfSource == NULL)
return true;
@ -3964,6 +3984,28 @@ BF_EXPORT void BfResolvePassData_SetDocumentationRequest(BfResolvePassData* reso
resolvePassData->mAutoComplete->mDocumentationEntryName = entryName;
}
BF_EXPORT void BfResolvePassData_AddEmitEmbed(BfResolvePassData* resolvePassData, char* typeName, int32 cursorIdx)
{
BfEmitEmbedEntry emitEmbedEntry;
emitEmbedEntry.mCursorIdx = cursorIdx;
resolvePassData->mEmitEmbedEntries[typeName] = emitEmbedEntry;
}
BF_EXPORT void* BfResolvePassData_GetEmitEmbedData(BfResolvePassData* resolvePassData, char* typeName, int* charCount, int* revision)
{
*charCount = -1;
*revision = 0;
BfEmitEmbedEntry* emitEmbedEntry = NULL;
if (!resolvePassData->mEmitEmbedEntries.TryGetValue(typeName, &emitEmbedEntry))
return NULL;
if (emitEmbedEntry->mParser == NULL)
return NULL;
*revision = emitEmbedEntry->mRevision;
*charCount = emitEmbedEntry->mParser->mSrcLength;
return emitEmbedEntry->mParser->mSourceClassifier->mCharData;
}
BF_EXPORT BfParser* BF_CALLTYPE BfSystem_CreateParser(BfSystem* bfSystem, BfProject* bfProject)
{
return bfSystem->CreateParser(bfProject);

View file

@ -38,8 +38,8 @@ namespace llvm
NS_BF_BEGIN
class BfSystem;
class BfTypeReference;
class BfCompiler;
class BfTypeReference;
class BfProject;
class BfTypeDef;
@ -157,7 +157,7 @@ enum BfCompilerOptionFlags
BfCompilerOptionFlag_EnableSideStack = 0x1000,
BfCompilerOptionFlag_EnableHotSwapping = 0x2000,
BfCompilerOptionFlag_IncrementalBuild = 0x4000,
BfCompilerOptionFlag_DebugAlloc = 0x8000,
BfCompilerOptionFlag_DebugAlloc = 0x8000,
BfCompilerOptionFlag_OmitDebugHelpers = 0x10000,
BfCompilerOptionFlag_NoFramePointerElim = 0x20000,
BfCompilerOptionFlag_ArithmeticChecks = 0x40000,
@ -1412,6 +1412,7 @@ public:
const int sMaxErrors = 1000;
BfSystem* mSystem;
BfCompiler* mCompiler;
bool mTrimMessagesToCursor;
int mFailedIdx;
int mWarnIdx;
@ -1426,7 +1427,7 @@ public:
bool mLastWasDisplayed;
bool mLastWasAdded;
uint8 mClassifierPassId;
BfParser* mFilterErrorsTo;
HashSet<BfSourceData*> mFilterErrorsTo;
bool mHadSignatureChanges;
public:
@ -1436,13 +1437,13 @@ public:
mFailedIdx = 0;
mWarnIdx = 0;
mSystem = bfSystem;
mCompiler = NULL;
mLastWasDisplayed = false;
mLastWasAdded = false;
mClassifierPassId = 0;
mWarningCount = 0;
mDeferredErrorCount = 0;
mIgnoreCount = 0;
mFilterErrorsTo = NULL;
mIgnoreCount = 0;
mHadSignatureChanges = false;
}

View file

@ -1,4 +1,5 @@
#include "BfUtil.h"
#include "BeefySysLib/util/Hash.h"
USING_NS_BF;
@ -52,6 +53,26 @@ void* Beefy::ZeroedAlloc(int size)
return data;
}
String Beefy::EncodeFileName(const StringImpl& fromStr)
{
String path;
if (fromStr.mLength > 80)
path.Insert(0, fromStr.mPtr, 80);
else
path += fromStr;
path.Replace("$", "\\");
for (auto& c : path)
{
if ((!::isalnum((uint8)c)) && (c != '_'))
c = '-';
}
path += "_";
path += HashEncode128(Hash128(fromStr.c_str(), (int)fromStr.length()));
return path;
}
uint64 stouln(const char* str, int len)
{
uint64 val = 0;

View file

@ -283,6 +283,8 @@ String EncodeDataPtr(uint32 addr, bool doPrefix);
String EncodeDataPtr(uint64 addr, bool doPrefix);
String EncodeDataPtr(int addr, bool doPrefix);
void* ZeroedAlloc(int size);
String EncodeFileName(const StringImpl& fromStr); // Make short, only legal chars, with a hash at end
/*template <typename T>
T* ZeroedAlloc()
{

View file

@ -938,7 +938,7 @@ String CeDebugger::DoEvaluate(CePendingExpr* pendingExpr, bool inCompilerThread)
autoComplete.mSystem = module->mSystem;
BfResolvePassData resolvePass;
resolvePass.mParser = pendingExpr->mParser;
resolvePass.mParsers.Add(pendingExpr->mParser);
resolvePass.mAutoComplete = &autoComplete;
SetAndRestoreValue<BfResolvePassData*> prevResolvePass;
@ -4925,3 +4925,8 @@ bool CeDebugger::IsOnDemandDebugger()
{
return true;
}
bool CeDebugger::GetEmitSource(const StringImpl& filePath, String& outText)
{
return false;
}

View file

@ -402,6 +402,7 @@ public:
virtual Profiler* PopProfiler() override; // Profiler requested by target program
virtual void ReportMemory(MemReporter* memReporter) override;
virtual bool IsOnDemandDebugger() override;
virtual bool GetEmitSource(const StringImpl& filePath, String& outText) override;
};
NS_BF_END

View file

@ -972,11 +972,42 @@ public:
}
};
enum BfCeTypeEmitSourceKind
{
BfCeTypeEmitSourceKind_Unknown,
BfCeTypeEmitSourceKind_Type,
BfCeTypeEmitSourceKind_Method
};
class BfCeTypeEmitSource
{
public:
BfCeTypeEmitSourceKind mKind;
int mSrcStart;
int mSrcEnd;
public:
BfCeTypeEmitSource()
{
mKind = BfCeTypeEmitSourceKind_Unknown;
mSrcStart = -1;
mSrcEnd = -1;
}
};
class BfCeTypeEmitEntry
{
public:
String mEmitData;
};
class BfCeTypeInfo
{
public:
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
Dictionary<int64, BfCeTypeEmitSource> mEmitSourceMap; // key is (extension<<32)|charId
Array<int> mPendingInterfaces;
Dictionary<CeRebuildKey, CeRebuildValue> mRebuildMap;
Val128 mHash;

View file

@ -2190,6 +2190,7 @@ DbgModule::DbgModule(DebugTarget* debugTarget) : mDefaultCompileUnit(this)
mStartTypeIdx = 0;
mEndTypeIdx = 0;
mHotIdx = 0;
mId = 0;
mStartSubprogramIdx = 0;
mEndSubprogramIdx = 0;
mCodeAddress = NULL;
@ -7139,6 +7140,9 @@ DbgFileExistKind DbgModule::CheckSourceFileExist(const StringImpl& path)
{
DbgFileExistKind existsKind = DbgFileExistKind_NotFound;
if (path.StartsWith("$Emit"))
return DbgFileExistKind_Found;
if (FileExists(path))
existsKind = DbgFileExistKind_Found;

View file

@ -1146,6 +1146,7 @@ public:
bool mMayBeOld; // If we had to load debug info from the SymCache or a SymServer then it may be old
bool mDeleting;
bool mFailed;
int mId;
int mHotIdx;
String mFilePath;
String mDisplayName;
@ -1226,6 +1227,7 @@ public:
virtual void ProcessDebugInfo();
virtual bool CanGetOldSource() { return false; }
virtual String GetOldSourceCommand(const StringImpl& path) { return ""; }
virtual bool GetEmitSource(const StringImpl& filePath, String& outText) { return false; }
virtual bool DbgIsStrMutable(const char* str) { return true; } // Always assume its a copy
virtual addr_target LocateSymbol(const StringImpl& name) { return 0; }
virtual DbgSubprogram* FindSubprogram(DbgType* dbgType, const char* methodName);

View file

@ -1609,6 +1609,19 @@ BF_EXPORT const char* BF_CALLTYPE Debugger_GetHotResolveData(uint8* outTypeData,
return outString.c_str();
}
BF_EXPORT const char* BF_CALLTYPE Debugger_GetEmitSource(char* inFilePath)
{
AutoCrit autoCrit(gDebugManager->mCritSect);
String& outString = *gTLStrReturn.Get();
outString.Clear();
if (!gDebugger->GetEmitSource(inFilePath, outString))
return NULL;
return outString.c_str();
}
BF_EXPORT NetResult* HTTP_GetFile(char* url, char* destPath)
{
AutoCrit autoCrit(gDebugManager->mNetManager->mThreadPool.mCritSect);

View file

@ -162,14 +162,14 @@ DbgModule* DebugTarget::Init(const StringImpl& launchPath, const StringImpl& tar
}
CheckTargetBinary(dwarf);
mDbgModules.push_back(dwarf);
AddDbgModule(dwarf);
return dwarf;
}
void DebugTarget::CreateEmptyTarget()
{
auto emptyTarget = new DbgModule(this);
mDbgModules.push_back(emptyTarget);
AddDbgModule(emptyTarget);
mTargetBinary = emptyTarget;
mLaunchBinary = emptyTarget;
}
@ -198,7 +198,7 @@ DbgModule* DebugTarget::HotLoad(const StringImpl& fileName, int hotIdx)
delete dwarf;
return NULL;
}
mDbgModules.push_back(dwarf);
AddDbgModule(dwarf);
return dwarf;
}
@ -217,7 +217,7 @@ DbgModule* DebugTarget::SetupDyn(const StringImpl& filePath, DataStream* stream,
delete dwarf;
return NULL;
}
mDbgModules.push_back(dwarf);
AddDbgModule(dwarf);
dwarf->mDisplayName = GetFileName(filePath);
dwarf->mOrigImageData = new DbgModuleMemoryCache(dwarf->mImageBase, dwarf->mImageSize);
@ -905,6 +905,12 @@ void DebugTarget::GetCompilerSettings()
}
}
void DebugTarget::AddDbgModule(DbgModule* dbgModule)
{
static int id = 0;
dbgModule->mId = ++id;
mDbgModules.Add(dbgModule);
}
#if 1
bool DebugTarget::RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC)

View file

@ -37,10 +37,8 @@ public:
int mLastHotHeapCleanIdx;
String mTargetPath;
DbgModule* mLaunchBinary;
DbgModule* mTargetBinary;
//DbgModule* m
Array<DbgModule*> mDbgModules;
//DbgModule* mLastDWARF;
DbgModule* mTargetBinary;
Array<DbgModule*> mDbgModules;
HashSet<DbgSrcFile*> mPendingSrcFileRehup; // Waiting to remove old/invalid line info
BumpAllocator mAlloc;
@ -57,12 +55,11 @@ public:
Array<DwCommonFrameDescriptor*> mCommonFrameDescriptors;
std::map<addr_target, DwFrameDescriptor> mDwFrameDescriptorMap;
std::map<addr_target, COFFFrameDescriptorEntry> mCOFFFrameDescriptorMap;
//Array<DbgSrcFile*> mSrcFiles;
Dictionary<String, DbgSrcFile*> mSrcFiles;
Dictionary<String, String> mLocalToOrigSrcMap;
protected:
protected:
bool RollBackStackFrame_ExceptionDirectory(addr_target findPC, CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC);
bool RollBackStackFrame_ExceptionDirectory(CPURegisters* registers, addr_target* outReturnAddressLoc, bool& alreadyRolledBackPC);
bool RollBackStackFrame_DwFrameDescriptor(CPURegisters* registers, addr_target* outReturnAddressLoc);
@ -76,6 +73,7 @@ public:
DebugTarget(WinDebugger* debugger);
~DebugTarget();
void AddDbgModule(DbgModule* dbgModule);
DbgModule* Init(const StringImpl& launchPath, const StringImpl& targetPath, intptr imageBase = 0);
void SetupTargetBinary();
void CheckTargetBinary(DbgModule* module);

View file

@ -351,7 +351,8 @@ public:
virtual Profiler* StartProfiling() = 0;
virtual Profiler* PopProfiler() = 0; // Profiler requested by target program
virtual void ReportMemory(MemReporter* memReporter) = 0;
virtual bool IsOnDemandDebugger() = 0;
virtual bool IsOnDemandDebugger() = 0;
virtual bool GetEmitSource(const StringImpl& filePath, String& outText) = 0;
};
class Profiler

View file

@ -76,7 +76,7 @@ MiniDumpDebugger::MiniDumpDebugger(DebugManager* debugManager, DbgMiniDump* mini
auto miscEntry = &mMiniDump->GetData<char>(module.MiscRecord.Rva);
mDebugTarget->mDbgModules.Add(dbgModule);
mDebugTarget->AddDbgModule(dbgModule);
//TESTING
/*{

View file

@ -1531,6 +1531,24 @@ void WinDebugger::ReportMemory(MemReporter* memReporter)
mDebugTarget->ReportMemory(memReporter);
}
bool WinDebugger::GetEmitSource(const StringImpl& filePath, String& outText)
{
if (!filePath.StartsWith("$Emit"))
return false;
int dollarPos = filePath.IndexOf('$', 1);
String numStr = filePath.Substring(5, dollarPos - 5);
int id = atoi(numStr.c_str());
for (auto dbgModule : mDebugTarget->mDbgModules)
{
if (dbgModule->mId == id)
return dbgModule->GetEmitSource(filePath, outText);
}
return false;
}
void WinDebugger::ModuleChanged(DbgModule* dbgModule)
{
mDebugManager->mOutMessages.push_back(String("dbgInfoLoaded ") + dbgModule->mFilePath);
@ -11092,6 +11110,21 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
*outFlags |= FrameFlags_WasHotReplaced;
};
auto _FixFilePath = [&](DbgModule* dbgModule)
{
if (outFile == NULL)
return;
if (outFile->StartsWith("$Emit"))
{
int dollarPos = outFile->IndexOf('$', 1);
if (dollarPos == -1)
return;
outFile->Insert(dollarPos, StrFormat("%d", dbgModule->mId));
}
};
if (wdStackFrame->mInInlineMethod)
{
WdStackFrame* nextStackFrame = mCallStack[actualStackFrameIdx - 1];
@ -11122,6 +11155,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
*outLanguage = callingSubProgram->mCompileUnit->mLanguage;
auto srcFile = callingSrcFile;
*outFile = srcFile->GetLocalPath();
_CheckHashSrcFile(*outFile, subProgram->mCompileUnit->mDbgModule, srcFile);
if (*outLine == callingLineData->mLine)
*outColumn = callingLineData->mColumn;
@ -11131,7 +11165,8 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
DbgModule* dbgModule = wdStackFrame->mSubProgram->mCompileUnit->mDbgModule;
DbgModule* linkedModule = dbgModule->GetLinkedModule();
if (!linkedModule->mDisplayName.empty())
name = linkedModule->mDisplayName + "!" + name;
name = linkedModule->mDisplayName + "!" + name;
_FixFilePath(dbgModule);
return name;
}
@ -11211,10 +11246,12 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
*outDefLineEnd = dwEndLineData->mLine;
}
_FixFilePath(dbgModule);
return demangledName;
}
else
{
_FixFilePath(dbgModule);
return demangledName + StrFormat("+0x%X", pcAddress - dwSubprogram->mBlock.mLowPC);
}
}
@ -11222,7 +11259,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
{
String symbolName;
addr_target offset;
DbgModule* dbgModule;
DbgModule* dbgModule = NULL;
if (mDebugTarget->FindSymbolAt(pcAddress, &symbolName, &offset, &dbgModule))
{
if (dbgModule->HasPendingDebugInfo())
@ -11242,6 +11279,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
String demangledName = BfDemangler::Demangle(symbolName, DbgLanguage_Unknown);
if (!linkedModule->mDisplayName.empty())
demangledName = linkedModule->mDisplayName + "!" + demangledName;
_FixFilePath(dbgModule);
return demangledName + StrFormat("+0x%X", offset);
}
}
@ -11257,6 +11295,7 @@ String WinDebugger::GetStackFrameInfo(int stackFrameIdx, intptr* addr, String* o
String outName = EncodeDataPtr(pcAddress, true);
if ((linkedModule != NULL) && (!linkedModule->mDisplayName.empty()))
outName = linkedModule->mDisplayName + "!" + outName;
_FixFilePath(dbgModule);
return outName;
}

View file

@ -657,10 +657,11 @@ public:
void AddProfiler(DbgProfiler* profiler);
void RemoveProfiler(DbgProfiler* profiler);
virtual void ReportMemory(MemReporter* memReporter) override;
virtual void ReportMemory(MemReporter* memReporter) override;
virtual bool IsOnDemandDebugger() override { return false; }
virtual bool IsMiniDumpDebugger() { return false; }
virtual bool GetEmitSource(const StringImpl& filePath, String& outText);
};
template<typename T> bool WinDebugger::WriteMemory(intptr addr, T val)