From 8e9d7ed4c47b4b4fd9e1dbb661b5a24a87a5f93d Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 25 Feb 2021 10:14:22 -0800 Subject: [PATCH] Lost changes --- .../Beefy2D/src/theme/dark/DarkListView.bf | 7 + BeefLibs/Beefy2D/src/widgets/KeyCode.bf | 18 + BeefLibs/Beefy2D/src/widgets/TabbedView.bf | 9 +- BeefLibs/SDL2/src/SDL2.bf | 2 +- BeefLibs/SDL2/src/SDL2_ttf.bf | 2 +- BeefLibs/corlib/src/IO/OpenFileDialog.bf | 3 +- BeefySysLib/platform/win/Platform.cpp | 5 + BeefySysLib/util/MultiHashSet.h | 27 +- IDE/dist/lib/gen/src/Program.bf | 3 +- IDE/src/BuildContext.bf | 89 ++-- IDE/src/Debugger/DebugManager.bf | 3 +- IDE/src/IDEApp.bf | 260 +++++++---- IDE/src/ScriptManager.bf | 2 +- IDE/src/ui/ClassViewPanel.bf | 14 +- IDE/src/ui/DisassemblyPanel.bf | 2 +- IDE/src/ui/ErrorsPanel.bf | 10 +- IDE/src/ui/HoverWatch.bf | 21 +- IDE/src/ui/ImmediateWidget.bf | 36 +- IDE/src/ui/MemoryPanel.bf | 22 +- IDE/src/ui/ProjectPanel.bf | 5 +- IDE/src/ui/SourceEditWidgetContent.bf | 6 +- IDE/src/ui/SourceViewPanel.bf | 9 +- IDE/src/ui/WatchPanel.bf | 4 +- IDEHelper/Backend/BeIRCodeGen.cpp | 6 +- IDEHelper/Backend/BeMCContext.cpp | 6 +- IDEHelper/Compiler/BfCodeGen.cpp | 3 +- IDEHelper/Compiler/BfCompiler.cpp | 87 ++-- IDEHelper/Compiler/BfCompiler.h | 5 +- IDEHelper/Compiler/BfConstResolver.cpp | 31 +- IDEHelper/Compiler/BfConstResolver.h | 9 +- IDEHelper/Compiler/BfContext.cpp | 25 +- IDEHelper/Compiler/BfContext.h | 4 +- IDEHelper/Compiler/BfDefBuilder.cpp | 54 +-- IDEHelper/Compiler/BfExprEvaluator.cpp | 213 +++++---- IDEHelper/Compiler/BfIRBuilder.cpp | 75 ++-- IDEHelper/Compiler/BfIRBuilder.h | 5 +- IDEHelper/Compiler/BfIRCodeGen.cpp | 36 +- IDEHelper/Compiler/BfModule.cpp | 405 ++++++++++++------ IDEHelper/Compiler/BfModule.h | 24 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 213 ++++++--- IDEHelper/Compiler/BfPrinter.cpp | 46 +- IDEHelper/Compiler/BfReducer.cpp | 6 +- IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 132 +++--- IDEHelper/Compiler/BfResolvedTypeUtils.h | 14 +- IDEHelper/Compiler/BfSourceClassifier.cpp | 44 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 20 +- IDEHelper/Compiler/BfSystem.cpp | 34 +- IDEHelper/Compiler/BfSystem.h | 4 +- IDEHelper/Compiler/CeMachine.cpp | 36 +- IDEHelper/Debugger.h | 1 + IDEHelper/NetManager.cpp | 127 +++--- IDEHelper/Tests/src/Comptime.bf | 22 + IDEHelper/Tests/src/Extensions.bf | 46 ++ IDEHelper/Tests/src/Generics2.bf | 10 + IDEHelper/Tests/src/Reflection.bf | 66 +-- IDEHelper/WinDebugger.cpp | 5 + 56 files changed, 1579 insertions(+), 794 deletions(-) diff --git a/BeefLibs/Beefy2D/src/theme/dark/DarkListView.bf b/BeefLibs/Beefy2D/src/theme/dark/DarkListView.bf index 7cfd7388..f433f187 100644 --- a/BeefLibs/Beefy2D/src/theme/dark/DarkListView.bf +++ b/BeefLibs/Beefy2D/src/theme/dark/DarkListView.bf @@ -796,6 +796,13 @@ namespace Beefy.theme.dark mDragKind = .None; } + if (Math.Abs(dY) < mSelfHeight * 0.21f) + { + mDragKind = .None; + mDragTarget = null; + return; + } + delete mCurDragEvent; mCurDragEvent = new DragEvent(); mCurDragEvent.mX = x; diff --git a/BeefLibs/Beefy2D/src/widgets/KeyCode.bf b/BeefLibs/Beefy2D/src/widgets/KeyCode.bf index 400b1c03..4369d2a3 100644 --- a/BeefLibs/Beefy2D/src/widgets/KeyCode.bf +++ b/BeefLibs/Beefy2D/src/widgets/KeyCode.bf @@ -106,6 +106,24 @@ namespace Beefy.widgets extension KeyCode { + public bool IsModifier + { + get + { + switch (this) + { + case .LWin, + .RWin, + .Alt, + .Control, + .Command: + return true; + default: + return false; + } + } + } + public static Result Parse(StringView str) { if (str.Length == 1) diff --git a/BeefLibs/Beefy2D/src/widgets/TabbedView.bf b/BeefLibs/Beefy2D/src/widgets/TabbedView.bf index 84904080..59e00f54 100644 --- a/BeefLibs/Beefy2D/src/widgets/TabbedView.bf +++ b/BeefLibs/Beefy2D/src/widgets/TabbedView.bf @@ -200,7 +200,8 @@ namespace Beefy.widgets { return (mTabbedView.mParentDockingFrame.mParentDockingFrame == null) && (mTabbedView.mParentDockingFrame.GetDockedWindowCount() == 1) && - (mTabbedView.GetTabCount() == 1); + (mTabbedView.GetTabCount() == 1) && + mTabbedView.mAutoClose; } void WindowDragLostFocusHandler(BFWindow window, BFWindow newFocus) @@ -237,7 +238,7 @@ namespace Beefy.widgets 300, 500, BFWindowBase.Flags.Border | BFWindowBase.Flags.ThickFrame | BFWindowBase.Flags.Resizable | BFWindowBase.Flags.SysMenu | BFWindowBase.Flags.Caption | BFWindowBase.Flags.Minimize | BFWindowBase.Flags.ToolWindow | BFWindowBase.Flags.TopMost | - BFWindowBase.Flags.UseParentMenu, + BFWindowBase.Flags.UseParentMenu | BFWindowBase.Flags.Maximize, subFrame); Dock(subFrame, null, DockingFrame.WidgetAlign.Top); //subFrame.AddDockedWidget(fourthTabbedView, null, DockingFrame.WidgetAlign.Left, false); @@ -288,7 +289,7 @@ namespace Beefy.widgets if ((refWidget != null) && (refWidget.mWidgetWindow != mWidgetWindow) && (mWidgetWindow != null)) mWidgetWindow.SetForeground(); - if (mTabbedView.GetTabCount() == 1) + if ((mTabbedView.GetTabCount() == 1) && mTabbedView.mAutoClose) { mTabbedView.Dock(frame, refWidget, align); return; @@ -327,7 +328,7 @@ namespace Beefy.widgets tabbedView.Dock(frame, refWidget, align); } - if (prevTabbedView.GetTabCount() == 0) + if ((prevTabbedView.GetTabCount() == 0) && prevTabbedView.mAutoClose) { prevTabbedView.mParentDockingFrame.RemoveDockedWidget(prevTabbedView); } diff --git a/BeefLibs/SDL2/src/SDL2.bf b/BeefLibs/SDL2/src/SDL2.bf index 17476e46..33e4f036 100644 --- a/BeefLibs/SDL2/src/SDL2.bf +++ b/BeefLibs/SDL2/src/SDL2.bf @@ -746,7 +746,7 @@ namespace SDL2 public static extern int32 GetDisplayMode(int32 displayIndex, int32 modeIndex, out SDL_DisplayMode mode); /* Available in 2.0.5 or higher */ - [LinkName("SDL_GetDisplayMode")] + [LinkName("SDL_GetDisplayUsableBounds")] public static extern int SDL_GetDisplayUsableBounds(int displayIndex, out Rect rect); [LinkName("SDL_GetNumDisplayModes")] diff --git a/BeefLibs/SDL2/src/SDL2_ttf.bf b/BeefLibs/SDL2/src/SDL2_ttf.bf index 699f45fd..feffb8b8 100644 --- a/BeefLibs/SDL2/src/SDL2_ttf.bf +++ b/BeefLibs/SDL2/src/SDL2_ttf.bf @@ -315,4 +315,4 @@ namespace SDL2 int index ); } -} +} \ No newline at end of file diff --git a/BeefLibs/corlib/src/IO/OpenFileDialog.bf b/BeefLibs/corlib/src/IO/OpenFileDialog.bf index 8c32cbc3..bb8cb5f2 100644 --- a/BeefLibs/corlib/src/IO/OpenFileDialog.bf +++ b/BeefLibs/corlib/src/IO/OpenFileDialog.bf @@ -119,7 +119,8 @@ namespace System.IO DeleteAndNullify!(mTitle); DeleteAndNullify!(mInitialDir); DeleteAndNullify!(mDefaultExt); - DeleteAndNullify!(mFileNames); + DeleteContainerAndItems!(mFileNames); + mFileNames = null; DeleteAndNullify!(mFilter); mFilterIndex = 1; mSupportMultiDottedExtensions = false; diff --git a/BeefySysLib/platform/win/Platform.cpp b/BeefySysLib/platform/win/Platform.cpp index 18d1ae94..0d82acc0 100644 --- a/BeefySysLib/platform/win/Platform.cpp +++ b/BeefySysLib/platform/win/Platform.cpp @@ -1,3 +1,8 @@ +#define INITKNOWNFOLDERS +#include +#include +#undef INITKNOWNFOLDERS + #pragma warning(disable:4065) #pragma warning(disable:4996) diff --git a/BeefySysLib/util/MultiHashSet.h b/BeefySysLib/util/MultiHashSet.h index 6e9548a9..5ff9efc7 100644 --- a/BeefySysLib/util/MultiHashSet.h +++ b/BeefySysLib/util/MultiHashSet.h @@ -164,17 +164,30 @@ public: { auto newHashHeads = (Entry**)TFuncs::AllocateZero(sizeof(Entry*) * newHashSize, alignof(Entry*)); + SizedArray entryList; + for (int hashIdx = 0; hashIdx < mHashSize; hashIdx++) { Entry* checkEntry = mHashHeads[hashIdx]; - while (checkEntry != NULL) + if (checkEntry != NULL) { - auto nextEntry = checkEntry->mNext; - int newHashIdx = (checkEntry->mHash & 0x7FFFFFFF) % newHashSize; - checkEntry->mNext = newHashHeads[newHashIdx]; - newHashHeads[newHashIdx] = checkEntry; - - checkEntry = nextEntry; + // We want to keep elements with equal hashes in their insert order so we need to + // iterate through the linked list in reverse + entryList.Clear(); + + while (checkEntry != NULL) + { + entryList.Add(checkEntry); + checkEntry = checkEntry->mNext; + } + + for (int i = (int)entryList.mSize - 1; i >= 0; i--) + { + auto checkEntry = entryList[i]; + int newHashIdx = (checkEntry->mHash & 0x7FFFFFFF) % newHashSize; + checkEntry->mNext = newHashHeads[newHashIdx]; + newHashHeads[newHashIdx] = checkEntry; + } } } diff --git a/IDE/dist/lib/gen/src/Program.bf b/IDE/dist/lib/gen/src/Program.bf index f174bd0b..9e94988f 100644 --- a/IDE/dist/lib/gen/src/Program.bf +++ b/IDE/dist/lib/gen/src/Program.bf @@ -12,7 +12,8 @@ namespace gen { class Program { - static String[] sNames = new .[]("comdlg32", "gdi32", "kernel32", "ole32", "netapi32", "ntdll", "rpcrt4", "user32", "version", "winmm") ~ delete _; + static String[] sNames = new .[]("advapi32", "comdlg32", "crypt32", "d3d11", "dinput8", "gdi32", "kernel32", "ole32", "netapi32", + "ntdll", "rpcrt4", "shell32", "shlwapi", "user32", "version", "winmm", "winhttp", "wininet", "WS2_32", "wsock32") ~ delete _; public static int Main(String[] args) { diff --git a/IDE/src/BuildContext.bf b/IDE/src/BuildContext.bf index ffbbfa23..211d5f3e 100644 --- a/IDE/src/BuildContext.bf +++ b/IDE/src/BuildContext.bf @@ -29,12 +29,8 @@ namespace IDE public int32 mUpdateCnt; public Project mHotProject; public Workspace.Options mWorkspaceOptions; - public Dictionary mImpLibMap = new .() ~ - { - for (let val in _.Values) - delete val; - delete _; - }; + public Dictionary mImpLibMap = new .() ~ DeleteDictionaryAndValues!(_); + public Dictionary mTargetPathMap = new .() ~ DeleteDictionaryAndValues!(_); public ScriptManager.Context mScriptContext = new .() ~ _.ReleaseLastRef(); public ScriptManager mScriptManager ~ delete _; @@ -122,7 +118,7 @@ namespace IDE bool didCommands = false; - let targetName = scope String("Project ", project.mProjectName); + //let targetName = scope String("Project ", project.mProjectName); //Console.WriteLine("Executing custom command {0} {1} {2}", highestDateTime, targetDateTime, forceRebuild); for (let origCustomCmd in cmdList) @@ -163,19 +159,13 @@ namespace IDE didCommands = true; } - mScriptManager.QueueCommands(customCmd, scope String()..AppendF("project {}", project.mProjectName), .NoLines); + let scriptCmd = new IDEApp.ScriptCmd(); + scriptCmd.mCmd = new String(customCmd); + scriptCmd.mPath = new $"project {project.mProjectName}"; + gApp.mExecutionQueue.Add(scriptCmd); continue; } - let targetCompleteCmd = new IDEApp.TargetCompletedCmd(project); - if (didCommands) - { - mScriptManager.QueueCommands(scope String()..AppendF("%targetComplete {}", project.mProjectName), targetName, .NoLines); - targetCompleteCmd.mIsReady = false; - project.mNeedsTargetRebuild = true; - } - gApp.mExecutionQueue.Add(targetCompleteCmd); - return didCommands ? .HadCommands : .NoCommands; } @@ -874,9 +864,9 @@ namespace IDE minRTModName.Insert(0, "_"); if (!is64Bit) - linkLine.Append("-libpath:\"", gApp.mInstallDir, "lib\\x86\" ", gApp.mInstallDir, "lib\\x86\\msvcrt.lib Beef", IDEApp.sRTVersionStr,"MinRT32", minRTModName, ".lib "); + linkLine.Append("-libpath:\"", gApp.mInstallDir, "lib\\x86\" \"", gApp.mInstallDir, "lib\\x86\\msvcrt.lib\" Beef", IDEApp.sRTVersionStr,"MinRT32", minRTModName, ".lib "); else - linkLine.Append("-libpath:\"", gApp.mInstallDir, "lib\\x64\" ", gApp.mInstallDir, "lib\\x64\\msvcrt.lib Beef", IDEApp.sRTVersionStr,"MinRT64", minRTModName, ".lib "); + linkLine.Append("-libpath:\"", gApp.mInstallDir, "lib\\x64\" \"", gApp.mInstallDir, "lib\\x64\\msvcrt.lib\" Beef", IDEApp.sRTVersionStr,"MinRT64", minRTModName, ".lib "); linkLine.Append("ntdll.lib user32.lib kernel32.lib gdi32.lib winmm.lib shell32.lib ole32.lib rpcrt4.lib version.lib comdlg32.lib -ignore:4049 -ignore:4217 "); } @@ -1062,17 +1052,8 @@ namespace IDE IDEUtils.AppendWithOptionalQuotes(linkLine, resOutPath); } - - let binPath = (!is64Bit) ? gApp.mSettings.mVSSettings.mBin32Path : gApp.mSettings.mVSSettings.mBin64Path; - if (binPath.IsWhiteSpace) - { - gApp.OutputErrorLine("Visual Studio tool path not configured. Check Visual Studio configuration in File\\Preferences\\Settings."); - return false; - } String linkerPath = scope String(); - linkerPath.Append(binPath); - linkerPath.Append("/link.exe"); if (workspaceOptions.mToolsetType == .LLVM) { linkerPath.Clear(); @@ -1097,6 +1078,17 @@ namespace IDE if ((mPlatformType == .Windows) && (!is64Bit)) linkLine.Append(" /safeseh:no"); } + else + { + let binPath = (!is64Bit) ? gApp.mSettings.mVSSettings.mBin32Path : gApp.mSettings.mVSSettings.mBin64Path; + if (binPath.IsWhiteSpace) + { + gApp.OutputErrorLine("Visual Studio tool path not configured. Check Visual Studio configuration in File\\Preferences\\Settings."); + return false; + } + linkerPath.Append(binPath); + linkerPath.Append("/link.exe"); + } if (options.mBuildOptions.mBeefLibType != .DynamicDebug) { @@ -1216,6 +1208,8 @@ namespace IDE } } + mTargetPathMap[project] = new String(targetPath); + if (hotProject == null) { switch (QueueProjectCustomBuildCommands(project, targetPath, compileKind.WantsRunAfter ? options.mBuildOptions.mBuildCommandsOnRun : options.mBuildOptions.mBuildCommandsOnCompile, options.mBuildOptions.mPreBuildCmds)) @@ -1226,22 +1220,9 @@ namespace IDE completedCompileCmd.mFailed = true; } } - - void DoPostBuild() - { - switch (QueueProjectCustomBuildCommands(project, targetPath, compileKind.WantsRunAfter ? options.mBuildOptions.mBuildCommandsOnRun : options.mBuildOptions.mBuildCommandsOnCompile, options.mBuildOptions.mPostBuildCmds)) - { - case .NoCommands: - case .HadCommands: - case .Failed: - completedCompileCmd.mFailed = true; - } - } if (project.mGeneralOptions.mTargetType == .CustomBuild) { - if (hotProject == null) - DoPostBuild(); return true; } @@ -1402,8 +1383,32 @@ namespace IDE return false; } - DoPostBuild(); return true; } + + public bool QueueProjectPostBuild(Project project, Project hotProject, IDEApp.BuildCompletedCmd completedCompileCmd, List hotFileNames, CompileKind compileKind) + { + if (hotProject != null) + return true; + + Project.Options options = gApp.GetCurProjectOptions(project); + if (options == null) + return true; + + String targetPath = null; + mTargetPathMap.TryGetValue(project, out targetPath); + if (targetPath == null) + return false; + + switch (QueueProjectCustomBuildCommands(project, targetPath, compileKind.WantsRunAfter ? options.mBuildOptions.mBuildCommandsOnRun : options.mBuildOptions.mBuildCommandsOnCompile, options.mBuildOptions.mPostBuildCmds)) + { + case .NoCommands: + case .HadCommands: + case .Failed: + completedCompileCmd.mFailed = true; + } + + return true; + } } } diff --git a/IDE/src/Debugger/DebugManager.bf b/IDE/src/Debugger/DebugManager.bf index a3b8a63e..046b01c8 100644 --- a/IDE/src/Debugger/DebugManager.bf +++ b/IDE/src/Debugger/DebugManager.bf @@ -96,7 +96,8 @@ namespace IDE.Debugger MemoryAddress = 0x40, MemoryWatch = 0x80, Symbol = 0x100, - StepIntoCall = 0x200 + StepIntoCall = 0x200, + RawStr = 0x400, } [Reflect] diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 6a2ec0cc..7198f23b 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -436,6 +436,12 @@ namespace IDE } } + public class ScriptCmd : ExecutionCmd + { + public String mCmd ~ delete _; + public String mPath ~ delete _; + } + public enum ArgsFileKind { None, @@ -7447,83 +7453,103 @@ namespace IDE return; } } - - var keyState = scope KeyState(); - keyState.mKeyCode = evt.mKeyCode; - keyState.mKeyFlags = evt.mKeyFlags; - - var curKeyMap = mCommands.mKeyMap; - bool hadChordState = mKeyChordState != null; - if (mKeyChordState != null) - curKeyMap = mKeyChordState.mCommandMap; - DeleteAndNullify!(mKeyChordState); - - KeyState matchedKey; - IDECommandBase commandBase; - if (curKeyMap.mMap.TryGet(keyState, out matchedKey, out commandBase)) + + if ((mKeyChordState != null) && (evt.mKeyCode.IsModifier)) { - if (var commandMap = commandBase as CommandMap) - { - mKeyChordState = new .(); - mKeyChordState.mCommandMap = commandMap; - mKeyChordState.mKeyState = matchedKey; - evt.mHandled = true; - return; - } - else if (var command = commandBase as IDECommand) - { - bool foundMatch = false; - if (useFlags != .None) - { - var checkCommand = command; - while (checkCommand != null) - { - bool matches = checkCommand.mContextFlags == .None; - if (checkCommand.mContextFlags.HasFlag(.Editor)) - matches |= useFlags.HasFlag(.Editor); - if (checkCommand.mContextFlags.HasFlag(.MainWindow)) - matches |= useFlags.HasFlag(.MainWindow); - if (checkCommand.mContextFlags.HasFlag(.WorkWindow)) - matches |= useFlags.HasFlag(.WorkWindow); - - if (matches) - { - checkCommand.mAction(); - foundMatch = true; - } - checkCommand = checkCommand.mNext; - } - } - - if (!foundMatch) - { - var checkCommand = command; - while (checkCommand != null) - { - if (checkCommand.mContextFlags == .None) - { - checkCommand.mAction(); - foundMatch = true; - } - checkCommand = checkCommand.mNext; - } - } - - if (foundMatch) - { - evt.mHandled = true; - return; - } - } + // Ignore } else { - // Not found - if (hadChordState) + var keyState = scope KeyState(); + keyState.mKeyCode = evt.mKeyCode; + keyState.mKeyFlags = evt.mKeyFlags; + + var curKeyMap = mCommands.mKeyMap; + + bool hadChordState = mKeyChordState != null; + if (mKeyChordState != null) + curKeyMap = mKeyChordState.mCommandMap; + var prevKeyChordState = mKeyChordState; + defer delete prevKeyChordState; + mKeyChordState = null; + + KeyState matchedKey; + IDECommandBase commandBase; + + bool hadMatch = curKeyMap.mMap.TryGet(keyState, out matchedKey, out commandBase); + if ((!hadMatch) && (prevKeyChordState != null)) { - Beep(.Error); - evt.mHandled = true; - return; + // If we have a "Ctrl+A, Ctrl+B" style sequence then also try to match that against "Ctrl+A, B" + KeyState rawKeyState = keyState; + rawKeyState.mKeyFlags &= ~prevKeyChordState.mKeyState.mKeyFlags; + hadMatch = curKeyMap.mMap.TryGet(rawKeyState, out matchedKey, out commandBase); + } + + if (hadMatch) + { + if (var commandMap = commandBase as CommandMap) + { + mKeyChordState = new .(); + mKeyChordState.mCommandMap = commandMap; + mKeyChordState.mKeyState = matchedKey; + evt.mHandled = true; + return; + } + else if (var command = commandBase as IDECommand) + { + bool foundMatch = false; + if (useFlags != .None) + { + var checkCommand = command; + while (checkCommand != null) + { + bool matches = checkCommand.mContextFlags == .None; + if (checkCommand.mContextFlags.HasFlag(.Editor)) + matches |= useFlags.HasFlag(.Editor); + if (checkCommand.mContextFlags.HasFlag(.MainWindow)) + matches |= useFlags.HasFlag(.MainWindow); + if (checkCommand.mContextFlags.HasFlag(.WorkWindow)) + matches |= useFlags.HasFlag(.WorkWindow); + + if (matches) + { + checkCommand.mAction(); + foundMatch = true; + } + checkCommand = checkCommand.mNext; + } + } + + if (!foundMatch) + { + var checkCommand = command; + while (checkCommand != null) + { + if (checkCommand.mContextFlags == .None) + { + checkCommand.mAction(); + foundMatch = true; + } + checkCommand = checkCommand.mNext; + } + } + + if (foundMatch) + { + evt.mHandled = true; + return; + } + } + } + else + { + // Not found + if (hadChordState) + { + Beep(.Error); + evt.mHandled = true; + return; + } } } @@ -8256,6 +8282,21 @@ namespace IDE } } + if (let scriptCmd = next as ScriptCmd) + { + if (mBuildContext?.mScriptManager != null) + { + if (scriptCmd.mCmd != null) + { + mBuildContext.mScriptManager.QueueCommands(scriptCmd.mCmd, scriptCmd.mPath, .NoLines); + DeleteAndNullify!(scriptCmd.mCmd); + } + + if (mBuildContext.mScriptManager.HasQueuedCommands) + return; + } + } + defer delete next; mExecutionQueue.RemoveAt(0); @@ -8411,6 +8452,11 @@ namespace IDE if (gApp.mDebugger.mIsRunning) mProfilePanel.StartProfiling(profileCmd.mThreadId, profileCmd.mDesc, profileCmd.mSampleRate); } + else if (var scriptCmd = next as ScriptCmd) + { + // Already handled + (void)scriptCmd; + } else { Runtime.FatalError("Unknown command"); @@ -9163,7 +9209,8 @@ namespace IDE public bool DoResolveConfigString(String platformName, Workspace.Options workspaceOptions, Project project, Project.Options options, StringView configString, String error, String result) { - int i = result.Length; + int startIdx = result.Length; + int i = startIdx; result.Append(configString); bool hadError = false; @@ -9258,6 +9305,28 @@ namespace IDE cmdErr = "Invalid number of arguments"; case "Var": break ReplaceBlock; + case "Arguments", + "BuildDir", + "LinkFlags", + "ProjectDir", + "ProjectName", + "TargetDir", + "TargetPath", + "WorkingDir": + var selProject = mWorkspace.FindProject(args[0]); + if (selProject != null) + { + Workspace.Options selWorkspaceOptions = gApp.GetCurWorkspaceOptions(); + Project.Options selOptions = gApp.GetCurProjectOptions(selProject); + String selConfigString = scope $"$({cmd})"; + replaceStr.Clear(); + newString = scope:ReplaceBlock .(); + DoResolveConfigString(platformName, selWorkspaceOptions, selProject, selOptions, selConfigString, error, newString); + } + else + cmdErr = "Unable to find project"; + default: + cmdErr = "Invalid command"; } if (newString == null) @@ -10251,6 +10320,12 @@ namespace IDE success = false; } + for (var project in orderedProjectList) + { + if (!mBuildContext.QueueProjectPostBuild(project, hotProject, completedCompileCmd, hotFileNames, compileKind)) + success = false; + } + if (hotFileNames.Count > 0) { // Why were we rehupping BEFORE hotLoad? @@ -10430,6 +10505,36 @@ namespace IDE #endif } + public bool IsVisualStudioRequired + { + get + { + if (Workspace.PlatformType.GetFromName(mPlatformName) != .Windows) + return false; + var workspaceOptions = GetCurWorkspaceOptions(); + if (workspaceOptions.mToolsetType != .LLVM) + return true; + + for (var project in mWorkspace.mProjects) + { + if ((project.mGeneralOptions.mTargetType != .BeefConsoleApplication) && + (project.mGeneralOptions.mTargetType != .BeefGUIApplication) && + (project.mGeneralOptions.mTargetType != .BeefApplication_DynamicLib) && + (project.mGeneralOptions.mTargetType != .BeefApplication_StaticLib)) + { + continue; + } + + var options = GetCurProjectOptions(project); + if (options == null) + continue; + if (options.mBuildOptions.mCLibType != .SystemMSVCRT) + return true; + } + return false; + } + } + protected bool Compile(CompileKind compileKind = .Normal, Project hotProject = null) { Debug.Assert(mBuildContext == null); @@ -10604,7 +10709,7 @@ namespace IDE } } - if (Workspace.PlatformType.GetFromName(mPlatformName) == .Windows) + if ((Workspace.PlatformType.GetFromName(mPlatformName) == .Windows) && (IsVisualStudioRequired)) { if (!mSettings.mVSSettings.IsConfigured()) mSettings.mVSSettings.SetDefaults(); @@ -10788,8 +10893,8 @@ namespace IDE //options.mDebugOptions.mCommand - String launchPath = scope String(); - ResolveConfigString(mPlatformName, workspaceOptions, project, options, options.mDebugOptions.mCommand, "debug command", launchPath); + String launchPathRel = scope String(); + ResolveConfigString(mPlatformName, workspaceOptions, project, options, options.mDebugOptions.mCommand, "debug command", launchPathRel); String arguments = scope String(); ResolveConfigString(mPlatformName, workspaceOptions, project, options, "$(Arguments)", "debug command arguments", arguments); String workingDirRel = scope String(); @@ -10797,6 +10902,9 @@ namespace IDE var workingDir = scope String(); Path.GetAbsolutePath(workingDirRel, project.mProjectDir, workingDir); + String launchPath = scope String(); + Path.GetAbsolutePath(launchPathRel, workingDir, launchPath); + String targetPath = scope .(); ResolveConfigString(mPlatformName, workspaceOptions, project, options, "$(TargetPath)", "Target path", targetPath); diff --git a/IDE/src/ScriptManager.bf b/IDE/src/ScriptManager.bf index 0e1973f8..4c0bafe9 100644 --- a/IDE/src/ScriptManager.bf +++ b/IDE/src/ScriptManager.bf @@ -1007,7 +1007,7 @@ namespace IDE if (!gApp.[Friend]mExecutionQueue.IsEmpty) { var nextCmd = gApp.mExecutionQueue[0]; - if (!(nextCmd is IDEApp.TargetCompletedCmd)) + if (!(nextCmd is IDEApp.ScriptCmd)) return false; } diff --git a/IDE/src/ui/ClassViewPanel.bf b/IDE/src/ui/ClassViewPanel.bf index 39e7a378..8211dfe6 100644 --- a/IDE/src/ui/ClassViewPanel.bf +++ b/IDE/src/ui/ClassViewPanel.bf @@ -876,16 +876,22 @@ namespace IDE.ui { base.Update(); + if (gApp.mBfResolveCompiler == null) + return; + var focusedItem = (ClassViewListViewItem)mTypeLV.GetRoot().FindFocusedItem(); var focusedStr = scope String(); if (focusedItem != null) GetName(focusedItem, focusedStr); - int32 compileRevision = gApp.mBfResolveCompiler.GetCompileRevision(); - if (mLastCompileRevision != compileRevision) + if (gApp.mBfResolveCompiler != null) { - mCompileRevisionDirtyDelay = 30; - mLastCompileRevision = compileRevision; + int32 compileRevision = gApp.mBfResolveCompiler.GetCompileRevision(); + if (mLastCompileRevision != compileRevision) + { + mCompileRevisionDirtyDelay = 30; + mLastCompileRevision = compileRevision; + } } if ((mCompileRevisionDirtyDelay > 0) && (--mCompileRevisionDirtyDelay == 0)) diff --git a/IDE/src/ui/DisassemblyPanel.bf b/IDE/src/ui/DisassemblyPanel.bf index cd9c039c..0273b030 100644 --- a/IDE/src/ui/DisassemblyPanel.bf +++ b/IDE/src/ui/DisassemblyPanel.bf @@ -266,7 +266,7 @@ namespace IDE.ui IdSpan liveCharIdData; String liveText = scope:: String(); app.FindProjectSourceContent(projectSource, out liveCharIdData, true, liveText, null); - defer(stack) liveCharIdData.Dispose(); + defer:: liveCharIdData.Dispose(); var compileInstance = IDEApp.sApp.mWorkspace.GetProjectSourceCompileInstance(projectSource, mHotIdx); if (compileInstance == null) diff --git a/IDE/src/ui/ErrorsPanel.bf b/IDE/src/ui/ErrorsPanel.bf index 0d13162c..f64e2724 100644 --- a/IDE/src/ui/ErrorsPanel.bf +++ b/IDE/src/ui/ErrorsPanel.bf @@ -276,7 +276,15 @@ namespace IDE.ui SetLabel(item, codeStr); let descItem = item.GetSubItem(1); - String errStr = scope String(32)..Append(error.mError); + String errStr = scope String(32); + int maxLen = 4*1024; + if (error.mError.Length > maxLen) + { + errStr.Append(error.mError.Substring(0, maxLen)); + errStr.Append("..."); + } + else + errStr.Append(error.mError); errStr.Replace('\n', ' '); SetLabel(descItem, errStr); diff --git a/IDE/src/ui/HoverWatch.bf b/IDE/src/ui/HoverWatch.bf index dae9c039..77468a09 100644 --- a/IDE/src/ui/HoverWatch.bf +++ b/IDE/src/ui/HoverWatch.bf @@ -718,6 +718,14 @@ namespace IDE.ui var watch = useListViewItem.mWatchEntry; String.NewOrSet!(watch.mName, displayString); String.NewOrSet!(watch.mEvalStr, evalString); + + if (watch.mEvalStr.StartsWith("!raw")) + { + for (int i < 4) + watch.mEvalStr[i] = ' '; + watch.mResultType = .RawText; + } + useListViewItem.mWatchEntry = watch; if (!isLiteral) useListViewItem.Label = displayString; @@ -730,7 +738,7 @@ namespace IDE.ui String val = scope String(); if (evalString.StartsWith(":", StringComparison.Ordinal)) { - var showString = scope String(evalString, 1); + var showString = scope String(4096)..Append(evalString, 1); bool isShowingDoc = showString.Contains('\x01'); if (!isShowingDoc) { @@ -759,11 +767,13 @@ namespace IDE.ui flags |= .AllowSideEffects | .AllowCalls; if (gApp.mSettings.mDebuggerSettings.mAutoEvaluateProperties) flags |= .AllowProperties; + if (watch.mResultType == .RawText) + flags |= .RawStr; DebugManager.Language language = mLanguage; if (parentWatchEntry != null) language = parentWatchEntry.mLanguage; - gApp.DebugEvaluate(null, evalString, val, -1, language, flags); + gApp.DebugEvaluate(null, watch.mEvalStr, val, -1, language, flags); } if (val == "!pending") { @@ -773,6 +783,13 @@ namespace IDE.ui } watch.mIsPending = false; } + + if (watch.mResultType == .RawText) + { + String.NewOrSet!(valueSubItem.mLabel, val); + return useListViewItem; + } + var vals = scope List(val.Split('\n')); //if (!vals[0].IsEmpty) diff --git a/IDE/src/ui/ImmediateWidget.bf b/IDE/src/ui/ImmediateWidget.bf index 1151fe1f..0c31f89b 100644 --- a/IDE/src/ui/ImmediateWidget.bf +++ b/IDE/src/ui/ImmediateWidget.bf @@ -7,6 +7,7 @@ using Beefy.theme.dark; using Beefy.gfx; using System.Diagnostics; using System.IO; +using IDE.Debugger; namespace IDE.ui { @@ -379,7 +380,11 @@ namespace IDE.ui var subItemLabel = result.GetSubItem(1).mLabel; if (subItemLabel == null) subItemLabel = ""; - mEditWidgetContent.AppendText(scope String(" ", subItemLabel, "\n")); + + if (result.mWatchEntry.mResultType == .RawText) + mEditWidgetContent.AppendText(scope String(subItemLabel, "\n")); + else + mEditWidgetContent.AppendText(scope String(" ", subItemLabel, "\n")); if (result.mWatchEntry.mWarnings != null) { @@ -415,7 +420,11 @@ namespace IDE.ui for (int32 i = startPos; i < mEditWidgetContent.mData.mTextLength; i++) mEditWidgetContent.mData.mText[i].mDisplayTypeId = (uint8)SourceElementType.Error; } - else + else if (result.mWatchEntry.mResultType == .RawText) + { + // No info button + } + else { mInfoButton.Resize(resultX - GS!(3), resultY - GS!(2), GS!(20), GS!(20)); mEditWidgetContent.AddWidget(mInfoButton); @@ -547,7 +556,16 @@ namespace IDE.ui } else { - gApp.DebugEvaluate(null, cmdText, val, mEditWidgetContent.CursorTextPos - mEntryStartPos.mIndex - 2); + DebugManager.EvalExpressionFlags flags = .None; + + if (cmdText.StartsWith("!raw")) + { + for (int i < 4) + cmdText[i] = ' '; + flags |= .RawStr; + } + + gApp.DebugEvaluate(null, cmdText, val, mEditWidgetContent.CursorTextPos - mEntryStartPos.mIndex - 2, .NotSet, flags); gApp.mIsImmediateDebugExprEval = true; } } @@ -570,7 +588,19 @@ namespace IDE.ui } var info = scope String()..Append(val, idx + ":autocomplete\n".Length); if (!editWidgetContent.mAutoComplete.mIsDocumentationPass) + { + if ((cmdText.StartsWith("!")) && (!cmdText.Contains(' '))) + { + if ("!raw".Contains(cmdText)) + info.Append("cmd\traw\n"); + if ("!info".Contains(cmdText)) + info.Append("cmd\tinfo\n"); + if ("!step".Contains(cmdText)) + info.Append("cmd\tstep\n"); + } + editWidgetContent.mAutoComplete.SetInfo(info, true, mEntryStartPos.mIndex + 1); + } } else if (editWidgetContent.mAutoComplete != null) editWidgetContent.mAutoComplete.Close(); diff --git a/IDE/src/ui/MemoryPanel.bf b/IDE/src/ui/MemoryPanel.bf index 853152cb..a8d36ee7 100644 --- a/IDE/src/ui/MemoryPanel.bf +++ b/IDE/src/ui/MemoryPanel.bf @@ -284,26 +284,20 @@ namespace IDE.ui s.AppendF("0x{:A}", (uint64)lockRange.mBaseOffset); case RepType.Int8: hasAltS = true; - (*(int8*)lockRange.mData.CArray()).ToString(s, (altIntBase == 10) ? "" : "X2", null); - if (altIntBase == 10) - ((UInt64)*(uint8*)lockRange.mData.CArray()).ToString(altS, "", null); + (*(int8*)lockRange.mData.CArray()).ToString(s, (intBase == 10) ? "" : "X2", null); + ((UInt64)*(uint8*)lockRange.mData.CArray()).ToString(altS, (altIntBase == 10) ? "" : "X2", null); case RepType.Int16: hasAltS = true; - (*(int16*)lockRange.mData.CArray()).ToString(s, (altIntBase == 10) ? "" : "X4", null); - if (altIntBase == 10) - ((UInt64)*(uint16*)lockRange.mData.CArray()).ToString(altS, "", null); + (*(int16*)lockRange.mData.CArray()).ToString(s, (intBase == 10) ? "" : "X4", null); + ((UInt64)*(uint16*)lockRange.mData.CArray()).ToString(altS, (altIntBase == 10) ? "" : "X4", null); case RepType.Int32: hasAltS = true; - (*(int32*)lockRange.mData.CArray()).ToString(s, (altIntBase == 10) ? "" : "X8", null); - if (altIntBase == 10) - ((UInt64)*(uint32*)lockRange.mData.CArray()).ToString(altS, "", null); + (*(int32*)lockRange.mData.CArray()).ToString(s, (intBase == 10) ? "" : "X8", null); + ((UInt64)*(uint32*)lockRange.mData.CArray()).ToString(altS, (altIntBase == 10) ? "" : "X8", null); case RepType.Int64: hasAltS = true; - (*(int64*)lockRange.mData.CArray()).ToString(s, (altIntBase == 10) ? "" : "X16", null); - if (altIntBase == 0x10) - s.Insert(8, '\''); - if (altIntBase == 10) - ((UInt64)*(uint64*)lockRange.mData.CArray()).ToString(altS, "", null); + (*(int64*)lockRange.mData.CArray()).ToString(s, (intBase == 10) ? "" : "X16", null); + ((UInt64)*(uint64*)lockRange.mData.CArray()).ToString(altS, (altIntBase == 10) ? "" : "X16", null); case RepType.Float: (*(float*)lockRange.mData.CArray()).ToString(s); case RepType.Double: diff --git a/IDE/src/ui/ProjectPanel.bf b/IDE/src/ui/ProjectPanel.bf index a47efbca..b70a966f 100644 --- a/IDE/src/ui/ProjectPanel.bf +++ b/IDE/src/ui/ProjectPanel.bf @@ -187,9 +187,10 @@ namespace IDE.ui { base.FocusForKeyboard(); SetFocus(); - if (mListView.GetRoot().FindFocusedItem() == null) + let root = mListView.GetRoot(); + if (root.IsOpen && root.FindFocusedItem() == null) { - mListView.GetRoot().GetChildAtIndex(0).Focused = true; + root.GetChildAtIndex(0).Focused = true; } } diff --git a/IDE/src/ui/SourceEditWidgetContent.bf b/IDE/src/ui/SourceEditWidgetContent.bf index 540c766f..af07c861 100644 --- a/IDE/src/ui/SourceEditWidgetContent.bf +++ b/IDE/src/ui/SourceEditWidgetContent.bf @@ -1244,7 +1244,7 @@ namespace IDE.ui { var undoBatchStart = new UndoBatchStart("pasteText"); mData.mUndoManager.Add(undoBatchStart); - defer(stack) mData.mUndoManager.Add(undoBatchStart.mBatchEnd); + defer:: mData.mUndoManager.Add(undoBatchStart.mBatchEnd); } if (HasSelection()) @@ -3644,7 +3644,7 @@ namespace IDE.ui bool hadSuggestion = false; List suggestions = scope List(); - defer (scope) ClearAndDeleteItems(suggestions); + defer ClearAndDeleteItems(suggestions); spellChecker.GetSuggestions(word, suggestions); for (var suggestion in suggestions) { @@ -3789,7 +3789,7 @@ namespace IDE.ui else if (bfSystem != null) { parser = bfSystem.CreateEmptyParser(null); - defer(stack) delete parser; + defer:: delete parser; var text = scope String(); mEditWidget.GetText(text); parser.SetSource(text, mSourceViewPanel.mFilePath); diff --git a/IDE/src/ui/SourceViewPanel.bf b/IDE/src/ui/SourceViewPanel.bf index d25fed70..98a4cf3c 100644 --- a/IDE/src/ui/SourceViewPanel.bf +++ b/IDE/src/ui/SourceViewPanel.bf @@ -5073,7 +5073,11 @@ namespace IDE.ui String showMouseoverString = null; if (bestError.mError != null) { - showMouseoverString = scope:: String(":", bestError.mError); + int maxLen = 16*1024; + if (bestError.mError.Length > maxLen) + showMouseoverString = scope:: String()..Concat(":", StringView(bestError.mError, 0, maxLen), "..."); + else + showMouseoverString = scope:: String()..Concat(":", bestError.mError); if (bestError.mMoreInfo != null) { @@ -5676,7 +5680,8 @@ namespace IDE.ui } } - UpdateMouseover(); + if (gApp.mIsUpdateBatchStart) + UpdateMouseover(); var compiler = ResolveCompiler; var bfSystem = BfResolveSystem; diff --git a/IDE/src/ui/WatchPanel.bf b/IDE/src/ui/WatchPanel.bf index 60cc666a..497beab4 100644 --- a/IDE/src/ui/WatchPanel.bf +++ b/IDE/src/ui/WatchPanel.bf @@ -27,7 +27,8 @@ namespace IDE.ui TypeClass = 0x80, TypeValueType = 0x100, Namespace = 0x200, - Text = 0x400 + Text = 0x400, + RawText = 0x800 } public class WatchEntry @@ -1740,6 +1741,7 @@ namespace IDE.ui evt.mDragKind = .After; dragTarget = (WatchListViewItem)dragTarget.mParentItem; evt.mDragTarget = dragTarget; + return; } if ((dragTarget.mLabel == "") && (dragKind == .After)) dragKind = .Before; diff --git a/IDEHelper/Backend/BeIRCodeGen.cpp b/IDEHelper/Backend/BeIRCodeGen.cpp index 403dcc50..766f2f9b 100644 --- a/IDEHelper/Backend/BeIRCodeGen.cpp +++ b/IDEHelper/Backend/BeIRCodeGen.cpp @@ -690,6 +690,8 @@ void BeIRCodeGen::Read(BeValue*& beValue) CMD_PARAM(BeConstant*, initializer); CMD_PARAM(String, name); CMD_PARAM(bool, isTLS); + + BF_ASSERT(varType != NULL); auto globalVariable = mBeModule->mGlobalVariables.Alloc(); globalVariable->mModule = mBeModule; @@ -1906,7 +1908,9 @@ void BeIRCodeGen::HandleNextCmd() CMD_PARAM(StringT<256>, name); CMD_PARAM(bool, isTLS); CMD_PARAM(BeConstant*, initializer); - + + BF_ASSERT(varType != NULL); + auto globalVariable = mBeModule->mGlobalVariables.Alloc(); globalVariable->mModule = mBeModule; globalVariable->mType = varType; diff --git a/IDEHelper/Backend/BeMCContext.cpp b/IDEHelper/Backend/BeMCContext.cpp index d23f7295..2f79f075 100644 --- a/IDEHelper/Backend/BeMCContext.cpp +++ b/IDEHelper/Backend/BeMCContext.cpp @@ -3787,7 +3787,7 @@ BeMCOperand BeMCContext::AllocVirtualReg(BeType* type, int refCount, bool mustBe if (mDebugging) { - if (mcOperand.mVRegIdx == 6) + if (mcOperand.mVRegIdx == 227) { NOP; } @@ -10364,7 +10364,7 @@ bool BeMCContext::DoLegalization() inst->mArg0.mKind = BeMCOperandKind_SymbolAddr; } - ReplaceWithNewVReg(inst->mArg0, movInstIdx, true, false); + ReplaceWithNewVReg(inst->mArg0, movInstIdx, true, false, true); auto vregInfo = GetVRegInfo(inst->mArg0); vregInfo->mDisableR11 = true; instIdx += 2; @@ -15842,7 +15842,7 @@ void BeMCContext::Generate(BeFunction* function) mDbgPreferredRegs[32] = X64Reg_R8;*/ //mDbgPreferredRegs[8] = X64Reg_RAX; - //mDebugging = (function->mName == "?ParseRegex@Program@Regex@bf@@CAPEAV?$List@?AUStringView@System@bf@@@Collections@System@3@UStringView@63@0@Z"); + //mDebugging = (function->mName == "?Zoips@TestProgram@BeefTest@bf@@SAXXZ"); // || (function->mName == "?MethodA@TestProgram@BeefTest@bf@@CAXXZ"); // || (function->mName == "?Hey@Blurg@bf@@SAXXZ") // ; diff --git a/IDEHelper/Compiler/BfCodeGen.cpp b/IDEHelper/Compiler/BfCodeGen.cpp index 9b374f23..cd767442 100644 --- a/IDEHelper/Compiler/BfCodeGen.cpp +++ b/IDEHelper/Compiler/BfCodeGen.cpp @@ -439,7 +439,8 @@ void BfCodeGenThread::RunLoop() errorMsg += "\n"; errorMsg += "Failed writing IR '" + fileName + "': " + ec.message(); } - fs.WriteSNZ(str); + else + fs.WriteSNZ(str); } if (!hasCacheMatch) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 6c25707a..1bd87e39 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -341,11 +341,10 @@ BfCompiler::HotResolveData::~HotResolveData() BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) { - //llvm::DebugFlag = true; - memset(&mStats, 0, sizeof(mStats)); mCompletionPct = 0; mCanceling = false; + mHasRequiredTypes = false; mNeedsFullRefresh = false; mFastFinish = false; mHasQueuedTypeRebuilds = false; @@ -399,6 +398,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mDbgRawAllocDataTypeDef = NULL; mDeferredCallTypeDef = NULL; mDelegateTypeDef = NULL; + mFunctionTypeDef = NULL; mActionTypeDef = NULL; mEnumTypeDef = NULL; mFriendAttributeTypeDef = NULL; @@ -406,8 +406,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mConstEvalAttributeTypeDef = NULL; mNoExtensionAttributeTypeDef = NULL; mCheckedAttributeTypeDef = NULL; - mUncheckedAttributeTypeDef = NULL; - mFunctionTypeDef = NULL; + mUncheckedAttributeTypeDef = NULL; mGCTypeDef = NULL; mGenericIEnumerableTypeDef = NULL; mGenericIEnumeratorTypeDef = NULL; @@ -2146,7 +2145,7 @@ void BfCompiler::UpdateDependencyMap(bool deleteUnusued, bool& didWork) madeFullPass = false; if ((mResolvePassData != NULL) && (mResolvePassData->mParser != NULL)) madeFullPass = false; - + SetAndRestoreValue prevAssertOnPopulateType(mContext->mAssertOnPopulateType, deleteUnusued && madeFullPass); if ((deleteUnusued) && (madeFullPass)) @@ -5107,6 +5106,18 @@ void BfCompiler::MarkStringPool(BfModule* module) stringPoolEntry.mLastUsedRevision = mRevision; } + for (int stringId : module->mUnreifiedStringPoolRefs) + { + BfStringPoolEntry& stringPoolEntry = module->mContext->mStringObjectIdMap[stringId]; + stringPoolEntry.mLastUsedRevision = mRevision; + } + + for (int stringId : module->mImportFileNames) + { + BfStringPoolEntry& stringPoolEntry = module->mContext->mStringObjectIdMap[stringId]; + stringPoolEntry.mLastUsedRevision = mRevision; + } + /*if (module->mOptModule != NULL) MarkStringPool(module->mOptModule);*/ auto altModule = module->mNextAltModule; @@ -5220,7 +5231,7 @@ int BfCompiler::GetVTableMethodOffset() bool BfCompiler::DoWorkLoop(bool onlyReifiedTypes, bool onlyReifiedMethods) { bool hadAnyWork = false; - + while (true) { bool didWork = false; @@ -6596,7 +6607,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) BpEnter("Compile_Start"); - bool hasRequiredTypes = true; + mHasRequiredTypes = true; //HashSet internalTypeDefs; @@ -6606,7 +6617,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) if (typeDef == NULL) { mPassInstance->Fail(StrFormat("Unable to find system type: %s", typeName.c_str())); - hasRequiredTypes = false; + mHasRequiredTypes = false; } return typeDef; }; @@ -6654,6 +6665,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mDbgRawAllocDataTypeDef = _GetRequiredType("System.DbgRawAllocData"); mDeferredCallTypeDef = _GetRequiredType("System.DeferredCall"); mDelegateTypeDef = _GetRequiredType("System.Delegate"); + mFunctionTypeDef = _GetRequiredType("System.Function"); mActionTypeDef = _GetRequiredType("System.Action"); mEnumTypeDef = _GetRequiredType("System.Enum"); mFriendAttributeTypeDef = _GetRequiredType("System.FriendAttribute"); @@ -6662,8 +6674,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mNoExtensionAttributeTypeDef = _GetRequiredType("System.NoExtensionAttribute"); mCheckedAttributeTypeDef = _GetRequiredType("System.CheckedAttribute"); mUncheckedAttributeTypeDef = _GetRequiredType("System.UncheckedAttribute"); - mResultTypeDef = _GetRequiredType("System.Result", 1); - mFunctionTypeDef = _GetRequiredType("System.Function"); + mResultTypeDef = _GetRequiredType("System.Result", 1); mGCTypeDef = _GetRequiredType("System.GC"); mGenericIEnumerableTypeDef = _GetRequiredType("System.Collections.IEnumerable", 1); mGenericIEnumeratorTypeDef = _GetRequiredType("System.Collections.IEnumerator", 1); @@ -6722,21 +6733,17 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mContext->mBfTypeType = NULL; mContext->mBfClassVDataPtrType = NULL; - if (!hasRequiredTypes) - { - // Force rebuilding - BfLogSysM("Compile missing required types\n"); - mInInvalidState = true; - mOptions.mForceRebuildIdx++; - return true; - } + if (!mHasRequiredTypes) + { + // Force rebuilding + BfLogSysM("Compile missing required types\n"); + mOptions.mForceRebuildIdx++; + } mSystem->CheckLockYield(); mContext->mScratchModule->ResolveTypeDef(mBfObjectTypeDef); - VisitSourceExteriorNodes(); - - //BF_ASSERT(hasRequiredTypes); + VisitSourceExteriorNodes(); if (!mIsResolveOnly) { @@ -6811,19 +6818,14 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) if (mIsResolveOnly) VisitAutocompleteExteriorIdentifiers(); - - if (!hasRequiredTypes) - { - BfLogSysM("Missing required types\n"); - } - + mStats.mTypesQueued = 0; mStats.mMethodsQueued = 0; mStats.mTypesQueued += (int)mContext->mPopulateTypeWorkList.size(); mStats.mMethodsQueued += (int)mContext->mMethodWorkList.size(); - if (hasRequiredTypes) + // { mContext->mScratchModule->ResolveTypeDef(mBfObjectTypeDef, BfPopulateType_Full); @@ -6864,9 +6866,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) } } } - - if (hasRequiredTypes) - ProcessPurgatory(true); + + ProcessPurgatory(true); // Mark used modules if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!mCanceling)) @@ -6967,7 +6968,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) } // Generate slot nums - if ((!mIsResolveOnly) && (hasRequiredTypes) && (!mCanceling)) + if ((!mIsResolveOnly) && (!mCanceling)) { if ((!IsHotCompile()) || (mHotState->mHasNewInterfaceTypes)) { @@ -6996,7 +6997,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) } } } - + DoWorkLoop(); BfLogSysM("Compile QueueUnused\n"); @@ -7098,13 +7099,12 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) { DoWorkLoop(); } - - if (hasRequiredTypes) - ProcessPurgatory(false); + + ProcessPurgatory(false); // Old Mark used modules - if ((!mIsResolveOnly) && (hasRequiredTypes)) + if (!mIsResolveOnly) { // if ((!mPassInstance->HasFailed()) && (!mCanceling)) // { @@ -7161,7 +7161,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) String moduleListStr; int numModulesWritten = 0; - if ((hasRequiredTypes) && (!mCanceling)) + if (!mCanceling) { if (!mIsResolveOnly) { @@ -7250,9 +7250,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) //printf("Compile done, waiting for finish\n"); while (true) - { - if (!hasRequiredTypes) - break; + { if (mCanceling) mCodeGen.Cancel(); bool isDone = mCodeGen.Finish(); @@ -7391,8 +7389,8 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) // gBEMemReporter.Report(); // int memReporterSize = gBEMemReporterSize; - mLastRevisionAborted = mCanceling || !hasRequiredTypes; - bool didCancel = mCanceling && hasRequiredTypes; + mLastRevisionAborted = mCanceling; + bool didCancel = mCanceling; mCanceling = false; mContext->ValidateDependencies(); @@ -8961,9 +8959,10 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeInfo(BfCompiler* bfCompiler, SetAndRestoreValue prevIgnoreWarnings(bfCompiler->mContext->mScratchModule->mIgnoreWarnings, true); SetAndRestoreValue prevResolvePass(bfCompiler->mResolvePassData, &resolvePass); - auto type = bfCompiler->mContext->mScratchModule->ResolveTypeRef(typeRef, BfPopulateType_Data, BfResolveTypeRefFlag_NoCreate); + auto type = bfCompiler->mContext->mScratchModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_NoCreate); if (type != NULL) { + bfCompiler->mContext->mScratchModule->PopulateType(type); outString += "Found"; if (auto typeInst = type->ToTypeInstance()) { diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 24aba505..03bcaec0 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -323,6 +323,7 @@ public: BfCodeGen mCodeGen; String mOutputDirectory; bool mCanceling; + bool mHasRequiredTypes; bool mNeedsFullRefresh; bool mFastFinish; bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild @@ -352,14 +353,14 @@ public: BfTypeDef* mDbgRawAllocDataTypeDef; BfTypeDef* mDeferredCallTypeDef; BfTypeDef* mDelegateTypeDef; + BfTypeDef* mFunctionTypeDef; BfTypeDef* mActionTypeDef; BfTypeDef* mEnumTypeDef; BfTypeDef* mStringTypeDef; BfTypeDef* mStringViewTypeDef; BfTypeDef* mTypeTypeDef; BfTypeDef* mValueTypeTypeDef; - BfTypeDef* mResultTypeDef; - BfTypeDef* mFunctionTypeDef; + BfTypeDef* mResultTypeDef; BfTypeDef* mGCTypeDef; BfTypeDef* mGenericIEnumerableTypeDef; BfTypeDef* mGenericIEnumeratorTypeDef; diff --git a/IDEHelper/Compiler/BfConstResolver.cpp b/IDEHelper/Compiler/BfConstResolver.cpp index 0c76c570..64e24e7d 100644 --- a/IDEHelper/Compiler/BfConstResolver.cpp +++ b/IDEHelper/Compiler/BfConstResolver.cpp @@ -35,7 +35,7 @@ BfConstResolver::BfConstResolver(BfModule* bfModule) : BfExprEvaluator(bfModule) } BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfConstResolveFlags flags) -{ +{ mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime); // Handle the 'int[?] val = .(1, 2, 3)' case @@ -137,11 +137,11 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo int stringId = mModule->GetStringPoolIdx(mResult.mValue); if (stringId != -1) { - if ((flags & BfConstResolveFlag_RemapFromStringId) != 0) + if ((flags & BfConstResolveFlag_ActualizeValues) != 0) { prevIgnoreWrites.Restore(); mModule->mBfIRBuilder->PopulateType(mResult.mType); - return BfTypedValue(mModule->GetStringObjectValue(stringId), mResult.mType); + return BfTypedValue(mModule->GetStringObjectValue(stringId, false, true), mResult.mType); } return BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId), toType); @@ -232,7 +232,9 @@ BfTypedValue BfConstResolver::Resolve(BfExpression* expr, BfType* wantType, BfCo }*/ mModule->FixIntUnknown(mResult); - mModule->FixValueActualization(mResult); + + if ((flags & BfConstResolveFlag_NoActualizeValues) == 0) + mModule->FixValueActualization(mResult, !prevIgnoreWrites.mPrevVal || ((flags & BfConstResolveFlag_ActualizeValues) != 0)); return mResult; } @@ -416,15 +418,22 @@ bool BfConstResolver::PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatch } else { - if ((argValue.mValue.IsFake()) && (!argValue.mType->IsValuelessType())) - { - if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Mixin)) - { - mModule->Fail("Expression does not evaluate to a constant value", argExpr); - } + bool requiresConst = false; + if ((mModule->mCurMethodInstance == NULL) || (mModule->mCurMethodInstance->mMethodDef->mMethodType != BfMethodType_Mixin)) + requiresConst = true; + + if ((requiresConst) && (argValue.mValue.IsFake()) && (!argValue.mType->IsValuelessType())) + { + mModule->Fail("Expression does not evaluate to a constant value", argExpr); } - llvmArgs.push_back(argValue.mValue); + if (!argValue.mType->IsVar()) + { + if ((!requiresConst) || (argValue.mValue.IsConst()) || (argValue.mType->IsValuelessType())) + llvmArgs.push_back(argValue.mValue); + else + llvmArgs.push_back(mModule->GetDefaultValue(argValue.mType)); + } paramIdx++; } argIdx++; diff --git a/IDEHelper/Compiler/BfConstResolver.h b/IDEHelper/Compiler/BfConstResolver.h index 19a6b0bf..6d1d02ff 100644 --- a/IDEHelper/Compiler/BfConstResolver.h +++ b/IDEHelper/Compiler/BfConstResolver.h @@ -15,9 +15,10 @@ enum BfConstResolveFlags BfConstResolveFlag_ExplicitCast = 1, BfConstResolveFlag_NoCast = 2, BfConstResolveFlag_AllowSoftFail = 4, - BfConstResolveFlag_RemapFromStringId = 8, - BfConstResolveFlag_ArrayInitSize = 0x10, - BfConstResolveFlag_AllowGlobalVariable = 0x20, + BfConstResolveFlag_ActualizeValues = 8, + BfConstResolveFlag_NoActualizeValues = 0x10, + BfConstResolveFlag_ArrayInitSize = 0x20, + BfConstResolveFlag_AllowGlobalVariable = 0x40, }; class BfConstResolver : public BfExprEvaluator @@ -33,7 +34,7 @@ public: BfConstResolver(BfModule* bfModule); BfTypedValue Resolve(BfExpression* expr, BfType* wantType = NULL, BfConstResolveFlags flags = BfConstResolveFlag_None); - bool PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatcher* methodMatcher, Array& llvmArgs); + bool PrepareMethodArguments(BfAstNode* targetSrc, BfMethodMatcher* methodMatcher, Array& llvmArgs); }; NS_BF_END \ No newline at end of file diff --git a/IDEHelper/Compiler/BfContext.cpp b/IDEHelper/Compiler/BfContext.cpp index d4b81a39..84a13720 100644 --- a/IDEHelper/Compiler/BfContext.cpp +++ b/IDEHelper/Compiler/BfContext.cpp @@ -829,8 +829,7 @@ void BfContext::ValidateDependencies() void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuildModule, bool placeSpecializiedInPurgatory) { BfTypeInstance* typeInst = type->ToTypeInstance(); - - + if (type->IsDeleting()) { return; @@ -2517,11 +2516,6 @@ void BfContext::QueueMethodSpecializations(BfTypeInstance* typeInst, bool checkS BP_ZONE("BfContext::QueueMethodSpecializations"); - if (typeInst->mTypeId == 578) - { - NOP; - } - auto module = typeInst->mModule; if (module == NULL) return; @@ -2917,10 +2911,21 @@ void BfContext::Cleanup() // Clean up deleted BfTypes // These need to get deleted before the modules because we access mModule in the MethodInstance dtors - for (auto type : mTypeGraveyard) + for (int pass = 0; pass < 2; pass++) { - BF_ASSERT(type->mRebuildFlags & BfTypeRebuildFlag_Deleted); - delete type; + for (int i = 0; i < (int)mTypeGraveyard.size(); i++) + { + auto type = mTypeGraveyard[i]; + if (type == NULL) + continue; + bool deleteNow = (type->IsBoxed() == (pass == 0)); + if (!deleteNow) + continue; + + BF_ASSERT(type->mRebuildFlags & BfTypeRebuildFlag_Deleted); + delete type; + mTypeGraveyard[i] = NULL; + } } mTypeGraveyard.Clear(); diff --git a/IDEHelper/Compiler/BfContext.h b/IDEHelper/Compiler/BfContext.h index 6efd1fdd..c9ab4227 100644 --- a/IDEHelper/Compiler/BfContext.h +++ b/IDEHelper/Compiler/BfContext.h @@ -143,10 +143,11 @@ public: BfPopulateType mPopulateType; BfTypeReference* mCurBaseTypeRef; + BfTypeInstance* mCurBaseType; BfTypeReference* mCurAttributeTypeRef; BfFieldDef* mCurFieldDef; BfTypeDef* mCurTypeDef; - BfTypeDef* mForceActiveTypeDef; + BfTypeDef* mForceActiveTypeDef; ResolveKind mResolveKind; BfAstNode* mCurVarInitializer; int mArrayInitializerSize; @@ -160,6 +161,7 @@ public: mPopulateType = BfPopulateType_Identity; mCurBaseTypeRef = NULL; + mCurBaseType = NULL; mCurFieldDef = NULL; mCurAttributeTypeRef = NULL; mCurTypeDef = NULL; diff --git a/IDEHelper/Compiler/BfDefBuilder.cpp b/IDEHelper/Compiler/BfDefBuilder.cpp index 828f271a..3e34d58d 100644 --- a/IDEHelper/Compiler/BfDefBuilder.cpp +++ b/IDEHelper/Compiler/BfDefBuilder.cpp @@ -443,17 +443,7 @@ BfMethodDef* BfDefBuilder::CreateMethodDef(BfMethodDeclaration* methodDeclaratio { methodDef->mIsConcrete = true; methodDef->mIsVirtual = false; - } - - if (mCurTypeDef->mTypeCode == BfTypeCode_Interface) - { - // - } - else - { - if (methodDef->mIsConcrete) - Fail("Only interfaces methods can be declared as 'concrete'", methodDeclaration->mVirtualSpecifier); - } + } if (methodDef->mIsAbstract) { @@ -1775,24 +1765,21 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) bool doInsertNew = true; if (prevRevisionTypeDef != NULL) { - mCurTypeDef->mIsNextRevision = true; + mCurTypeDef->mIsNextRevision = true; bfParser->mTypeDefs.Add(prevRevisionTypeDef); if (prevRevisionTypeDef->mDefState == BfTypeDef::DefState_AwaitingNewVersion) { - delete prevRevisionTypeDef->mNextRevision; + if (prevRevisionTypeDef->mNextRevision != NULL) + { + BfLogSysM("Deleting unused nextRevision %p from prevRevision %p\n", prevRevisionTypeDef->mNextRevision, prevRevisionTypeDef); + delete prevRevisionTypeDef->mNextRevision; + } prevRevisionTypeDef->mNextRevision = mCurTypeDef; BF_ASSERT(mCurTypeDef->mSystem != NULL); mCurActualTypeDef = prevRevisionTypeDef; doInsertNew = false; - } - else - { - if (prevRevisionTypeDef->mNextRevision != NULL) - prevRevisionTypeDef = prevRevisionTypeDef->mNextRevision; - - prevRevisionTypeDef = NULL; - } + } } else { @@ -1820,8 +1807,8 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) outerTypeDef->mNestedTypes.push_back(mCurActualTypeDef); } - BfLogSysM("Creating TypeDef %p Hash:%d from TypeDecl: %p Source: %p ResolvePass: %d AutoComplete:%d\n", mCurTypeDef, mSystem->mTypeDefs.GetHash(mCurTypeDef), typeDeclaration, - typeDeclaration->GetSourceData(), mResolvePassData != NULL, isAutoCompleteTempType); + BfLogSysM("Creating TypeDef %p Hash:%d from TypeDecl: %p Source: %p ResolvePass: %d AutoComplete:%d PrevRevision:%d\n", mCurTypeDef, mSystem->mTypeDefs.GetHash(mCurTypeDef), typeDeclaration, + typeDeclaration->GetSourceData(), mResolvePassData != NULL, isAutoCompleteTempType, prevRevisionTypeDef); BF_ASSERT(mCurTypeDef->mNameEx == NULL); @@ -1875,9 +1862,9 @@ void BfDefBuilder::Visit(BfTypeDeclaration* typeDeclaration) if (mCurTypeDef->mFullHash == prevRevisionTypeDef->mFullHash) { - if (!mFullRefresh) + if ((!mFullRefresh) && (!prevRevisionTypeDef->mForceUseNextRevision)) { - BfLogSys(bfParser->mSystem, "DefBuilder deleting typeDef with no changes %p\n", prevRevisionTypeDef); + BfLogSys(bfParser->mSystem, "DefBuilder deleting typeDef with no changes %p prevRevision: %p\n", mCurTypeDef, prevRevisionTypeDef); prevRevisionTypeDef->mDefState = BfTypeDef::DefState_Defined; BF_ASSERT(prevRevisionTypeDef->mNextRevision == mCurTypeDef); prevRevisionTypeDef->mNextRevision = NULL; @@ -1918,9 +1905,10 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) BfMethodDef* dynamicCastMethod = NULL; BfMethodDef* toStringMethod = NULL; bool needsEqualsMethod = ((mCurTypeDef->mTypeCode == BfTypeCode_Struct) || (mCurTypeDef->mTypeCode == BfTypeCode_Enum)) && (!mCurTypeDef->mIsStatic); + BfMethodDef* equalsOpMethod = NULL; BfMethodDef* equalsMethod = NULL; - BfMethodDef* strictEqualsMethod = NULL; - + BfMethodDef* strictEqualsMethod = NULL; + bool needsStaticInit = false; for (int methodIdx = 0; methodIdx < (int)mCurTypeDef->mMethods.size(); methodIdx++) { @@ -1962,7 +1950,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) auto ctorDeclaration = (BfConstructorDeclaration*)method->mMethodDeclaration; if (method->mHasAppend) - { + { mCurTypeDef->mHasAppendCtor = true; auto methodDef = new BfMethodDef(); @@ -2038,6 +2026,10 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) { if (method->mName == BF_METHODNAME_MARKMEMBERS_STATIC) _SetMethod(staticMarkMethod, method); + if (method->mName == BF_METHODNAME_DEFAULT_EQUALS) + _SetMethod(equalsMethod, method); + if (method->mName == BF_METHODNAME_DEFAULT_STRICT_EQUALS) + _SetMethod(strictEqualsMethod, method); } else { @@ -2061,7 +2053,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) if ((method->mParams[0]->mTypeRef->ToString() == mCurTypeDef->mName->ToString()) && (method->mParams[1]->mTypeRef->ToString() == mCurTypeDef->mName->ToString())) { - _SetMethod(equalsMethod, method); + _SetMethod(equalsOpMethod, method); } } } @@ -2300,7 +2292,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) methodDef->mAddedAfterEmit = mIsComptime; } - if ((needsEqualsMethod) && (equalsMethod == NULL)) + if ((needsEqualsMethod) && (equalsMethod == NULL) && (equalsOpMethod == NULL)) { auto methodDef = new BfMethodDef(); mCurTypeDef->mMethods.push_back(methodDef); @@ -2314,7 +2306,7 @@ void BfDefBuilder::FinishTypeDef(bool wantsToString) methodDef->mAddedAfterEmit = mIsComptime; } - if (needsEqualsMethod) + if ((needsEqualsMethod) && (strictEqualsMethod == NULL)) { auto methodDef = new BfMethodDef(); mCurTypeDef->mMethods.push_back(methodDef); diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index c3e481ea..f98a1769 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -4248,6 +4248,14 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar mModule->PopulateType(startCheckType, BfPopulateType_BaseType); } + if ((startCheckType != NULL) && (mModule->mContext->mCurTypeState != NULL)) + { + // Don't allow lookups yet + if ((mModule->mContext->mCurTypeState->mResolveKind == BfTypeState::ResolveKind_Attributes) && + (startCheckType == mModule->mContext->mCurTypeState->mTypeInstance)) + return BfTypedValue(); + } + String findName; int varSkipCount = 0; if (fieldName.StartsWith('@')) @@ -4627,6 +4635,8 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar bool doAccessCheck = true; + if ((flags & BfLookupFieldFlag_BindOnly) != 0) + doAccessCheck = false; if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mDisableObjectAccessChecksAttributeTypeDef))) doAccessCheck = false; @@ -4853,7 +4863,7 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar } // Check for direct auto-property access - if (startCheckType == mModule->mCurTypeInstance) + if ((startCheckType == mModule->mCurTypeInstance) && ((flags & BfLookupFieldFlag_BindOnly) == 0)) { if (auto propertyDeclaration = BfNodeDynCast(mPropDef->mFieldDeclaration)) { @@ -10104,19 +10114,22 @@ void BfExprEvaluator::Visit(BfTypeOfExpression* typeOfExpr) bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifierNode* propName) { - // We ignore errors because we go through the normal Visit(BfTypeOfExpression) if this fails, which will throw the error again - SetAndRestoreValue prevIgnoreErrors(mModule->mIgnoreErrors, true); - auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef); BfType* type; - if (auto genericTypeRef = BfNodeDynCast(typeOfExpr->mTypeRef)) + // { - type = mModule->ResolveTypeRefAllowUnboundGenerics(typeOfExpr->mTypeRef, BfPopulateType_Identity); - } - else - { - type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity); + // We ignore errors because we go through the normal Visit(BfTypeOfExpression) if this fails, which will throw the error again + SetAndRestoreValue prevIgnoreErrors(mModule->mIgnoreErrors, true); + if (auto genericTypeRef = BfNodeDynCast(typeOfExpr->mTypeRef)) + { + SetAndRestoreValue prevIgnoreErrors(mModule->mIgnoreErrors, true); + type = mModule->ResolveTypeRefAllowUnboundGenerics(typeOfExpr->mTypeRef, BfPopulateType_Identity); + } + else + { + type = ResolveTypeRef(typeOfExpr->mTypeRef, BfPopulateType_Identity, BfResolveTypeRefFlag_IgnoreLookupError); + } } if (type == NULL) @@ -10206,11 +10219,42 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie else if ((memberName == "MinValue") || (memberName == "MaxValue")) { bool isMin = memberName == "MinValue"; - - BfType* checkType = typeInstance; + + BfType* checkType = type; if (checkType->IsTypedPrimitive()) checkType = checkType->GetUnderlyingType(); + if (checkType->IsGenericParam()) + { + bool foundMatch = false; + + auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)checkType); + if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) || + ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef)))) + foundMatch = true; + + if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL)) + { + for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size(); + genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++) + { + genericParamInstance = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx]; + if (genericParamInstance->mExternType == type) + { + if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) || + ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef)))) + foundMatch = true; + } + } + } + + if (foundMatch) + { + mResult = mModule->GetDefaultTypedValue(type, false, Beefy::BfDefaultValueKind_Undef); + return true; + } + } + if (checkType->IsPrimitiveType()) { auto primType = (BfPrimitiveType*)checkType; @@ -10257,15 +10301,15 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie default: break; } } - } + } - if (typeInstance->IsEnum()) + if (type->IsEnum()) { - mModule->Fail("'MinValue' cannot be used on enums with payloads", propName); + mModule->Fail(StrFormat("'MinValue' cannot be used on enum with payload '%s'", mModule->TypeToString(type).c_str()), propName); } else { - mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(typeInstance).c_str()), propName); + mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(type).c_str()), propName); } } else @@ -11923,17 +11967,18 @@ void BfExprEvaluator::VisitLambdaBodies(BfAstNode* body, BfFieldDtorDeclaration* if (auto blockBody = BfNodeDynCast(body)) mModule->VisitChild(blockBody); else if (auto bodyExpr = BfNodeDynCast(body)) - { + { auto result = mModule->CreateValueFromExpression(bodyExpr); if ((result) && (mModule->mCurMethodState->mClosureState != NULL) && (mModule->mCurMethodState->mClosureState->mReturnTypeInferState == BfReturnTypeInferState_Inferring)) - mModule->mCurMethodState->mClosureState->mReturnType = result.mType; + mModule->mCurMethodState->mClosureState->mReturnType = result.mType; } while (fieldDtor != NULL) { + mModule->mCurMethodState->mLeftBlockUncond = false; mModule->VisitChild(fieldDtor->mBody); - fieldDtor = fieldDtor->mNextFieldDtor; + fieldDtor = fieldDtor->mNextFieldDtor; } } @@ -13829,6 +13874,9 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs mModule->Fail("Too many array dimensions, consider using a jagged array.", objCreateExpr); } + if (arrayType == NULL) + return; + if (isAppendAlloc) arrayValue = BfTypedValue(mModule->AppendAllocFromType(resultType, BfIRValue(), 0, arraySize, (int)dimLengthVals.size(), isRawArrayAlloc, zeroMemory), arrayType); else @@ -14790,7 +14838,15 @@ BfModuleMethodInstance BfExprEvaluator::GetSelectedMethod(BfAstNode* targetSrc, if (unspecializedMethod == NULL) unspecializedMethod = mModule->GetRawMethodInstance(curTypeInst, methodDef); - BfType* specializedReturnType = mModule->ResolveGenericType(unspecializedMethod->mReturnType, NULL, &methodMatcher.mBestMethodGenericArguments); + BfTypeVector* typeGenericArgs = NULL; + auto typeUnspecMethodInstance = unspecializedMethod; + if (curTypeInst->IsUnspecializedTypeVariation()) + { + typeUnspecMethodInstance = mModule->GetUnspecializedMethodInstance(typeUnspecMethodInstance, true); + typeGenericArgs = &curTypeInst->mGenericTypeInfo->mTypeGenericArguments; + } + + BfType* specializedReturnType = mModule->ResolveGenericType(typeUnspecMethodInstance->mReturnType, typeGenericArgs, &methodMatcher.mBestMethodGenericArguments); if (specializedReturnType != NULL) *overrideReturnType = specializedReturnType; } @@ -18711,10 +18767,10 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr) int valueIdx = -1; for (int fieldIdx = 0; fieldIdx < (int)tupleType->mFieldInstances.size(); fieldIdx++) { - BfFieldInstance* fieldInstance = &tupleType->mFieldInstances[fieldIdx]; + BfFieldInstance* fieldInstance = &tupleType->mFieldInstances[fieldIdx]; + ++valueIdx; if (fieldInstance->mResolvedType->IsValuelessType()) continue; - ++valueIdx; auto typedVal = typedValues[valueIdx]; if (!typedVal) { @@ -20399,11 +20455,70 @@ void BfExprEvaluator::PerformBinaryOperation(BfExpression* leftExpression, BfExp } return; } - + BfType* wantType = leftValue.mType; if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift)) wantType = NULL; // Don't presume wantType = mModule->FixIntUnknown(wantType); + + if ((binaryOp == BfBinaryOp_NullCoalesce) && (leftValue) && ((leftValue.mType->IsPointer()) || (leftValue.mType->IsFunction()) || (leftValue.mType->IsObject()))) + { + auto prevBB = mModule->mBfIRBuilder->GetInsertBlock(); + + auto rhsBB = mModule->mBfIRBuilder->CreateBlock("nullc.rhs"); + auto endBB = mModule->mBfIRBuilder->CreateBlock("nullc.end"); + + BfIRValue isNull; + if (leftValue.mType->IsFunction()) + isNull = mModule->mBfIRBuilder->CreateIsNull( + mModule->mBfIRBuilder->CreateIntToPtr(leftValue.mValue, mModule->mBfIRBuilder->MapType(mModule->GetPrimitiveType(BfTypeCode_NullPtr)))); + else + isNull = mModule->mBfIRBuilder->CreateIsNull(leftValue.mValue); + mModule->mBfIRBuilder->CreateCondBr(isNull, rhsBB, endBB); + + mModule->AddBasicBlock(rhsBB); + rightValue = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_NoCast)); + if (!rightValue) + { + mModule->AssertErrorState(); + return; + } + else + { + auto rightToLeftValue = mModule->CastToValue(rightExpression, rightValue, leftValue.mType, BfCastFlags_SilentFail); + if (rightToLeftValue) + { + rightValue = BfTypedValue(rightToLeftValue, leftValue.mType); + } + else + { + auto leftToRightValue = mModule->CastToValue(leftExpression, leftValue, rightValue.mType, BfCastFlags_SilentFail); + if (leftToRightValue) + { + leftValue = BfTypedValue(leftToRightValue, rightValue.mType); + } + else + { + // Note: Annoying trigraph split for '??' + mModule->Fail(StrFormat("Operator '?" "?' cannot be applied to operands of type '%s' and '%s'", + mModule->TypeToString(leftValue.mType).c_str(), mModule->TypeToString(rightValue.mType).c_str()), opToken); + leftValue = mModule->GetDefaultTypedValue(rightValue.mType); + } + } + } + + mModule->mBfIRBuilder->CreateBr(endBB); + + auto endRhsBB = mModule->mBfIRBuilder->GetInsertBlock(); + mModule->AddBasicBlock(endBB); + auto phi = mModule->mBfIRBuilder->CreatePhi(mModule->mBfIRBuilder->MapType(leftValue.mType), 2); + mModule->mBfIRBuilder->AddPhiIncoming(phi, leftValue.mValue, prevBB); + mModule->mBfIRBuilder->AddPhiIncoming(phi, rightValue.mValue, endRhsBB); + mResult = BfTypedValue(phi, leftValue.mType); + + return; + } + rightValue = mModule->CreateValueFromExpression(rightExpression, wantType, (BfEvalExprFlags)((mBfEvalExprFlags & BfEvalExprFlags_InheritFlags) | BfEvalExprFlags_NoCast)); if ((!leftValue) || (!rightValue)) return; @@ -20611,58 +20726,6 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod return; } - if ((binaryOp == BfBinaryOp_NullCoalesce) && ((leftValue.mType->IsPointer()) || (leftValue.mType->IsObject()))) - { - auto prevBB = mModule->mBfIRBuilder->GetInsertBlock(); - - auto rhsBB = mModule->mBfIRBuilder->CreateBlock("nullc.rhs"); - auto endBB = mModule->mBfIRBuilder->CreateBlock("nullc.end"); - - auto isNull = mModule->mBfIRBuilder->CreateIsNull(leftValue.mValue); - mModule->mBfIRBuilder->CreateCondBr(isNull, rhsBB, endBB); - - mModule->AddBasicBlock(rhsBB); - if (!rightValue) - { - mModule->AssertErrorState(); - return; - } - else - { - auto rightToLeftValue = mModule->CastToValue(rightExpression, rightValue, leftValue.mType, BfCastFlags_SilentFail); - if (rightToLeftValue) - { - rightValue = BfTypedValue(rightToLeftValue, leftValue.mType); - } - else - { - auto leftToRightValue = mModule->CastToValue(leftExpression, leftValue, rightValue.mType, BfCastFlags_SilentFail); - if (leftToRightValue) - { - leftValue = BfTypedValue(leftToRightValue, rightValue.mType); - } - else - { - // Note: Annoying trigraph split for '??' - mModule->Fail(StrFormat("Operator '?" "?' cannot be applied to operands of type '%s' and '%s'", - mModule->TypeToString(leftValue.mType).c_str(), mModule->TypeToString(rightValue.mType).c_str()), opToken); - leftValue = mModule->GetDefaultTypedValue(rightValue.mType); - } - } - } - - mModule->mBfIRBuilder->CreateBr(endBB); - - auto endRhsBB = mModule->mBfIRBuilder->GetInsertBlock(); - mModule->AddBasicBlock(endBB); - auto phi = mModule->mBfIRBuilder->CreatePhi(mModule->mBfIRBuilder->MapType(leftValue.mType), 2); - mModule->mBfIRBuilder->AddPhiIncoming(phi, leftValue.mValue, prevBB); - mModule->mBfIRBuilder->AddPhiIncoming(phi, rightValue.mValue, endRhsBB); - mResult = BfTypedValue(phi, leftValue.mType); - - return; - } - if ((binaryOp == BfBinaryOp_LeftShift) || (binaryOp == BfBinaryOp_RightShift)) { forceLeftType = true; diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 9469c721..427f6c9d 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -615,17 +615,7 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f else if (fromConst->mConstType == BfConstType_GlobalVar) { auto fromGlobalVar = (BfGlobalVar*)fromConst; - auto constGV = mTempAlloc.Alloc(); - chunkId = mTempAlloc.GetChunkedId(constGV); - constGV->mStreamId = -1; - constGV->mConstType = BfConstType_GlobalVar; - constGV->mType = fromGlobalVar->mType; - constGV->mIsConst = fromGlobalVar->mIsConst; - constGV->mLinkageType = fromGlobalVar->mLinkageType; - constGV->mInitializer = fromGlobalVar->mInitializer; - constGV->mName = AllocStr(fromGlobalVar->mName); - constGV->mIsTLS = fromGlobalVar->mIsTLS; - copiedConst = (BfConstant*)constGV; + return CreateGlobalVariableConstant(fromGlobalVar->mType, fromGlobalVar->mIsConst, fromGlobalVar->mLinkageType, fromGlobalVar->mInitializer, fromGlobalVar->mName, fromGlobalVar->mIsTLS); } else if (fromConst->mConstType == BfConstType_GEP32_2) { @@ -1875,6 +1865,7 @@ void BfIRBuilder::ClearConstData() mTempAlloc.Clear(); mConstMemMap.Clear(); mFunctionMap.Clear(); + mGlobalVarMap.Clear(); BF_ASSERT(mMethodTypeMap.GetCount() == 0); BF_ASSERT(mTypeMap.GetCount() == 0); BF_ASSERT(mDITemporaryTypes.size() == 0); @@ -1889,6 +1880,7 @@ void BfIRBuilder::ClearNonConstData() { mMethodTypeMap.Clear(); mFunctionMap.Clear(); + mGlobalVarMap.Clear(); mTypeMap.Clear(); mConstMemMap.Clear(); mDITemporaryTypes.Clear(); @@ -2996,11 +2988,6 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type) if (fieldInstance->mConstIdx != -1) { - if (fieldInstance->GetFieldDef()->mName == "mMembers") - { - NOP; - } - constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx); staticValue = mModule->ConstantToCurrent(constant, typeInstance->mConstHolder, resolvedFieldType); } @@ -4743,39 +4730,53 @@ BfIRValue BfIRBuilder::CreateStackRestore(BfIRValue stackVal) return retVal; } -BfIRValue BfIRBuilder::CreateGlobalVariable(BfIRType varType, bool isConstant, BfIRLinkageType linkageType, BfIRValue initializer, const StringImpl& name, bool isTLS) +void BfIRBuilder::CreateGlobalVariable(BfIRValue irValue) { + auto globalVar = (BfGlobalVar*)GetConstant(irValue); + + if ((!mIgnoreWrites) && (globalVar->mStreamId == -1)) + { + if (globalVar->mInitializer) + mHasGlobalDefs = true; + + BfIRValue retVal = WriteCmd(BfIRCmd_GlobalVariable, globalVar->mType, globalVar->mIsConst, (uint8)globalVar->mLinkageType, String(globalVar->mName), globalVar->mIsTLS, globalVar->mInitializer); + globalVar->mStreamId = retVal.mId; + + NEW_CMD_INSERTED_IRVALUE; + } +} + +BfIRValue BfIRConstHolder::CreateGlobalVariableConstant(BfIRType varType, bool isConstant, BfIRLinkageType linkageType, BfIRValue initializer, const StringImpl& name, bool isTLS) +{ + BfIRValue* valuePtr = NULL; + if ((!mGlobalVarMap.TryAdd(name, NULL, &valuePtr)) && (!initializer)) + { + return *valuePtr; + } + BF_ASSERT(varType); auto constGV = mTempAlloc.Alloc(); int chunkId = mTempAlloc.GetChunkedId(constGV); constGV->mStreamId = -1; - constGV->mConstType = BfConstType_GlobalVar; - constGV->mType = varType; + constGV->mConstType = BfConstType_GlobalVar; + constGV->mType = varType; constGV->mIsConst = isConstant; constGV->mLinkageType = linkageType; constGV->mInitializer = initializer; constGV->mName = AllocStr(name); - constGV->mIsTLS = isTLS; + constGV->mIsTLS = isTLS; - if (!mIgnoreWrites) - { - if (initializer) - mHasGlobalDefs = true; + auto irValue = BfIRValue(BfIRValueFlags_Const, chunkId);; + *valuePtr = irValue; + return irValue; +} - BfIRValue retVal = WriteCmd(BfIRCmd_GlobalVariable, varType, isConstant, (uint8)linkageType, name, isTLS, initializer); - constGV->mStreamId = retVal.mId; - retVal.mFlags = BfIRValueFlags_Const; -#ifdef CHECK_CONSTHOLDER - retVal.mHolder = this; -#endif - retVal.mId = chunkId; - NEW_CMD_INSERTED_IRVALUE; - return retVal; - } - - auto irValue = BfIRValue(BfIRValueFlags_Const, chunkId); - return irValue; +BfIRValue BfIRBuilder::CreateGlobalVariable(BfIRType varType, bool isConstant, BfIRLinkageType linkageType, BfIRValue initializer, const StringImpl& name, bool isTLS) +{ + auto irValue = CreateGlobalVariableConstant(varType, isConstant, linkageType, initializer, name, isTLS); + CreateGlobalVariable(irValue); + return irValue; } void BfIRBuilder::GlobalVar_SetUnnamedAddr(BfIRValue val, bool unnamedAddr) diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index ff098a6c..3d045deb 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -901,6 +901,7 @@ class BfIRConstHolder public: BumpAllocatorT<256> mTempAlloc; BfModule* mModule; + Dictionary mGlobalVarMap; public: void FixTypeCode(BfTypeCode& typeCode); @@ -936,6 +937,7 @@ public: BfIRValue CreateTypeOf(BfType* type); BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData); BfIRValue GetUndefConstValue(BfIRType type); + BfIRValue CreateGlobalVariableConstant(BfIRType varType, bool isConstant, BfIRLinkageType linkageType, BfIRValue initializer, const StringImpl& name, bool isTLS = false); bool WriteConstant(BfIRValue val, void* ptr, BfType* type); BfIRValue ReadConstant(void* ptr, BfType* type); @@ -979,7 +981,7 @@ public: bool mHasDebugInfo; bool mHasDebugLineInfo; Dictionary mMethodTypeMap; - Dictionary mFunctionMap; + Dictionary mFunctionMap; Dictionary mTypeMap; Dictionary mConstMemMap; Array mDITemporaryTypes; @@ -1227,6 +1229,7 @@ public: BfIRValue CreateStackRestore(BfIRValue stackVal); BfIRValue CreateGlobalVariable(BfIRType varType, bool isConstant, BfIRLinkageType linkageType, BfIRValue initializer, const StringImpl& name, bool isTLS = false); + void CreateGlobalVariable(BfIRValue irValue); void GlobalVar_SetUnnamedAddr(BfIRValue val, bool unnamedAddr); void GlobalVar_SetInitializer(BfIRValue globalVar, BfIRValue initVal); void GlobalVar_SetAlignment(BfIRValue globalVar, int alignment); diff --git a/IDEHelper/Compiler/BfIRCodeGen.cpp b/IDEHelper/Compiler/BfIRCodeGen.cpp index 986471cb..94ec1b69 100644 --- a/IDEHelper/Compiler/BfIRCodeGen.cpp +++ b/IDEHelper/Compiler/BfIRCodeGen.cpp @@ -810,13 +810,17 @@ void BfIRCodeGen::Read(llvm::Value*& llvmValue, BfIRCodeGenEntry** codeGenEntry, llvm::GlobalVariable* globalVariable = mLLVMModule->getGlobalVariable(name.c_str(), true); if (globalVariable == NULL) { - globalVariable = new llvm::GlobalVariable( - *mLLVMModule, - varType, - isConstant, - LLVMMapLinkageType(linkageType), - initializer, - name.c_str(), NULL, isTLS ? llvm::GlobalValue::GeneralDynamicTLSModel : llvm::GlobalValue::NotThreadLocal); + globalVariable = mLLVMModule->getGlobalVariable(name.c_str()); + if (globalVariable == NULL) + { + globalVariable = new llvm::GlobalVariable( + *mLLVMModule, + varType, + isConstant, + LLVMMapLinkageType(linkageType), + initializer, + name.c_str(), NULL, isTLS ? llvm::GlobalValue::GeneralDynamicTLSModel : llvm::GlobalValue::NotThreadLocal); + } } llvmValue = globalVariable; @@ -2389,13 +2393,17 @@ void BfIRCodeGen::HandleNextCmd() CMD_PARAM(bool, isTLS); CMD_PARAM(llvm::Constant*, initializer); - auto globalVariable = new llvm::GlobalVariable( - *mLLVMModule, - varType, - isConstant, - LLVMMapLinkageType(linkageType), - initializer, - name.c_str(), NULL, isTLS ? llvm::GlobalValue::GeneralDynamicTLSModel : llvm::GlobalValue::NotThreadLocal); + auto globalVariable = mLLVMModule->getGlobalVariable(name.c_str()); + if (globalVariable == NULL) + { + globalVariable = new llvm::GlobalVariable( + *mLLVMModule, + varType, + isConstant, + LLVMMapLinkageType(linkageType), + initializer, + name.c_str(), NULL, isTLS ? llvm::GlobalValue::GeneralDynamicTLSModel : llvm::GlobalValue::NotThreadLocal); + } SetResult(curId, globalVariable); } break; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 563214ca..5908bfbd 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1222,7 +1222,10 @@ void BfModule::StartNewRevision(RebuildKind rebuildKind, bool force) // Clear this here, not in ClearModuleData, so we preserve those references even after writing out module if (rebuildKind != BfModule::RebuildKind_None) // Leave string pool refs for when we need to use things like [LinkName("")] methods bofore re-reification - mStringPoolRefs.Clear(); + { + mStringPoolRefs.Clear(); + mUnreifiedStringPoolRefs.Clear(); + } mDllImportEntries.Clear(); mImportFileNames.Clear(); for (auto& pairVal : mDeferredMethodCallData) @@ -1543,7 +1546,7 @@ BfIRValue BfModule::CreateStringCharPtr(const StringImpl& str, int stringId, boo } BfIRValue BfModule::CreateStringObjectValue(const StringImpl& str, int stringId, bool define) -{ +{ auto stringTypeInst = ResolveTypeDef(mCompiler->mStringTypeDef, define ? BfPopulateType_Data : BfPopulateType_Declaration)->ToTypeInstance(); mBfIRBuilder->PopulateType(stringTypeInst); @@ -1654,8 +1657,14 @@ String* BfModule::GetStringPoolString(BfIRValue constantStr, BfIRConstHolder * c return NULL; } -BfIRValue BfModule::GetStringCharPtr(int stringId) +BfIRValue BfModule::GetStringCharPtr(int stringId, bool force) { + if ((mBfIRBuilder->mIgnoreWrites) && (!force)) + { + mUnreifiedStringPoolRefs.Add(stringId); + return mBfIRBuilder->CreateConst(BfTypeCode_StringId, stringId); + } + BfIRValue* irValue = NULL; if (!mStringCharPtrPool.TryAdd(stringId, NULL, &irValue)) return *irValue; @@ -1670,13 +1679,13 @@ BfIRValue BfModule::GetStringCharPtr(int stringId) return strCharPtrConst; } -BfIRValue BfModule::GetStringCharPtr(BfIRValue strValue) +BfIRValue BfModule::GetStringCharPtr(BfIRValue strValue, bool force) { if (strValue.IsConst()) { int stringId = GetStringPoolIdx(strValue); BF_ASSERT(stringId != -1); - return GetStringCharPtr(stringId); + return GetStringCharPtr(stringId, force); } BfIRValue charPtrPtr = mBfIRBuilder->CreateInBoundsGEP(strValue, 0, 1); @@ -1684,27 +1693,33 @@ BfIRValue BfModule::GetStringCharPtr(BfIRValue strValue) return charPtr; } -BfIRValue BfModule::GetStringCharPtr(const StringImpl& str) +BfIRValue BfModule::GetStringCharPtr(const StringImpl& str, bool force) { - return GetStringCharPtr(GetStringObjectValue(str)); + return GetStringCharPtr(GetStringObjectValue(str, force), force); } -BfIRValue BfModule::GetStringObjectValue(int strId) +BfIRValue BfModule::GetStringObjectValue(int strId, bool define, bool force) { BfIRValue* objValue; if (mStringObjectPool.TryGetValue(strId, &objValue)) return *objValue; auto stringPoolEntry = mContext->mStringObjectIdMap[strId]; - return GetStringObjectValue(stringPoolEntry.mString, true); + return GetStringObjectValue(stringPoolEntry.mString, define, force); } -BfIRValue BfModule::GetStringObjectValue(const StringImpl& str, bool define) +BfIRValue BfModule::GetStringObjectValue(const StringImpl& str, bool define, bool force) { auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef, define ? BfPopulateType_Data : BfPopulateType_Declaration); mBfIRBuilder->PopulateType(stringType); - int strId = mContext->GetStringLiteralId(str); + int strId = mContext->GetStringLiteralId(str); + + if ((mBfIRBuilder->mIgnoreWrites) && (!force)) + { + mUnreifiedStringPoolRefs.Add(strId); + return mBfIRBuilder->CreateConst(BfTypeCode_StringId, strId); + } BfIRValue* irValuePtr = NULL; if (!mStringObjectPool.TryAdd(strId, NULL, &irValuePtr)) @@ -1916,13 +1931,7 @@ void BfModule::AddStackAlloc(BfTypedValue val, BfIRValue arraySize, BfAstNode* r bool hadDtorCall = false; while (checkBaseType != NULL) { - checkBaseType->mTypeDef->PopulateMemberSets(); - BfMemberSetEntry* entry = NULL; - BfMethodDef* dtorMethodDef = NULL; - checkBaseType->mTypeDef->mMethodSet.TryGetWith(String("~this"), &entry); - if (entry != NULL) - dtorMethodDef = (BfMethodDef*)entry->mMemberDef; - + BfMethodDef* dtorMethodDef = checkBaseType->mTypeDef->GetMethodByName("~this"); if (dtorMethodDef != NULL) { auto dtorMethodInstance = GetMethodInstance(checkBaseType, dtorMethodDef, BfTypeVector()); @@ -3416,10 +3425,11 @@ void BfModule::AddDependency(BfType* usedType, BfType* userType, BfDependencyMap BfModule* usedModule; if (usedType->IsFunction()) { - auto typeInst = usedType->ToTypeInstance(); - if (typeInst->mBaseType == NULL) - PopulateType(typeInst); - usedModule = typeInst->mBaseType->GetModule(); + if (mCompiler->mFunctionTypeDef != NULL) + { + auto functionType = ResolveTypeDef(mCompiler->mFunctionTypeDef)->ToTypeInstance(); + usedModule = functionType->GetModule(); + } } else usedModule = usedType->GetModule(); @@ -5235,7 +5245,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin typeFlags |= BfTypeFlags_Delegate; if (type->IsFunction()) typeFlags |= BfTypeFlags_Function; - if (type->WantsGCMarking()) + if ((type->mDefineState != BfTypeDefineState_CETypeInit) && (type->WantsGCMarking())) typeFlags |= BfTypeFlags_WantsMarking; int virtSlotIdx = -1; @@ -5906,8 +5916,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (needsTypeNames) { - typeNameConst = GetStringObjectValue(typeDef->mName->mString, true); - namespaceConst = GetStringObjectValue(typeDef->mNamespace.ToString(), true); + typeNameConst = GetStringObjectValue(typeDef->mName->mString, !mIsComptimeModule); + namespaceConst = GetStringObjectValue(typeDef->mNamespace.ToString(), !mIsComptimeModule); } else { @@ -5967,7 +5977,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin // Fields BfType* reflectFieldDataType = ResolveTypeDef(mCompiler->mReflectFieldDataDef); BfIRValue emptyValueType = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(reflectFieldDataType->ToTypeInstance()->mBaseType), SizedArray()); - + auto _HandleCustomAttrs = [&](BfCustomAttributes* customAttributes) { if (customAttributes == NULL) @@ -6023,7 +6033,28 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin PUSH_INT16(0); // mSize PUSH_INT32(attr->mType->mTypeId); // mType - PUSH_INT16(attr->mCtor->mIdx); + + int ctorIdx = -1; + int ctorCount = 0; + + attr->mType->mTypeDef->PopulateMemberSets(); + BfMemberSetEntry* entry; + if (attr->mType->mTypeDef->mMethodSet.TryGetWith(String("__BfCtor"), &entry)) + { + BfMethodDef* nextMethodDef = (BfMethodDef*)entry->mMemberDef; + while (nextMethodDef != NULL) + { + if (nextMethodDef == attr->mCtor) + ctorIdx = ctorCount; + nextMethodDef = nextMethodDef->mNextWithSameName; + ctorCount++; + } + } + + BF_ASSERT(ctorIdx != -1); + if (ctorIdx != -1) + ctorIdx = (ctorCount - 1) - ctorIdx; + PUSH_INT16(ctorIdx); auto ctorMethodInstance = GetRawMethodInstanceAtIdx(attr->mType, attr->mCtor->mIdx); int argIdx = 0; @@ -6047,7 +6078,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin *orderedIdPtr = (int)usedStringIdMap.size() - 1; } - GetStringObjectValue(stringId); + GetStringObjectValue(stringId, true, true); PUSH_INT8(0xFF); // String PUSH_INT32(*orderedIdPtr); argIdx++; @@ -6067,7 +6098,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin *orderedIdPtr = (int)usedStringIdMap.size() - 1; } - GetStringObjectValue(stringId); + GetStringObjectValue(stringId, true, true); PUSH_INT8(0xFF); // String PUSH_INT32(*orderedIdPtr); argIdx++; @@ -6231,7 +6262,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfType* payloadType = typeInstance->GetUnionInnerType(); if (!payloadType->IsValuelessType()) { - BfIRValue payloadNameConst = GetStringObjectValue("$payload", true); + BfIRValue payloadNameConst = GetStringObjectValue("$payload", !mIsComptimeModule); SizedArray payloadFieldVals = { emptyValueType, @@ -6246,7 +6277,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } BfType* dscrType = typeInstance->GetDiscriminatorType(); - BfIRValue dscrNameConst = GetStringObjectValue("$discriminator", true); + BfIRValue dscrNameConst = GetStringObjectValue("$discriminator", !mIsComptimeModule); SizedArray dscrFieldVals = { emptyValueType, @@ -6268,7 +6299,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfFieldInstance* fieldInstance = &typeInstance->mFieldInstances[fieldIdx]; BfFieldDef* fieldDef = fieldInstance->GetFieldDef(); - BfIRValue fieldNameConst = GetStringObjectValue(fieldDef->mName, true); + BfIRValue fieldNameConst = GetStringObjectValue(fieldDef->mName, !mIsComptimeModule); int typeId = 0; auto fieldType = fieldInstance->GetResolvedType(); @@ -6448,6 +6479,14 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfType* reflectParamDataType = ResolveTypeDef(mCompiler->mReflectParamDataDef); BfType* reflectParamDataPtrType = CreatePointerType(reflectParamDataType); + struct _SortedMethodInfo + { + BfMethodDef* mMethodDef; + BfCustomAttributes* mMethodCustomAttributes; + }; + + Array<_SortedMethodInfo> sortedMethodList; + SizedArray methodTypes; for (int methodIdx = 0; methodIdx < (int)typeDef->mMethods.size(); methodIdx++) { @@ -6460,7 +6499,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodIdx]; if (!methodInstanceGroup->IsImplemented()) - continue; + continue; auto methodDef = typeDef->mMethods[methodIdx]; if (methodDef->mIsNoReflect) continue; @@ -6474,12 +6513,12 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin continue; if (!defaultMethod->mIsReified) continue; - + if ((defaultMethod->mChainType == BfMethodChainType_ChainMember) || (defaultMethod->mChainType == BfMethodChainType_ChainSkip)) continue; if (defaultMethod->mMethodDef->mMethodType == BfMethodType_CtorNoBody) - continue; - + continue; + auto methodReflectKind = (BfReflectKind)(reflectKind & ~BfReflectKind_User); bool includeMethod = reflectIncludeAllMethods; @@ -6501,10 +6540,10 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } } - + if ((!mIsComptimeModule) && (!typeInstance->IsTypeMemberAccessible(methodDef->mDeclaringType, mProject))) continue; - + // { SetAndRestoreValue prevTypeInstance(mCurTypeInstance, typeInstance); @@ -6522,13 +6561,42 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin includeMethod = true; if ((methodDef->mIsStatic) && ((methodReflectKind & BfReflectKind_StaticMethods) != 0)) includeMethod = true; - + if ((!includeMethod) && (typeOptions != NULL)) includeMethod = ApplyTypeOptionMethodFilters(includeMethod, methodDef, typeOptions); - + if (!includeMethod) continue; + sortedMethodList.Add({ methodDef, methodCustomAttributes }); + } + + auto _GetMethodKind = [](BfMethodDef* methodDef) + { + if (methodDef->mMethodType == BfMethodType_Ctor) + return 0; + return 1; + }; + + std::sort(sortedMethodList.begin(), sortedMethodList.end(), [_GetMethodKind](const _SortedMethodInfo& lhs, const _SortedMethodInfo& rhs) + { + int lhsKind = _GetMethodKind(lhs.mMethodDef); + int rhsKind = _GetMethodKind(rhs.mMethodDef); + + if (lhsKind != rhsKind) + return lhsKind < rhsKind; + if (lhs.mMethodDef->mName != rhs.mMethodDef->mName) + return lhs.mMethodDef->mName < rhs.mMethodDef->mName; + return lhs.mMethodDef->mIdx < rhs.mMethodDef->mIdx; + }); + + for (auto& methodInfo : sortedMethodList) + { + auto methodDef = methodInfo.mMethodDef; + int methodIdx = methodDef->mIdx; + auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodIdx]; + auto defaultMethod = methodInstanceGroup->mDefault; + BfModuleMethodInstance moduleMethodInstance; BfIRValue funcVal = voidPtrNull; @@ -6544,11 +6612,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin funcVal = mBfIRBuilder->CreateBitCast(moduleMethodInstance.mFunc, voidPtrIRType); } - BfIRValue methodNameConst = GetStringObjectValue(methodDef->mName, true); + BfIRValue methodNameConst = GetStringObjectValue(methodDef->mName, !mIsComptimeModule); BfMethodFlags methodFlags = defaultMethod->GetMethodFlags(); - int customAttrIdx = _HandleCustomAttrs(methodCustomAttributes); + int customAttrIdx = _HandleCustomAttrs(methodInfo.mMethodCustomAttributes); enum ParamFlags { @@ -6567,7 +6635,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (defaultMethod->GetParamIsSplat(paramIdx)) paramFlags = (ParamFlags)(paramFlags | ParamFlag_Splat); - BfIRValue paramNameConst = GetStringObjectValue(paramName, true); + BfIRValue paramNameConst = GetStringObjectValue(paramName, !mIsComptimeModule); SizedArray paramDataVals = { @@ -7150,7 +7218,7 @@ BfIRFunction BfModule::GetBuiltInFunc(BfBuiltInFuncType funcTypeId) return mBuiltInFuncs[(int)funcTypeId]; } -void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized) +void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized, Array* deferredResolveTypes) { BfGenericParamDef* genericParamDef = genericParamInstance->GetGenericParamDef(); BfExternalConstraintDef* externConstraintDef = genericParamInstance->GetExternConstraintDef(); @@ -7256,14 +7324,23 @@ void BfModule::ResolveGenericParamConstraints(BfGenericParamInstance* genericPar if (bfAutocomplete != NULL) bfAutocomplete->CheckTypeRef(constraintTypeRef, true); //TODO: Constraints may refer to other generic params (of either type or method) - // TO allow resolution, perhaps move this generic param initalization into GetMethodInstance (passing a genericPass bool) + // TO allow resolution, perhaps move this generic param initialization into GetMethodInstance (passing a genericPass bool) BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_AllowGenericMethodParamConstValue; if (isUnspecialized) resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_DisallowComptime); - auto constraintType = ResolveTypeRef(constraintTypeRef, BfPopulateType_Declaration, resolveFlags); + // We we have a deferredResolveTypes then we defer the generic validation, because we may have a case like + // `where T : Dictionay and TElem : IHashable` and we don't want to throw the error on `T` before we build `TElem` + auto constraintType = ResolveTypeRef(constraintTypeRef, (deferredResolveTypes != NULL) ? BfPopulateType_Identity : BfPopulateType_Declaration, resolveFlags); if (constraintType != NULL) - { + { + if (deferredResolveTypes != NULL) + { + PopulateType(constraintType, BfPopulateType_Declaration); + if (constraintType->IsUnspecializedTypeVariation()) + deferredResolveTypes->Add(constraintTypeRef); + } + if ((constraintDef->mGenericParamFlags & BfGenericParamFlag_Const) != 0) { bool isValidTypeCode = false; @@ -7444,11 +7521,11 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS origCheckArgType = origCheckArgType->GetUnderlyingType(); bool argMayBeReferenceType = false; - + int checkGenericParamFlags = 0; if (checkArgType->IsGenericParam()) { - auto checkGenericParamInst = GetGenericParamInstance((BfGenericParamType*)checkArgType); + BfGenericParamInstance* checkGenericParamInst = GetGenericParamInstance((BfGenericParamType*)checkArgType); checkGenericParamFlags = checkGenericParamInst->mGenericParamFlags; if (checkGenericParamInst->mTypeConstraint != NULL) checkArgType = checkGenericParamInst->mTypeConstraint; @@ -7782,7 +7859,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS if (TypeIsSubTypeOf(wrappedStructType, typeConstraintInst)) implementsInterface = true; } - + if (!implementsInterface) { if ((!ignoreErrors) && (PreFail())) @@ -10601,6 +10678,7 @@ void BfModule::ClearConstData() mStringObjectPool.Clear(); mStringCharPtrPool.Clear(); mStringPoolRefs.Clear(); + mUnreifiedStringPoolRefs.Clear(); } BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType) @@ -10630,17 +10708,18 @@ BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConst auto constVal = mBfIRBuilder->CreateConst(constant, constHolder); BfTypedValue typedValue; + bool allowUnactualized = mBfIRBuilder->mIgnoreWrites; if (constant->mTypeCode == BfTypeCode_StringId) { if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) || ((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8)))) { - typedValue = BfTypedValue(ConstantToCurrent(constant, constHolder, wantType), wantType); + typedValue = BfTypedValue(ConstantToCurrent(constant, constHolder, wantType, allowUnactualized), wantType); return typedValue; } auto stringType = ResolveTypeDef(mCompiler->mStringTypeDef); - typedValue = BfTypedValue(ConstantToCurrent(constant, constHolder, stringType), stringType); + typedValue = BfTypedValue(ConstantToCurrent(constant, constHolder, stringType, allowUnactualized), stringType); } if (!typedValue) @@ -10684,7 +10763,27 @@ BfTypedValue BfModule::GetTypedValueFromConstant(BfConstant* constant, BfIRConst return BfTypedValue(irValue, wantType, false); } -BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowStringId) +bool BfModule::HasUnactializedConstant(BfConstant* constant, BfIRConstHolder* constHolder) +{ + if ((constant->mConstType == BfConstType_TypeOf) || (constant->mConstType == BfConstType_TypeOf_WithData)) + return true; + if (constant->mTypeCode == BfTypeCode_StringId) + return true; + + if (constant->mConstType == BfConstType_Agg) + { + auto constArray = (BfConstantAgg*)constant; + for (auto val : constArray->mValues) + { + if (HasUnactializedConstant(constHolder->GetConstant(val), constHolder)) + return true; + } + } + + return false; +} + +BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowUnactualized) { if (constant->mTypeCode == BfTypeCode_NullPtr) { @@ -10699,20 +10798,27 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con if (constant->mTypeCode == BfTypeCode_StringId) { - if (!allowStringId) + if (!allowUnactualized) { if ((wantType->IsInstanceOf(mCompiler->mStringTypeDef)) || ((wantType->IsPointer()) && (wantType->GetUnderlyingType() == GetPrimitiveType(BfTypeCode_Char8)))) { const StringImpl& str = mContext->mStringObjectIdMap[constant->mInt32].mString; - BfIRValue stringObjConst = GetStringObjectValue(str); + BfIRValue stringObjConst = GetStringObjectValue(str, false, true); if (wantType->IsPointer()) - return GetStringCharPtr(stringObjConst); + return GetStringCharPtr(stringObjConst, true); return stringObjConst; } } } + if (constant->mConstType == Beefy::BfConstType_TypeOf) + { + auto constTypeOf = (BfTypeOf_Const*)constant; + AddDependency(constTypeOf->mType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); + return CreateTypeDataRef(constTypeOf->mType); + } + if (constant->mConstType == BfConstType_Agg) { auto constArray = (BfConstantAgg*)constant; @@ -10789,6 +10895,9 @@ void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, Bf void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget, bool allowNonConstArgs, BfCaptureInfo* captureInfo) { + if (!mCompiler->mHasRequiredTypes) + return; + if ((attributesDirective != NULL) && (mCompiler->mResolvePassData != NULL) && (attributesDirective->IsFromParser(mCompiler->mResolvePassData->mParser)) && (mCompiler->mResolvePassData->mSourceClassifier != NULL)) { @@ -10908,6 +11017,12 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri continue; } + if ((mIsReified) && (attrTypeInst->mAttributeData != NULL) && ((attrTypeInst->mAttributeData->mFlags & BfAttributeFlag_ReflectAttribute) != 0)) + { + // Reify attribute + PopulateType(attrTypeInst); + } + if (mCurTypeInstance != NULL) AddDependency(attrTypeInst, mCurTypeInstance, BfDependencyMap::DependencyFlag_CustomAttribute); @@ -11018,8 +11133,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri auto& fieldTypeInst = checkTypeInst->mFieldInstances[bestField->mIdx]; if (assignExpr->mRight != NULL) - { - BfTypedValue result = constResolver.Resolve(assignExpr->mRight, fieldTypeInst.mResolvedType); + { + BfTypedValue result = constResolver.Resolve(assignExpr->mRight, fieldTypeInst.mResolvedType, BfConstResolveFlag_NoActualizeValues); if (result) { CurrentAddToConstHolder(result.mValue); @@ -11078,9 +11193,11 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri auto propType = methodInstance.mMethodInstance->GetParamType(0); if (assignExpr->mRight != NULL) { - BfTypedValue result = constResolver.Resolve(assignExpr->mRight, propType); - if (result) + BfTypedValue result = constResolver.Resolve(assignExpr->mRight, propType, BfConstResolveFlag_NoActualizeValues); + if ((result) && (!result.mType->IsVar())) { + if (!result.mValue.IsConst()) + result = GetDefaultTypedValue(result.mType); BF_ASSERT(result.mType == propType); CurrentAddToConstHolder(result.mValue); setProperty.mParam = result; @@ -11092,7 +11209,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri } if ((!handledExpr) && (assignExpr->mRight != NULL)) - constResolver.Resolve(assignExpr->mRight); + constResolver.Resolve(assignExpr->mRight, NULL, BfConstResolveFlag_NoActualizeValues); } else { @@ -11112,7 +11229,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri resolvedArg.mArgFlags = BfArgFlag_DeferredEval; } else - resolvedArg.mTypedValue = constResolver.Resolve(arg); + resolvedArg.mTypedValue = constResolver.Resolve(arg, NULL, BfConstResolveFlag_NoActualizeValues); if (!inPropSet) { @@ -11193,7 +11310,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri if ((arg.mArgFlags & BfArgFlag_DeferredEval) != 0) { if (auto expr = BfNodeDynCast(arg.mExpression)) - constResolver.Resolve(expr); + constResolver.Resolve(expr, NULL, BfConstResolveFlag_NoActualizeValues); } } @@ -11512,14 +11629,17 @@ BfVariant BfModule::TypedValueToVariant(BfAstNode* refNode, const BfTypedValue& case BfTypeCode_UIntPtr: case BfTypeCode_IntUnknown: case BfTypeCode_UIntUnknown: - case BfTypeCode_Float: case BfTypeCode_Double: case BfTypeCode_Char8: case BfTypeCode_Char16: case BfTypeCode_Char32: variant.mTypeCode = constant->mTypeCode; variant.mInt64 = constant->mInt64; - break; + break; + case BfTypeCode_Float: + variant.mTypeCode = constant->mTypeCode; + variant.mSingle = (float)constant->mDouble; + break; default: if (refNode != NULL) Fail("Invalid const expression type", refNode); @@ -13624,6 +13744,13 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) { globalValue = *globalValuePtr; BF_ASSERT(globalValue); + + auto globalVar = (BfGlobalVar*)mBfIRBuilder->GetConstant(globalValue); + if ((globalVar->mStreamId == -1) && (!mBfIRBuilder->mIgnoreWrites)) + { + mBfIRBuilder->MapType(fieldInstance->mResolvedType); + mBfIRBuilder->CreateGlobalVariable(globalValue); + } } else { @@ -13655,16 +13782,11 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) BfIRValue(), staticVarName, IsThreadLocal(fieldInstance)); - - if (!mBfIRBuilder->mIgnoreWrites) - { - // Only store this if we actually did the creation - BF_ASSERT(globalValue); - mStaticFieldRefs[fieldInstance] = globalValue; - } + + BF_ASSERT(globalValue); + mStaticFieldRefs[fieldInstance] = globalValue; BfLogSysM("Mod:%p Type:%p ReferenceStaticField %p -> %p\n", this, fieldInstance->mOwner, fieldInstance, globalValue); - } } @@ -13676,7 +13798,7 @@ BfTypedValue BfModule::ReferenceStaticField(BfFieldInstance* fieldInstance) } BfTypedValue BfModule::GetThis() -{ +{ auto useMethodState = mCurMethodState; while ((useMethodState != NULL) && (useMethodState->mClosureState != NULL) && (useMethodState->mClosureState->mCapturing)) { @@ -13705,33 +13827,6 @@ BfTypedValue BfModule::GetThis() return BfTypedValue(); } -// if (useMethodState->HasNonStaticMixin()) -// { -// auto checkMethodState = useMethodState; -// while (checkMethodState != NULL) -// { -// for (int localIdx = (int)checkMethodState->mLocals.size() - 1; localIdx >= 0; localIdx--) -// { -// auto varDecl = checkMethodState->mLocals[localIdx]; -// if (varDecl->mName == "this") -// { -// varDecl->mReadFromId = useMethodState->GetRootMethodState()->mCurAccessId++; -// if (varDecl->mIsSplat) -// { -// return BfTypedValue(varDecl->mValue, varDecl->mResolvedType, BfTypedValueKind_ThisSplatHead); -// } -// else if ((varDecl->mResolvedType->IsValueType()) && (varDecl->mAddr)) -// { -// return BfTypedValue(varDecl->mAddr, varDecl->mResolvedType, BfTypedValueKind_ThisAddr); -// } -// return BfTypedValue(varDecl->mValue, varDecl->mResolvedType, varDecl->mResolvedType->IsValueType() ? BfTypedValueKind_ThisAddr : BfTypedValueKind_ThisValue); -// } -// } -// -// checkMethodState = checkMethodState->mPrevMethodState; -// } -// } - // Check mixin state for 'this' { auto checkMethodState = mCurMethodState; @@ -14059,8 +14154,10 @@ void BfModule::DoLocalVariableDebugInfo(BfLocalVariable* localVarDef, bool doAli if (mBfIRBuilder->HasDebugLocation()) { if ((isConstant) && (!didConstToMem)) - { - localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(localVarDef->mConstValue, diVariable); + { + BfTypedValue result(localVarDef->mConstValue, localVarDef->mResolvedType); + FixValueActualization(result); + localVarDef->mDbgDeclareInst = mBfIRBuilder->DbgInsertValueIntrinsic(result.mValue, diVariable); } else { @@ -15668,7 +15765,11 @@ void BfModule::EmitDtorBody() } else { - if (!mCurTypeInstance->IsValueType()) + if (fieldInst->mResolvedType->IsValuelessType()) + { + value = mBfIRBuilder->GetFakeVal(); + } + else if (!mCurTypeInstance->IsValueType()) { auto thisValue = GetThis(); value = mBfIRBuilder->CreateInBoundsGEP(thisValue.mValue, 0, fieldInst->mDataIdx); @@ -15744,13 +15845,7 @@ void BfModule::EmitDtorBody() UpdateSrcPos(typeDef->mTypeDeclaration->mNameNode); } - checkBaseType->mTypeDef->PopulateMemberSets(); - BfMemberSetEntry* entry = NULL; - BfMethodDef* dtorMethodDef = NULL; - checkBaseType->mTypeDef->mMethodSet.TryGetWith(String("~this"), &entry); - if (entry != NULL) - dtorMethodDef = (BfMethodDef*)entry->mMemberDef; - + BfMethodDef* dtorMethodDef = checkBaseType->mTypeDef->GetMethodByName("~this"); if (dtorMethodDef != NULL) { auto dtorMethodInstance = GetMethodInstance(checkBaseType, dtorMethodDef, BfTypeVector()); @@ -18160,7 +18255,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) auto methodDeclaration = methodDef->GetMethodDeclaration(); if ((methodDef->mHasComptime) && (!mIsComptimeModule)) - mBfIRBuilder->mIgnoreWrites = true; + mBfIRBuilder->mIgnoreWrites = true; if ((methodInstance->mIsReified) && (methodInstance->mVirtualTableIdx != -1)) { @@ -18285,7 +18380,36 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } BfLogSysM("ProcessMethod %p Unspecialized: %d Module: %p IRFunction: %d Reified: %d Incomplete:%d\n", methodInstance, mCurTypeInstance->IsUnspecializedType(), this, methodInstance->mIRFunction.mId, methodInstance->mIsReified, mIncompleteMethodCount); - + + int importStrNum = -1; + auto importKind = methodInstance->GetImportKind(); + if ((!mCompiler->mIsResolveOnly) && + ((importKind == BfImportKind_Import_Static) || (importKind == BfImportKind_Import_Dynamic))) + { + if (auto customAttr = methodInstance->GetCustomAttributes()->Get(mCompiler->mImportAttributeTypeDef)) + { + if (customAttr->mCtorArgs.size() == 1) + { + auto fileNameArg = customAttr->mCtorArgs[0]; + auto constant = mCurTypeInstance->mConstHolder->GetConstant(fileNameArg); + if (constant != NULL) + { + if (!constant->IsNull()) + importStrNum = constant->mInt32; + } + else + { + importStrNum = GetStringPoolIdx(fileNameArg, mCurTypeInstance->mConstHolder); + } + if (importStrNum != -1) + { + if (!mStringPoolRefs.Contains(importStrNum)) + mStringPoolRefs.Add(importStrNum); + } + } + } + } + if (methodInstance->GetImportCallKind() != BfImportCallKind_None) { if (mBfIRBuilder->mIgnoreWrites) @@ -19451,7 +19575,11 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } auto bodyBlock = BfNodeDynCast(methodDef->mBody); - if (methodDef->mBody == NULL) + if (!mCompiler->mHasRequiredTypes) + { + // Skip processing to avoid errors + } + else if (methodDef->mBody == NULL) { if (methodDeclaration != NULL) { @@ -19463,34 +19591,19 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) } bool isDllImport = false; - if (methodInstance->GetImportKind() == BfImportKind_Import_Static) + if ((importKind == BfImportKind_Import_Static) || (importKind == BfImportKind_Import_Dynamic)) { - for (auto customAttr : methodInstance->GetCustomAttributes()->mAttributes) - { - if (customAttr.mType->mTypeDef->mFullName.ToString() == "System.ImportAttribute") + if (importStrNum != -1) + { + if (importKind == BfImportKind_Import_Static) { - if (customAttr.mCtorArgs.size() == 1) + if (!mImportFileNames.Contains(importStrNum)) { - auto fileNameArg = customAttr.mCtorArgs[0]; - int strNum = 0; - auto constant = mCurTypeInstance->mConstHolder->GetConstant(fileNameArg); - if (constant != NULL) - { - if (constant->IsNull()) - continue; // Invalid - strNum = constant->mInt32; - } - else - { - strNum = GetStringPoolIdx(fileNameArg, mCurTypeInstance->mConstHolder); - } - if (!mImportFileNames.Contains(strNum)) - mImportFileNames.Add(strNum); + mImportFileNames.Add(importStrNum); } } + } - - //mImportFileNames } else if (methodInstance->GetImportKind() == BfImportKind_Import_Dynamic) { @@ -21534,6 +21647,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { BfTypeInstance* unspecializedTypeInstance = NULL; + Array deferredResolveTypes; for (int genericParamIdx = 0; genericParamIdx < (int)methodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++) { auto genericParam = methodInstance->mMethodInfoEx->mGenericParams[genericParamIdx]; @@ -21557,8 +21671,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool else genericParam->mExternType = GetPrimitiveType(BfTypeCode_Var); } - - ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized); + + ResolveGenericParamConstraints(genericParam, methodInstance->mIsUnspecialized, &deferredResolveTypes); if (genericParamIdx < (int)methodDef->mGenericParams.size()) { @@ -21572,6 +21686,8 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool } } } + for (auto typeRef : deferredResolveTypes) + auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None); for (auto genericParam : methodInstance->mMethodInfoEx->mGenericParams) { @@ -21920,6 +22036,12 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool } else { + BfTypeState typeState; + typeState.mTypeInstance = mCurTypeInstance; + typeState.mCurTypeDef = methodDef->mDeclaringType; + //typeState.mCurMethodDef = methodDef; + SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); + BfConstResolver constResolver(this); defaultValue = constResolver.Resolve(paramDef->mParamDeclaration->mInitializer, resolvedParamType, (BfConstResolveFlags)(BfConstResolveFlag_NoCast | BfConstResolveFlag_AllowGlobalVariable)); if ((defaultValue) && (defaultValue.mType != resolvedParamType)) @@ -22051,7 +22173,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool resolvedParamType = CreateArrayType(mContext->mBfObjectType, 1); } - if (addParams) + if ((addParams) && (resolvedParamType != NULL)) { BfMethodParam methodParam; methodParam.mResolvedType = resolvedParamType; @@ -22692,6 +22814,11 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool } } + if ((methodDef->mIsConcrete) && (!methodInstance->mIsForeignMethodDef) && (!mCurTypeInstance->IsInterface())) + { + Fail("Only interfaces methods can be declared as 'concrete'", methodDeclaration->mVirtualSpecifier); + } + if ((methodDef->mIsVirtual) && (methodDef->mIsStatic) && (!methodInstance->mIsInnerOverride)) { if ((virtualToken != NULL) && (virtualToken->mToken == BfToken_Override) && (methodDef->mDeclaringType->mTypeCode == BfTypeCode_Extension)) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index fedc977d..ed3dcf89 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1435,6 +1435,7 @@ public: Dictionary mStringObjectPool; Dictionary mStringCharPtrPool; Array mStringPoolRefs; + HashSet mUnreifiedStringPoolRefs; Array mPrevIRBuilders; // Before extensions BfIRBuilder* mBfIRBuilder; @@ -1538,12 +1539,12 @@ public: BfIRValue CreateStringCharPtr(const StringImpl& str, int stringId, bool define); int GetStringPoolIdx(BfIRValue constantStr, BfIRConstHolder* constHolder = NULL); String* GetStringPoolString(BfIRValue constantStr, BfIRConstHolder* constHolder = NULL); - BfIRValue GetStringCharPtr(int stringId); - BfIRValue GetStringCharPtr(BfIRValue strValue); - BfIRValue GetStringCharPtr(const StringImpl& str); - BfIRValue GetStringObjectValue(int idx); - BfIRValue GetStringObjectValue(const StringImpl& str, bool define = false); - BfIRValue CreateGlobalConstValue(const StringImpl& name, BfIRValue constant, BfIRType type, bool external); + BfIRValue GetStringCharPtr(int stringId, bool force = false); + BfIRValue GetStringCharPtr(BfIRValue strValue, bool force = false); + BfIRValue GetStringCharPtr(const StringImpl& str, bool force = false); + BfIRValue GetStringObjectValue(int idx, bool define, bool force); + BfIRValue GetStringObjectValue(const StringImpl& str, bool define = false, bool force = false); + BfIRValue CreateGlobalConstValue(const StringImpl& name, BfIRValue constant, BfIRType type, bool external); void VariantToString(StringImpl& str, const BfVariant& variant); StringT<128> TypeToString(BfType* resolvedType, Array* genericMethodParamNameOverrides = NULL); StringT<128> TypeToString(BfType* resolvedType, BfTypeNameFlags typeNameFlags, Array* genericMethodParamNameOverrides = NULL); @@ -1553,8 +1554,9 @@ public: void pm(BfMethodInstance* type); void CurrentAddToConstHolder(BfIRValue& irVal); void ClearConstData(); - BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType); - BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowStringId = false); + bool HasUnactializedConstant(BfConstant* constant, BfIRConstHolder* constHolder); + BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType); + BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowUnactualized = false); void ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget); void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL); BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL); @@ -1771,12 +1773,12 @@ public: BfMethodRefType* CreateMethodRefType(BfMethodInstance* methodInstance, bool mustAlreadyExist = false); BfType* FixIntUnknown(BfType* type); void FixIntUnknown(BfTypedValue& typedVal, BfType* matchType = NULL); - void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs); - void FixValueActualization(BfTypedValue& typedVal); + void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs); + void FixValueActualization(BfTypedValue& typedVal, bool force = false); bool TypeEquals(BfTypedValue& val, BfType* type); BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef, BfType** outType = NULL, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); - void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized); + void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized, Array* deferredResolveTypes = NULL); String GenericParamSourceToString(const BfGenericParamSource& genericParamSource); bool CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs = NULL, BfError** errorOut = NULL); BfIRValue AllocLocalVariable(BfType* type, const StringImpl& name, bool doLifetimeEnd = true); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 8913af24..78f1c52a 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -164,7 +164,8 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef) typeState.mResolveKind = BfTypeState::ResolveKind_BuildingGenericParams; typeState.mTypeInstance = resolvedTypeRef->ToTypeInstance(); SetAndRestoreValue prevTypeState(mContext->mCurTypeState, &typeState); - + Array deferredResolveTypes; + BF_ASSERT(mCurMethodInstance == NULL); auto genericTypeInst = resolvedTypeRef->ToGenericTypeInstance(); @@ -210,7 +211,7 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef) genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var); } - ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType()); + ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType(), &deferredResolveTypes); if (genericParamDef != NULL) { @@ -283,7 +284,7 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef) genericParamInstance->mExternType = GetPrimitiveType(BfTypeCode_Var); } - ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType()); + ResolveGenericParamConstraints(genericParamInstance, genericTypeInst->IsUnspecializedType(), &deferredResolveTypes); auto genericParamDef = genericParamInstance->GetGenericParamDef(); if (genericParamDef != NULL) { @@ -295,6 +296,9 @@ bool BfModule::FinishGenericParams(BfType* resolvedTypeRef) } } + for (auto typeRef : deferredResolveTypes) + auto constraintType = ResolveTypeRef(typeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_None); + for (auto genericParam : genericTypeInst->mGenericTypeInfo->mGenericParams) { for (auto constraintTypeInst : genericParam->mInterfaceConstraints) @@ -339,6 +343,13 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan return true; } + for (auto typeArg : genericTypeInst->mGenericTypeInfo->mTypeGenericArguments) + { + auto genericArg = typeArg->ToGenericTypeInstance(); + if (genericArg != NULL) + genericTypeInst->mGenericTypeInfo->mMaxGenericDepth = BF_MAX(genericTypeInst->mGenericTypeInfo->mMaxGenericDepth, genericArg->mGenericTypeInfo->mMaxGenericDepth + 1); + } + auto typeDef = genericTypeInst->mTypeDef; for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++) { @@ -1029,7 +1040,21 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType typeModule->mIsReified = true; typeModule->mWantsIRIgnoreWrites = false; for (auto ownedTypes : typeModule->mOwnedTypeInstances) + { ownedTypes->mIsReified = true; + + if (ownedTypes->mCustomAttributes != NULL) + { + for (auto& attr : ownedTypes->mCustomAttributes->mAttributes) + { + if ((attr.mType->mAttributeData != NULL) && ((attr.mType->mAttributeData->mFlags & BfCustomAttributeFlags_ReflectAttribute) != 0)) + { + // Reify this attribute + typeModule->PopulateType(attr.mType); + } + } + } + } mCompiler->mStats.mReifiedModuleCount++; if (typeModule->mBfIRBuilder != NULL) { @@ -1038,7 +1063,7 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType typeModule->SetupIRBuilder(false); } else - typeModule->PrepareForIRWriting(resolvedTypeRef->ToTypeInstance()); + typeModule->PrepareForIRWriting(resolvedTypeRef->ToTypeInstance()); } else { @@ -2002,7 +2027,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* for (auto& customAttribute : customAttributes->mAttributes) { auto attrType = customAttribute.mType; - PopulateType(attrType, BfPopulateType_DataAndMethods); + mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods); if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) continue; @@ -2331,7 +2356,7 @@ void BfModule::DoCEEmit(BfMethodInstance* methodInstance) for (auto& customAttribute : customAttributes->mAttributes) { auto attrType = customAttribute.mType; - PopulateType(attrType, BfPopulateType_DataAndMethods); + mContext->mUnreifiedModule->PopulateType(attrType, BfPopulateType_DataAndMethods); if (attrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted) continue; @@ -2599,8 +2624,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy SetAndRestoreValue prevTypeInstance(mCurTypeInstance, typeInstance); SetAndRestoreValue prevMethodInstance(mCurMethodInstance, NULL); SetAndRestoreValue prevMethodState(mCurMethodState, NULL); - SetAndRestoreValue prevHadError(mHadBuildError, false); - SetAndRestoreValue prevHadWarning(mHadBuildWarning, false); + + // WHY were we clearing these values? + //SetAndRestoreValue prevHadError(mHadBuildError, false); + //SetAndRestoreValue prevHadWarning(mHadBuildWarning, false); BfTypeState typeState(mCurTypeInstance, mContext->mCurTypeState); typeState.mPopulateType = populateType; @@ -2640,8 +2667,8 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (typeInstance->mIsFinishingType) { - // This type already failed - return; + if (typeInstance->mTypeFailed) + return; } if (!typeInstance->mTypeFailed) @@ -3006,7 +3033,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy bool populateBase = !typeInstance->mTypeFailed; auto checkType = ResolveTypeRef(checkTypeRef, BfPopulateType_Declaration); if ((checkType != NULL) && (!checkType->IsInterface()) && (populateBase)) + { + SetAndRestoreValue prevBaseType(mContext->mCurTypeState->mCurBaseType, checkType->ToTypeInstance()); PopulateType(checkType, BfPopulateType_Data); + } if (typeInstance->mDefineState >= BfTypeDefineState_Defined) { @@ -3387,6 +3417,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy for (auto& validateEntry : deferredTypeValidateList) { + SetAndRestoreValue prevAttributeTypeRef(typeState.mCurAttributeTypeRef, validateEntry.mTypeRef); SetAndRestoreValue ignoreErrors(mIgnoreErrors, mIgnoreErrors | validateEntry.mIgnoreErrors); ValidateGenericConstraints(validateEntry.mTypeRef, validateEntry.mGenericType, false); } @@ -3742,7 +3773,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (populateChildType) { - BF_ASSERT(!resolvedFieldType->IsDataIncomplete()); + if (resolvedFieldType->IsFinishingType()) + { + AssertErrorState(); + } + else + BF_ASSERT(!resolvedFieldType->IsDataIncomplete()); } else { @@ -4319,34 +4355,41 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if ((mCompiler->mOptions.mAllowHotSwapping) && (typeInstance->mDefineState < BfTypeDefineState_Defined)) { - auto hotTypeVersion = typeInstance->mHotTypeData->mTypeVersions.back(); - - if ((typeInstance->mBaseType != NULL) && (typeInstance->mBaseType->mHotTypeData != NULL)) + if (typeInstance->mHotTypeData == NULL) { - hotTypeVersion->mMembers.Add(typeInstance->mBaseType->mHotTypeData->GetLatestVersion()); + BF_ASSERT(typeInstance->mTypeFailed); } - - for (auto& fieldInst : typeInstance->mFieldInstances) + else { - auto fieldDef = fieldInst.GetFieldDef(); - if ((fieldDef == NULL) || (fieldDef->mIsStatic)) - continue; - auto depType = fieldInst.mResolvedType; + auto hotTypeVersion = typeInstance->mHotTypeData->mTypeVersions.back(); - while (depType->IsSizedArray()) - depType = ((BfSizedArrayType*)depType)->mElementType; - if (depType->IsStruct()) + if ((typeInstance->mBaseType != NULL) && (typeInstance->mBaseType->mHotTypeData != NULL)) { - PopulateType(depType); - auto depTypeInst = depType->ToTypeInstance(); - BF_ASSERT(depTypeInst->mHotTypeData != NULL); - if (depTypeInst->mHotTypeData != NULL) - hotTypeVersion->mMembers.Add(depTypeInst->mHotTypeData->GetLatestVersion()); + hotTypeVersion->mMembers.Add(typeInstance->mBaseType->mHotTypeData->GetLatestVersion()); } - } - for (auto member : hotTypeVersion->mMembers) - member->mRefCount++; + for (auto& fieldInst : typeInstance->mFieldInstances) + { + auto fieldDef = fieldInst.GetFieldDef(); + if ((fieldDef == NULL) || (fieldDef->mIsStatic)) + continue; + auto depType = fieldInst.mResolvedType; + + while (depType->IsSizedArray()) + depType = ((BfSizedArrayType*)depType)->mElementType; + if (depType->IsStruct()) + { + PopulateType(depType); + auto depTypeInst = depType->ToTypeInstance(); + BF_ASSERT(depTypeInst->mHotTypeData != NULL); + if (depTypeInst->mHotTypeData != NULL) + hotTypeVersion->mMembers.Add(depTypeInst->mHotTypeData->GetLatestVersion()); + } + } + + for (auto member : hotTypeVersion->mMembers) + member->mRefCount++; + } } if (typeInstance->mDefineState < BfTypeDefineState_Defined) @@ -4962,7 +5005,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) // { - if (typeInstance->IsSpecializedType()) + if ((typeInstance->IsSpecializedType()) || (typeInstance->IsUnspecializedTypeVariation())) wantsOnDemandMethods = true; else if ((mCompiler->mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!typeInstance->IsUnspecializedTypeVariation())) @@ -6000,11 +6043,14 @@ BfArrayType* BfModule::CreateArrayType(BfType* resolvedType, int dimensions) BF_ASSERT(!resolvedType->IsVar()); BF_ASSERT(!resolvedType->IsIntUnknown()); + auto arrayTypeDef = mCompiler->GetArrayTypeDef(dimensions); + if (arrayTypeDef == NULL) + return NULL; auto arrayType = mContext->mArrayTypePool.Get(); delete arrayType->mGenericTypeInfo; arrayType->mGenericTypeInfo = new BfGenericTypeInfo(); arrayType->mContext = mContext; - arrayType->mTypeDef = mCompiler->GetArrayTypeDef(dimensions); + arrayType->mTypeDef = arrayTypeDef; arrayType->mDimensions = dimensions; arrayType->mGenericTypeInfo->mTypeGenericArguments.clear(); arrayType->mGenericTypeInfo->mTypeGenericArguments.push_back(resolvedType); @@ -6450,19 +6496,16 @@ void BfModule::FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs) FixIntUnknown(rhs); } -void BfModule::FixValueActualization(BfTypedValue& typedVal) +void BfModule::FixValueActualization(BfTypedValue& typedVal, bool force) { if (!typedVal.mValue.IsConst()) return; - if (mBfIRBuilder->mIgnoreWrites) + if ((mBfIRBuilder->mIgnoreWrites) && (!force)) return; auto constant = mBfIRBuilder->GetConstant(typedVal.mValue); - if (constant->mConstType == BfConstType_TypeOf) - { - auto constTypeOf = (BfTypeOf_Const*)constant; - AddDependency(constTypeOf->mType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference); - typedVal.mValue = CreateTypeDataRef(constTypeOf->mType); - } + if (!HasUnactializedConstant(constant, mBfIRBuilder)) + return; + typedVal.mValue = ConstantToCurrent(constant, mBfIRBuilder, typedVal.mType, false); } BfTypeInstance* BfModule::GetPrimitiveStructType(BfTypeCode typeCode) @@ -7928,7 +7971,7 @@ bool BfModule::ResolveTypeResult_Validate(BfTypeReference* typeRef, BfType* reso if ((curGenericTypeInstance->mDependencyMap.mMinDependDepth > 32) && (genericTypeInstance->mDependencyMap.mMinDependDepth > 32)) { - Fail(StrFormat("Generic type dependency depth exceeded for type '{}'", TypeToString(genericTypeInstance).c_str()), typeRef); + Fail(StrFormat("Generic type dependency depth exceeded for type '%s'", TypeToString(genericTypeInstance).c_str()), typeRef); return false; } @@ -9714,7 +9757,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula CheckUnspecializedGenericType(genericTypeInst, populateType); resolvedEntry->mValue = genericTypeInst; populateModule->InitType(genericTypeInst, populateType); - BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash); +#ifdef _DEBUG + if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash) + { + int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx); + int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx); + BF_ASSERT(refHash == typeHash); + } +#endif return ResolveTypeResult(typeRef, genericTypeInst, populateType, resolveFlags); } } @@ -9731,6 +9781,11 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } typeInst->mTypeDef = typeDef; + if (((resolveFlags & BfResolveTypeRefFlag_NoReify) != 0) && (mCompiler->mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude)) + { + typeInst->mIsReified = false; + } + if (typeInst->mTypeDef->mGenericParamDefs.size() != 0) { Fail("Generic type arguments expected", typeRef); @@ -9767,12 +9822,13 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } auto elementType = ResolveTypeRef(arrayTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue); - if (elementType == NULL) + auto arrayTypeDef = mCompiler->GetArrayTypeDef(arrayTypeRef->mDimensions); + if ((elementType == NULL) || (arrayTypeDef == NULL)) { mContext->mResolvedTypes.RemoveEntry(resolvedEntry); return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); } - + if ((arrayTypeRef->mDimensions == 1) && (arrayTypeRef->mParams.size() == 1)) { intptr elementCount = -1; @@ -9840,7 +9896,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula arrayType->mGenericTypeInfo = new BfGenericTypeInfo(); arrayType->mContext = mContext; arrayType->mDimensions = arrayTypeRef->mDimensions; - arrayType->mTypeDef = mCompiler->GetArrayTypeDef(arrayType->mDimensions); + arrayType->mTypeDef = arrayTypeDef; arrayType->mGenericTypeInfo->mTypeGenericArguments.push_back(elementType); resolvedEntry->mValue = arrayType; @@ -9962,15 +10018,16 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula auto parentTypeInstance = outerTypeInstance; if (parentTypeInstance->IsTypeAlias()) parentTypeInstance = (BfTypeInstance*)GetOuterType(parentTypeInstance)->ToTypeInstance(); + genericTypeInst->mGenericTypeInfo->mMaxGenericDepth = BF_MAX(genericTypeInst->mGenericTypeInfo->mMaxGenericDepth, parentTypeInstance->mGenericTypeInfo->mMaxGenericDepth); for (int i = 0; i < startDefGenericParamIdx; i++) { genericTypeInst->mGenericTypeInfo->mGenericParams.push_back(parentTypeInstance->mGenericTypeInfo->mGenericParams[i]->AddRef()); genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.push_back(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i]); auto typeGenericArg = genericTypeInst->mGenericTypeInfo->mTypeGenericArguments[i]; genericTypeInst->mGenericTypeInfo->mIsUnspecialized |= typeGenericArg->IsGenericParam() || typeGenericArg->IsUnspecializedType(); + } - } - + } int wantedGenericParams = genericParamCount - startDefGenericParamIdx; int genericArgDiffCount = (int)genericArguments.size() - wantedGenericParams; @@ -9989,14 +10046,28 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula for (auto genericArgRef : genericArguments) { auto genericArg = genericArgs[genericParamIdx + startDefGenericParamIdx]; + + if (auto genericGenericArg = genericArg->ToGenericTypeInstance()) + { + genericTypeInst->mGenericTypeInfo->mMaxGenericDepth = BF_MAX(genericTypeInst->mGenericTypeInfo->mMaxGenericDepth, genericGenericArg->mGenericTypeInfo->mMaxGenericDepth + 1); + } + genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.push_back(genericArg); genericTypeInst->mGenericTypeInfo->mTypeGenericArgumentRefs.push_back(genericArgRef); genericParamIdx++; } - resolvedEntry->mValue = genericTypeInst; + if (genericTypeInst->mGenericTypeInfo->mMaxGenericDepth > 64) + { + Fail("Maximum generic depth exceeded", typeRef); + delete genericTypeInst; + mContext->mResolvedTypes.RemoveEntry(resolvedEntry); + return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); + } + resolvedEntry->mValue = genericTypeInst; + CheckUnspecializedGenericType(genericTypeInst, populateType); populateModule->InitType(genericTypeInst, populateType); @@ -10011,6 +10082,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula { BF_ASSERT(BfResolvedTypeSet::Equals(genericTypeInst, typeRef, &lookupCtx)); } + + BfLogSysM("Generic type %p typeHash: %8X\n", genericTypeInst, resolvedEntry->mHash); #endif BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash); @@ -10145,7 +10218,14 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula CheckUnspecializedGenericType(genericTypeInst, populateType); resolvedEntry->mValue = genericTypeInst; - BF_ASSERT(BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) == resolvedEntry->mHash); +#ifdef _DEBUG + if (BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx) != resolvedEntry->mHash) + { + int refHash = BfResolvedTypeSet::Hash(typeRef, &lookupCtx); + int typeHash = BfResolvedTypeSet::Hash(genericTypeInst, &lookupCtx); + BF_ASSERT(refHash == typeHash); + } +#endif populateModule->InitType(genericTypeInst, populateType); return ResolveTypeResult(typeRef, genericTypeInst, populateType, resolveFlags); } @@ -10281,7 +10361,11 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula if ((mCurTypeInstance == NULL) || (!mCurTypeInstance->IsGenericTypeInstance())) wantGeneric = false; - auto baseDelegateType = ResolveTypeDef(mCompiler->mDelegateTypeDef)->ToTypeInstance(); + BfTypeInstance* baseDelegateType = NULL; + if (mCompiler->mDelegateTypeDef != NULL) + baseDelegateType = ResolveTypeDef(mCompiler->mDelegateTypeDef)->ToTypeInstance(); + else + failed = true; BfDelegateInfo* delegateInfo = NULL; BfTypeInstance* delegateType = NULL; @@ -10328,7 +10412,8 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula Val128 hashContext; BfTypeDef* typeDef = new BfTypeDef(); - typeDef->mProject = baseDelegateType->mTypeDef->mProject; + if (baseDelegateType != NULL) + typeDef->mProject = baseDelegateType->mTypeDef->mProject; typeDef->mSystem = mCompiler->mSystem; typeDef->mName = mSystem->mEmptyAtom; if (delegateTypeRef->mTypeToken->GetToken() == BfToken_Delegate) @@ -10360,9 +10445,12 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula delegateInfo->mDirectAllocNodes.push_back(directTypeRef); if (typeDef->mIsDelegate) directTypeRef->Init(delegateType); + else if (mCompiler->mFunctionTypeDef == NULL) + failed = true; else directTypeRef->Init(ResolveTypeDef(mCompiler->mFunctionTypeDef)); - typeDef->mBaseTypes.push_back(directTypeRef); + if (!failed) + typeDef->mBaseTypes.push_back(directTypeRef); directTypeRef = BfAstNode::ZeroedAlloc(); delegateInfo->mDirectAllocNodes.push_back(directTypeRef); @@ -11013,7 +11101,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp { SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true); auto constraintTypeInst = genericParamInst->mTypeConstraint->ToTypeInstance(); - if ((constraintTypeInst != NULL) && (constraintTypeInst->mTypeDef == mCompiler->mEnumTypeDef)) + if ((constraintTypeInst != NULL) && (constraintTypeInst->mTypeDef == mCompiler->mEnumTypeDef) && (explicitCast)) { // Enum->int if ((explicitCast) && (toType->IsInteger())) @@ -11052,7 +11140,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } } - if (toType->IsInteger()) + if ((toType->IsInteger()) && (explicitCast)) { if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) { @@ -12780,6 +12868,19 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeInstance* wantType if (srcType->mDefineState < BfTypeDefineState_HasInterfaces) { + if (srcType->mDefineState == BfTypeDefineState_ResolvingBaseType) + { + auto typeState = mContext->mCurTypeState; + while (typeState != NULL) + { + if ((typeState->mTypeInstance == srcType) && (typeState->mCurBaseType != NULL)) + { + return TypeIsSubTypeOf(typeState->mCurBaseType, wantType, checkAccessibility); + } + typeState = typeState->mPrevState; + } + } + // Type is incomplete. We don't do the IsIncomplete check here because of re-entry // While handling 'var' resolution, we don't want to force a PopulateType reentry // but we do have enough information for TypeIsSubTypeOf diff --git a/IDEHelper/Compiler/BfPrinter.cpp b/IDEHelper/Compiler/BfPrinter.cpp index 8faa4a8c..6e424020 100644 --- a/IDEHelper/Compiler/BfPrinter.cpp +++ b/IDEHelper/Compiler/BfPrinter.cpp @@ -374,6 +374,50 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node) { Visit((BfAstNode*)node); startIdx = node->mSrcStart; + + if (doWrap) + { + bool wantWrap = false; + + int spacedWordCount = 0; + bool inQuotes = false; + auto src = astNodeSrc->mSrc; + bool isDefinitelyCode = false; + bool hadNonSlash = false; + + for (int i = node->mSrcStart + 1; i < node->mSrcEnd - 1; i++) + { + char c = src[i]; + if (c != '/') + hadNonSlash = true; + if (inQuotes) + { + if (c == '\\') + { + i++; + } + else if (c == '\"') + { + inQuotes = false; + } + } + else if (c == '"') + { + inQuotes = true; + } + else if (c == ' ') + { + if ((isalpha((uint8)src[i - 1])) && (isalpha((uint8)src[i + 1]))) + spacedWordCount++; + } + else if ((c == '/') && (src[i - 1] == '/') && (hadNonSlash)) + isDefinitelyCode = true; + } + + // If this doesn't look like a sentence then don't try to word wrap + if ((isDefinitelyCode) || (spacedWordCount < 4)) + doWrap = false; + } } int lineEmittedChars = 0; @@ -1803,7 +1847,7 @@ void BfPrinter::Visit(BfDeferStatement* deferStmt) VisitChild(deferStmt->mDeferToken); VisitChild(deferStmt->mColonToken); - VisitChild(deferStmt->mScopeToken); + VisitChild(deferStmt->mScopeName); if (deferStmt->mBind != NULL) { diff --git a/IDEHelper/Compiler/BfReducer.cpp b/IDEHelper/Compiler/BfReducer.cpp index b00c8d54..64b05b01 100644 --- a/IDEHelper/Compiler/BfReducer.cpp +++ b/IDEHelper/Compiler/BfReducer.cpp @@ -3797,6 +3797,8 @@ BfAstNode* BfReducer::DoCreateStatement(BfAstNode* node, CreateStmtFlags createS } else if (nextTokenNode->GetToken() == BfToken_LParen) { + mPassInstance->Warn(0, "Syntax deprecated", nextTokenNode); + MEMBER_SET(deferStmt, mOpenParen, nextTokenNode); mVisitorPos.MoveNext(); @@ -9264,9 +9266,9 @@ bool BfReducer::ParseMethod(BfMethodDeclaration* methodDeclaration, SizedArrayIm bool isFunction = false; bool isDelegate = false; - if ((mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Function)) + if ((mCurTypeDecl != NULL) && (mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Function)) isFunction = true; - else if ((mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Delegate)) + else if ((mCurTypeDecl != NULL) && (mCurTypeDecl->mTypeNode != NULL) && (mCurTypeDecl->mTypeNode->GetToken() == BfToken_Delegate)) isDelegate = true; if ((!isFunction) && (!isDelegate)) diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index f95a36c7..b8253306 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -1686,7 +1686,7 @@ BfType* BfTypeInstance::GetUnionInnerType(bool* wantSplat) { SetAndRestoreValue prevTypeRef(mContext->mCurTypeState->mCurFieldDef, fieldDef); - mModule->PopulateType(checkInnerType); + mModule->PopulateType(checkInnerType, checkInnerType->IsValueType() ? BfPopulateType_Data : BfPopulateType_Declaration); if (checkInnerType->mSize > unionSize) unionSize = checkInnerType->mSize; @@ -2194,7 +2194,7 @@ bool BfTypeInstance::WantsGCMarking() return true; if ((IsEnum()) && (!IsPayloadEnum())) return false; - BF_ASSERT(mDefineState >= BfTypeDefineState_Defined); + BF_ASSERT((mDefineState >= BfTypeDefineState_Defined) || (mTypeFailed)); return mWantsGCMarking; } @@ -2674,7 +2674,7 @@ size_t BfTypeVectorHash::operator()(const BfTypeVector& typeVec) const size_t hash = typeVec.size(); BfResolvedTypeSet::LookupContext ctx; for (auto type : typeVec) - hash = ((hash ^ BfResolvedTypeSet::Hash(type, &ctx)) << 5) - hash; + hash = ((hash ^ BfResolvedTypeSet::Hash(type, &ctx, Beefy::BfResolvedTypeSet::BfHashFlag_None, 0)) << 5) - hash; return hash; } @@ -2721,6 +2721,8 @@ BfResolvedTypeSet::~BfResolvedTypeSet() } +#define HASH_MIX(origHashVal, newHashVal) ((((origHashVal) << 5) - (origHashVal)) ^ (newHashVal)) + #define HASH_VAL_PTR 1 #define HASH_VAL_BOXED 2 #define HASH_VAL_REF 3 @@ -2767,7 +2769,7 @@ BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* return variant; } -int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) +int BfResolvedTypeSet::DoHash(BfType* type, LookupContext* ctx, bool allowRef, int hashSeed) { //BP_ZONE("BfResolvedTypeSet::Hash"); @@ -2787,13 +2789,13 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) if (type->IsBoxed()) { BfBoxedType* boxedType = (BfBoxedType*)type; - int elemHash = Hash(boxedType->mElementType, ctx) ^ HASH_VAL_BOXED; + int elemHash = Hash(boxedType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ HASH_VAL_BOXED; return (elemHash << 5) - elemHash; } else if (type->IsArray()) { BfArrayType* arrayType = (BfArrayType*)type; - int elemHash = Hash(arrayType->mGenericTypeInfo->mTypeGenericArguments[0], ctx) ^ (arrayType->mDimensions << 8); + int elemHash = Hash(arrayType->mGenericTypeInfo->mTypeGenericArguments[0], ctx, BfHashFlag_None, hashSeed) ^ (arrayType->mDimensions << 8); return (elemHash << 5) - elemHash; } else if (type->IsDelegateFromTypeRef() || type->IsFunctionFromTypeRef()) @@ -2803,7 +2805,7 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) auto delegateInfo = type->GetDelegateInfo(); - hashVal = ((hashVal ^ (Hash(delegateInfo->mReturnType, ctx))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(delegateInfo->mReturnType, ctx, BfHashFlag_None, hashSeed))) << 5) - hashVal; auto methodDef = typeInst->mTypeDef->mMethods[0]; BF_ASSERT(methodDef->mName == "Invoke"); @@ -2817,7 +2819,7 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) for (int paramIdx = 0; paramIdx < delegateInfo->mParams.size(); paramIdx++) { // Parse attributes? - hashVal = ((hashVal ^ (Hash(delegateInfo->mParams[paramIdx], ctx))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(delegateInfo->mParams[paramIdx], ctx, BfHashFlag_None, hashSeed))) << 5) - hashVal; String paramName = methodDef->mParams[paramIdx]->mName; int nameHash = (int)Hash64(paramName.c_str(), (int)paramName.length()); hashVal = ((hashVal ^ (nameHash)) << 5) - hashVal; @@ -2852,7 +2854,7 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) BfFieldInstance* fieldInstance = &tupleType->mFieldInstances[fieldIdx]; auto fieldType = fieldInstance->mResolvedType; - hashVal = ((hashVal ^ (Hash(fieldType, ctx))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(fieldType, ctx, BfHashFlag_None, hashSeed))) << 5) - hashVal; BfFieldDef* fieldDef = NULL; if (tupleType->mTypeDef != NULL) fieldDef = fieldInstance->GetFieldDef(); @@ -2873,8 +2875,8 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) else if (type->IsGenericTypeInstance()) { BfTypeInstance* genericType = (BfTypeInstance*)type; - for (auto genericArg : genericType->mGenericTypeInfo->mTypeGenericArguments) - hashVal = ((hashVal ^ (Hash(genericArg, ctx))) << 5) - hashVal; + for (auto genericArg : genericType->mGenericTypeInfo->mTypeGenericArguments) + hashVal = HASH_MIX(hashVal, Hash(genericArg, ctx, BfHashFlag_None, hashSeed + 1)); } return hashVal; } @@ -2886,7 +2888,7 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) else if (type->IsPointer()) { BfPointerType* pointerType = (BfPointerType*) type; - int elemHash = Hash(pointerType->mElementType, ctx) ^ HASH_VAL_PTR; + int elemHash = Hash(pointerType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ HASH_VAL_PTR; return (elemHash << 5) - elemHash; } else if (type->IsGenericParam()) @@ -2897,30 +2899,30 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) else if (type->IsRef()) { auto refType = (BfRefType*)type; - int elemHash = Hash(refType->mElementType, ctx) ^ (HASH_VAL_REF + (int)refType->mRefKind); + int elemHash = Hash(refType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ (HASH_VAL_REF + (int)refType->mRefKind); return (elemHash << 5) - elemHash; } else if (type->IsModifiedTypeType()) { auto modifiedTypeType = (BfModifiedTypeType*)type; - int elemHash = Hash(modifiedTypeType->mElementType, ctx) ^ HASH_MODTYPE + (int)modifiedTypeType->mModifiedKind; + int elemHash = Hash(modifiedTypeType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ HASH_MODTYPE + (int)modifiedTypeType->mModifiedKind; return (elemHash << 5) - elemHash; } else if (type->IsConcreteInterfaceType()) { auto concreteInterfaceType = (BfConcreteInterfaceType*)type; - int elemHash = Hash(concreteInterfaceType->mInterface, ctx) ^ HASH_CONCRETE_INTERFACE; + int elemHash = Hash(concreteInterfaceType->mInterface, ctx, BfHashFlag_None, hashSeed) ^ HASH_CONCRETE_INTERFACE; return (elemHash << 5) - elemHash; } else if (type->IsSizedArray()) { auto sizedArray = (BfSizedArrayType*)type; - int elemHash = Hash(sizedArray->mElementType, ctx) ^ HASH_SIZED_ARRAY; + int elemHash = Hash(sizedArray->mElementType, ctx, BfHashFlag_None, hashSeed) ^ HASH_SIZED_ARRAY; int hashVal = (elemHash << 5) - elemHash; if (type->IsUnknownSizedArrayType()) { auto unknownSizedArray = (BfUnknownSizedArrayType*)type; - int elemHash = Hash(unknownSizedArray->mElementCountSource, ctx); + int elemHash = Hash(unknownSizedArray->mElementCountSource, ctx, BfHashFlag_None, hashSeed); hashVal = ((hashVal ^ elemHash) << 5) - hashVal; } else @@ -2940,7 +2942,7 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) { BfConstExprValueType* constExprValueType = (BfConstExprValueType*)type; int hashVal = ((int)constExprValueType->mValue.mTypeCode << 17) ^ (constExprValueType->mValue.mInt32 << 3) ^ HASH_CONSTTYPE; - hashVal = ((hashVal ^ (Hash(constExprValueType->mType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(constExprValueType->mType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal; return hashVal; } else @@ -2950,21 +2952,29 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) return 0; } -void BfResolvedTypeSet::HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hashVal) +int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef, int hashSeed) +{ + int hashVal = DoHash(type, ctx, allowRef, hashSeed); + if (hashSeed == 0) + return hashVal; + return HASH_MIX(hashVal, hashSeed); +} + +void BfResolvedTypeSet::HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hashVal, int hashSeed) { if (auto elementedTypeRef = BfNodeDynCast(typeRef)) { - HashGenericArguments(elementedTypeRef->mElementType, ctx, hashVal); + HashGenericArguments(elementedTypeRef->mElementType, ctx, hashVal, hashSeed); } else if (auto qualifiedTypeRef = BfNodeDynCast(typeRef)) { - HashGenericArguments(qualifiedTypeRef->mLeft, ctx, hashVal); + HashGenericArguments(qualifiedTypeRef->mLeft, ctx, hashVal, hashSeed); } if (auto genericTypeRef = BfNodeDynCast(typeRef)) { for (auto genericArg : genericTypeRef->mGenericArguments) - hashVal = ((hashVal ^ (Hash(genericArg, ctx, BfHashFlag_AllowGenericParamConstValue))) << 5) - hashVal; + hashVal = HASH_MIX(hashVal, Hash(genericArg, ctx, BfHashFlag_AllowGenericParamConstValue, hashSeed + 1)); } } @@ -2976,7 +2986,7 @@ static int HashNode(BfAstNode* node) return (int)Hash64(nameStr, node->GetSrcLength()); } -int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags) +int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int hashSeed) { bool isHeadType = typeRef == ctx->mRootTypeRef; @@ -2990,7 +3000,7 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx, ctx->mFailed = true; return 0; } - return Hash(resolvedType, ctx); + return Hash(resolvedType, ctx, BfHashFlag_None, hashSeed); } BfTypeDef* BfResolvedTypeSet::FindRootCommonOuterType(BfTypeDef* outerType, LookupContext* ctx, BfTypeInstance*& outOuterTypeInstance) @@ -3020,7 +3030,7 @@ BfTypeDef* BfResolvedTypeSet::FindRootCommonOuterType(BfTypeDef* outerType, Look return commonOuterType; } -int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags) +int BfResolvedTypeSet::DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int& hashSeed) { if ((typeRef == ctx->mRootTypeRef) && (ctx->mRootTypeDef != NULL) && ((typeRef->IsNamedTypeReference()) || (BfNodeIsA(typeRef)))) @@ -3072,8 +3082,8 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash auto curGenericTypeInst = (BfTypeInstance*)checkTypeInstance; int numParentGenericParams = (int)commonOuterType->mGenericParamDefs.size(); for (int i = 0; i < numParentGenericParams; i++) - { - hashVal = ((hashVal ^ (Hash(curGenericTypeInst->mGenericTypeInfo->mTypeGenericArguments[i], ctx))) << 5) - hashVal; + { + hashVal = HASH_MIX(hashVal, Hash(curGenericTypeInst->mGenericTypeInfo->mTypeGenericArguments[i], ctx, BfHashFlag_None, hashSeed + 1)); } } @@ -3082,7 +3092,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash if (typeRef->IsNamedTypeReference()) { - return DirectHash(typeRef, ctx, flags); + int hashVal = DirectHash(typeRef, ctx, flags, hashSeed); + hashSeed = 0; + return hashVal; } if (auto genericInstTypeRef = BfNodeDynCastExact(typeRef)) { @@ -3124,7 +3136,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash ctx->mFailed = true; return 0; } - return Hash(underlyingType, ctx, flags); + int hashVal = Hash(underlyingType, ctx, flags, hashSeed); + hashSeed = 0; + return hashVal; } } } @@ -3155,23 +3169,23 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash { auto parentTypeInstance = checkTypeInstance; int numParentGenericParams = (int)commonOuterType->mGenericParamDefs.size(); - for (int i = 0; i < numParentGenericParams; i++) - hashVal = ((hashVal ^ (Hash(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i], ctx))) << 5) - hashVal; + for (int i = 0; i < numParentGenericParams; i++) + hashVal = HASH_MIX(hashVal, Hash(parentTypeInstance->mGenericTypeInfo->mTypeGenericArguments[i], ctx, Beefy::BfResolvedTypeSet::BfHashFlag_None, hashSeed + 1)); } } - HashGenericArguments(genericInstTypeRef, ctx, hashVal); + HashGenericArguments(genericInstTypeRef, ctx, hashVal, hashSeed); return hashVal; } else if (auto tupleTypeRef = BfNodeDynCastExact(typeRef)) - { + { int hashVal = HASH_VAL_TUPLE; for (int fieldIdx = 0; fieldIdx < (int)tupleTypeRef->mFieldTypes.size(); fieldIdx++) { BfTypeReference* fieldType = tupleTypeRef->mFieldTypes[fieldIdx]; - hashVal = ((hashVal ^ (Hash(fieldType, ctx))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(fieldType, ctx, BfHashFlag_None, hashSeed))) << 5) - hashVal; int nameHash = 0; BfIdentifierNode* fieldName = NULL; @@ -3197,7 +3211,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash { if ((arrayType->mDimensions == 1) && (arrayType->mParams.size() != 0)) { - int rawElemHash = Hash(arrayType->mElementType, ctx); + int rawElemHash = Hash(arrayType->mElementType, ctx, BfHashFlag_None, hashSeed); int elemHash = rawElemHash ^ HASH_SIZED_ARRAY; int hashVal = (elemHash << 5) - elemHash; @@ -3221,7 +3235,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash BfTypedValue typedVal = constResolver.Resolve(sizeExpr, NULL, BfConstResolveFlag_ArrayInitSize); if (typedVal.mKind == BfTypedValueKind_GenericConstValue) { - int elemHash = Hash(typedVal.mType, ctx); + int elemHash = Hash(typedVal.mType, ctx, BfHashFlag_None, hashSeed); hashVal = ((hashVal ^ elemHash) << 5) - hashVal; return hashVal; } @@ -3280,13 +3294,13 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } } - int elemHash = Hash(arrayType->mElementType, ctx) ^ (arrayType->mDimensions << 8); + int elemHash = Hash(arrayType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ (arrayType->mDimensions << 8); return (elemHash << 5) - elemHash; } } else if (auto pointerType = BfNodeDynCastExact(typeRef)) { - int elemHash = Hash(pointerType->mElementType, ctx) ^ HASH_VAL_PTR; + int elemHash = Hash(pointerType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ HASH_VAL_PTR; return (elemHash << 5) - elemHash; } else if (auto nullableType = BfNodeDynCastExact(typeRef)) @@ -3294,8 +3308,8 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash if (ctx->mRootTypeRef == typeRef) ctx->mRootTypeDef = ctx->mModule->mCompiler->mNullableTypeDef; - int hashVal = ctx->mModule->mCompiler->mNullableTypeDef->mHash; - hashVal = ((hashVal ^ (Hash(nullableType->mElementType, ctx))) << 5) - hashVal; + int hashVal = ctx->mModule->mCompiler->mNullableTypeDef->mHash; + hashVal = HASH_MIX(hashVal, Hash(nullableType->mElementType, ctx, BfHashFlag_None, hashSeed + 1)); return hashVal; } else if (auto refType = BfNodeDynCastExact(typeRef)) @@ -3312,7 +3326,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash else if (refType->mRefToken->GetToken() == BfToken_Mut) refKind = BfRefType::RefKind_Mut; - int elemHash = Hash(refType->mElementType, ctx) ^ (HASH_VAL_REF + (int)refKind); + int elemHash = Hash(refType->mElementType, ctx, BfHashFlag_None, hashSeed) ^ (HASH_VAL_REF + (int)refKind); return (elemHash << 5) - elemHash; } else @@ -3356,7 +3370,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash ctx->mFailed = true; return 0; } - return Hash(resolvedType, ctx); + int hashVal = Hash(resolvedType, ctx, BfHashFlag_None, hashSeed); + hashSeed = 0; + return hashVal; } else if (auto varType = BfNodeDynCastExact(typeRef)) { @@ -3379,26 +3395,26 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash if (ctx->mRootTypeRef != retTypeTypeRef) { auto type = ctx->mModule->ResolveTypeRef(retTypeTypeRef, BfPopulateType_Identity, ctx->mResolveFlags); - return Hash(type, ctx, flags); + return Hash(type, ctx, flags, hashSeed); } - int elemHash = Hash(retTypeTypeRef->mElementType, ctx) ^ HASH_MODTYPE + retTypeTypeRef->mRetTypeToken->mToken; + int elemHash = Hash(retTypeTypeRef->mElementType, ctx, BfHashFlag_None, hashSeed) ^ HASH_MODTYPE + retTypeTypeRef->mRetTypeToken->mToken; return (elemHash << 5) - elemHash; } else if (auto resolvedTypeRef = BfNodeDynCastExact(typeRef)) { - return Hash(resolvedTypeRef->mType, ctx); + return Hash(resolvedTypeRef->mType, ctx, BfHashFlag_None, hashSeed); } else if (auto constTypeRef = BfNodeDynCastExact(typeRef)) { // We purposely don't mix in a HASH_CONSTTYPE because there's no such thing as a const type in Beef, so we just strip it - return Hash(constTypeRef->mElementType, ctx, flags); + return Hash(constTypeRef->mElementType, ctx, flags, hashSeed); } else if (auto delegateTypeRef = BfNodeDynCastExact(typeRef)) { int hashVal = HASH_DELEGATE; if (delegateTypeRef->mReturnType != NULL) - hashVal = ((hashVal ^ (Hash(delegateTypeRef->mReturnType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(delegateTypeRef->mReturnType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal; else ctx->mFailed = true; @@ -3431,7 +3447,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } } - hashVal = ((hashVal ^ (Hash(fieldType, ctx, (BfHashFlags)(BfHashFlag_AllowRef)))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(fieldType, ctx, (BfHashFlags)(BfHashFlag_AllowRef), hashSeed))) << 5) - hashVal; hashVal = ((hashVal ^ (HashNode(param->mNameNode))) << 5) - hashVal; isFirstParam = true; } @@ -3508,7 +3524,9 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash return 0; } - return Hash(cachedResolvedType, ctx, flags); + int hashVal = Hash(cachedResolvedType, ctx, flags, hashSeed); + hashSeed = 0; + return hashVal; } else if (auto constExprTypeRef = BfNodeDynCastExact(typeRef)) { @@ -3518,7 +3536,11 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash { result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, resultType); if ((resultType != NULL) && (resultType->IsGenericParam())) - return Hash(resultType, ctx); + { + int hashVal = Hash(resultType, ctx, BfHashFlag_None, hashSeed); + hashSeed = 0; + return hashVal; + } } if (resultType == NULL) @@ -3528,7 +3550,7 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash } auto hashVal = ((int)result.mTypeCode << 17) ^ (result.mInt32 << 3) ^ HASH_CONSTTYPE; - hashVal = ((hashVal ^ (Hash(resultType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; + hashVal = ((hashVal ^ (Hash(resultType, ctx, BfHashFlag_AllowRef, hashSeed))) << 5) - hashVal; return hashVal; } else if (auto dotTypeRef = BfNodeDynCastExact(typeRef)) @@ -3544,6 +3566,14 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash return 0; } +int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int hashSeed) +{ + int hashVal = DoHash(typeRef, ctx, flags, hashSeed); + if (hashSeed == 0) + return hashVal; + return HASH_MIX(hashVal, hashSeed); +} + // These types can be from different contexts ("foreign" types) so we can't just compare ptrs bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx) { diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 4b296aa5..e17c74a8 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -501,6 +501,7 @@ public: virtual bool HasBeenReferenced() { return mDefineState != BfTypeDefineState_Undefined; } virtual bool HasTypeFailed() { return false; } virtual bool IsDataIncomplete() { return mDefineState == BfTypeDefineState_Undefined; } + virtual bool IsFinishingType() { return false; } virtual bool IsIncomplete() { return mDefineState < BfTypeDefineState_Defined; } virtual bool IsDeleting() { return ((mRebuildFlags & (BfTypeRebuildFlag_Deleted | BfTypeRebuildFlag_DeleteQueued)) != 0); } virtual bool IsDeclared() { return mDefineState >= BfTypeDefineState_Declared; } @@ -1774,6 +1775,7 @@ public: bool mInitializedGenericParams; bool mFinishedGenericParams; Array mProjectsReferenced; // Generic methods that only refer to these projects don't need a specialized extension + int32 mMaxGenericDepth; public: BfGenericTypeInfo() @@ -1785,6 +1787,7 @@ public: mValidatedGenericConstraints = false; mInitializedGenericParams = false; mFinishedGenericParams = false; + mMaxGenericDepth = -1; } ~BfGenericTypeInfo(); @@ -1955,6 +1958,7 @@ public: virtual bool IsReified() override { return mIsReified; } virtual bool NeedsExplicitAlignment() override { return !IsSizeAligned() || mIsPacked; } virtual bool IsDataIncomplete() override { return ((mTypeIncomplete) || (mBaseTypeMayBeIncomplete)) && (!mNeedsMethodProcessing); } + virtual bool IsFinishingType() override { return mIsFinishingType; } virtual bool IsIncomplete() override { return (mTypeIncomplete) || (mBaseTypeMayBeIncomplete); } virtual bool IsSplattable() override { BF_ASSERT((mInstSize >= 0) || (!IsComposite())); return mIsSplattable; } virtual int GetSplatCount() override; @@ -2525,10 +2529,12 @@ public: static BfVariant EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType); static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* lhsTypeGenericArguments, BfTypeReference* rhs, LookupContext* ctx, int& genericParamOffset); static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* typeGenericArguments, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx); - static void HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hash); - static int Hash(BfType* type, LookupContext* ctx, bool allowRef = false); - static int DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None); - static int Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None); + static void HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hash, int hashSeed); + static int DoHash(BfType* type, LookupContext* ctx, bool allowRef, int hashSeed); + static int Hash(BfType* type, LookupContext* ctx, bool allowRef = false, int hashSeed = 0); + static int DirectHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0); + static int DoHash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags, int& hashSeed); + static int Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHashFlags flags = BfHashFlag_None, int hashSeed = 0); static bool Equals(BfType* lhs, BfType* rhs, LookupContext* ctx); static bool Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* ctx); static bool Equals(BfType* lhs, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx); diff --git a/IDEHelper/Compiler/BfSourceClassifier.cpp b/IDEHelper/Compiler/BfSourceClassifier.cpp index 387671ca..fc073b17 100644 --- a/IDEHelper/Compiler/BfSourceClassifier.cpp +++ b/IDEHelper/Compiler/BfSourceClassifier.cpp @@ -1,5 +1,6 @@ #include "BfSourceClassifier.h" #include "BfParser.h" +#include "BeefySysLib/util/BeefPerf.h" USING_NS_BF; @@ -421,14 +422,22 @@ void BfSourceClassifier::Visit(BfTokenNode* tokenNode) void BfSourceClassifier::Visit(BfInvocationExpression* invocationExpr) { - BfElementVisitor::Visit(invocationExpr); + //BfElementVisitor::Visit(invocationExpr); + Visit(invocationExpr->ToBase()); + + //BP_ZONE("BfSourceClassifier BfInvocationExpression"); BfAstNode* target = invocationExpr->mTarget; if (target == NULL) return; - + + VisitChild(invocationExpr->mOpenParen); + VisitChild(invocationExpr->mCloseParen); + VisitChild(invocationExpr->mGenericArgs); + if (auto scopedTarget = BfNodeDynCast(target)) { + VisitChild(target); target = scopedTarget->mTarget; VisitChild(scopedTarget->mScopeName); } @@ -438,25 +447,33 @@ void BfSourceClassifier::Visit(BfInvocationExpression* invocationExpr) { VisitChild(qualifiedName->mLeft); VisitChild(qualifiedName->mDot); + VisitChild(qualifiedName->mRight); identifier = qualifiedName->mRight; } else if ((identifier = BfNodeDynCast(target))) { + VisitChild(target); // Leave as BfAttributedIdentifierNode if that's the case - identifier = target; + identifier = target; } else if (auto qualifiedName = BfNodeDynCast(target)) { VisitChild(qualifiedName->mLeft); VisitChild(qualifiedName->mDot); + VisitChild(qualifiedName->mRight); identifier = qualifiedName->mRight; } else if (auto memberRefExpr = BfNodeDynCast(target)) { VisitChild(memberRefExpr->mTarget); VisitChild(memberRefExpr->mDotToken); + VisitChild(memberRefExpr->mMemberName); identifier = memberRefExpr->mMemberName; } + else + { + VisitChild(target); + } if (identifier != NULL) { @@ -469,20 +486,25 @@ void BfSourceClassifier::Visit(BfInvocationExpression* invocationExpr) if (identifier != NULL) SetElementType(identifier, BfSourceElementType_Method); } + + for (auto& val : invocationExpr->mArguments) + VisitChild(val); + for (auto& val : invocationExpr->mCommas) + VisitChild(val); } void BfSourceClassifier::Visit(BfIndexerExpression* indexerExpr) { - BfElementVisitor::Visit(indexerExpr); + //BfElementVisitor::Visit(indexerExpr); + Visit(indexerExpr->ToBase()); VisitChild(indexerExpr->mTarget); VisitChild(indexerExpr->mOpenBracket); - for (int i = 0; i < (int) indexerExpr->mArguments.size(); i++) - { - if (i > 0) - VisitChild(indexerExpr->mCommas[i - 1]); - VisitChild(indexerExpr->mArguments[i]); - } + + for (auto& val : indexerExpr->mArguments) + VisitChild(val); + for (auto& val : indexerExpr->mCommas) + VisitChild(val); VisitChild(indexerExpr->mCloseBracket); } @@ -523,6 +545,8 @@ void BfSourceClassifier::Visit(BfMethodDeclaration* methodDeclaration) if (!IsInterestedInMember(methodDeclaration)) return; + //BP_ZONE("BfSourceClassifier BfMethodDeclaration"); + SetAndRestoreValue prevMember(mCurMember, methodDeclaration); BfElementVisitor::Visit(methodDeclaration); diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 46e94efd..091b96e6 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -1654,7 +1654,7 @@ BfLocalVariable* BfModule::HandleVariableDeclaration(BfVariableDeclaration* varD if (isConst) { BfConstResolver constResolver(this); - initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_RemapFromStringId); + initValue = constResolver.Resolve(varDecl->mInitializer, resolvedType, BfConstResolveFlag_ActualizeValues); if (!initValue) initValue = GetDefaultTypedValue(resolvedType); } @@ -3934,15 +3934,7 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt) bool allowProtected = allowPrivate || TypeIsSubTypeOf(mCurTypeInstance, checkTypeInst); while (checkTypeInst != NULL) { - auto checkTypeDef = checkTypeInst->mTypeDef; - - checkTypeDef->PopulateMemberSets(); - BfMemberSetEntry* entry = NULL; - BfMethodDef* dtorMethodDef = NULL; - checkTypeDef->mMethodSet.TryGetWith(String("~this"), &entry); - if (entry != NULL) - dtorMethodDef = (BfMethodDef*)entry->mMemberDef; - + auto dtorMethodDef = checkTypeInst->mTypeDef->GetMethodByName("~this"); if (dtorMethodDef) { if (!CheckProtection(dtorMethodDef->mProtection, checkTypeInst->mTypeDef, allowProtected, allowPrivate)) @@ -6734,7 +6726,13 @@ void BfModule::Visit(BfDeferStatement* deferStmt) if ((scope == mCurMethodState->mCurScope) && (scope->mCloseNode == NULL)) { - Warn(0, "This defer will immediately execute. Consider specifying a wider scope target such as 'defer::'", deferStmt->mDeferToken); + auto parser = deferStmt->GetParser(); + if ((parser != NULL) && (parser->mFileName.Contains('|'))) + { + // Is emitted + } + else + Warn(0, "This defer will immediately execute. Consider specifying a wider scope target such as 'defer::'", deferStmt->mDeferToken); } if (auto block = BfNodeDynCast(deferStmt->mTargetNode)) diff --git a/IDEHelper/Compiler/BfSystem.cpp b/IDEHelper/Compiler/BfSystem.cpp index 098a58be..1c5fa766 100644 --- a/IDEHelper/Compiler/BfSystem.cpp +++ b/IDEHelper/Compiler/BfSystem.cpp @@ -833,12 +833,26 @@ int BfTypeDef::GetSelfGenericParamCount() BfMethodDef* BfTypeDef::GetMethodByName(const StringImpl& name, int paramCount) { - for (auto method : mMethods) - { - if ((name == method->mName) && ((paramCount == -1) || (paramCount == (int)method->mParams.size()))) - return method; + PopulateMemberSets(); + BfMemberSetEntry* entry = NULL; + if (!mMethodSet.TryGetWith(name, &entry)) + return NULL; + + BfMethodDef* bestMethodDef = NULL; + auto methodDef = (BfMethodDef*)entry->mMemberDef; + while (methodDef != NULL) + { + if (((paramCount == -1) || (paramCount == (int)methodDef->mParams.size()))) + { + if ((bestMethodDef == NULL) || + ((bestMethodDef->mDeclaringType->IsExtension()) && (!methodDef->mDeclaringType->IsExtension()))) + bestMethodDef = methodDef; + } + + methodDef = methodDef->mNextWithSameName; } - return NULL; + + return bestMethodDef; } BfFieldDef* BfTypeDef::GetFieldByName(const StringImpl& name) @@ -1810,7 +1824,7 @@ BfSystem::BfSystem() if (gPerfManager == NULL) gPerfManager = new PerfManager(); //gPerfManager->StartRecording(); - + mAtomUpdateIdx = 0; mAtomCreateIdx = 0; mTypeMapVersion = 1; @@ -2586,6 +2600,13 @@ void BfSystem::RemoveTypeDef(BfTypeDef* typeDef) mTypeDefs.Remove(typeDef); AutoCrit autoCrit(mDataLock); + if (typeDef->mOuterType != NULL) + { + // We are in the outer type's mNestedTypes list + BfLogSys(this, "Setting mForceUseNextRevision on outer type %p from %p\n", typeDef->mOuterType, typeDef); + typeDef->mOuterType->mForceUseNextRevision = true; + } + // This will get properly handled in UntrackName when we process the mTypeDefDeleteQueue, but this // mAtomUpdateIdx increment will trigger lookup changes in BfContext::VerifyTypeLookups if (typeDef->mName != mEmptyAtom) @@ -2797,6 +2818,7 @@ void BfSystem::InjectNewRevision(BfTypeDef* typeDef) typeDef->mNextRevision = NULL; typeDef->mDefState = BfTypeDef::DefState_Defined; + typeDef->mForceUseNextRevision = false; VerifyTypeDef(typeDef); } diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index dc7876c4..cec7a07d 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -1006,6 +1006,7 @@ public: bool mIsNextRevision; bool mInDeleteQueue; bool mHasEmitMembers; + bool mForceUseNextRevision; public: BfTypeDef() @@ -1048,6 +1049,7 @@ public: mIsNextRevision = false; mInDeleteQueue = false; mHasEmitMembers = false; + mForceUseNextRevision = false; mDupDetectedRevision = -1; mNestDepth = 0; mOuterType = NULL; @@ -1500,7 +1502,7 @@ public: Array mMergedTypeOptions; int mUpdateCnt; bool mWorkspaceConfigChanged; - Val128 mWorkspaceConfigHash; + Val128 mWorkspaceConfigHash; Array mCompilers; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index e39ece14..1945bee8 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -3809,7 +3809,7 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType BfIRValue CeContext::CreateAttribute(BfAstNode* targetSrc, BfModule* module, BfIRConstHolder* constHolder, BfCustomAttribute* customAttribute) { - module->PopulateType(customAttribute->mType); + module->mContext->mUnreifiedModule->PopulateType(customAttribute->mType); auto ceAttrAddr = CeMalloc(customAttribute->mType->mSize) - mMemory.mVals; BfIRValue ceAttrVal = module->mBfIRBuilder->CreateConstAggCE(module->mBfIRBuilder->MapType(customAttribute->mType, BfIRPopulateType_Identity), ceAttrAddr); BfTypedValue ceAttrTypedValue(ceAttrVal, customAttribute->mType); @@ -4335,7 +4335,7 @@ static void CeSetAddrVal(void* ptr, addr_ce val, int32 ptrSize) } bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* startFramePtr, BfType*& returnType) -{ +{ auto ceModule = mCeMachine->mCeModule; CeFunction* ceFunction = startFunction; returnType = startFunction->mMethodInstance->mReturnType; @@ -5408,6 +5408,15 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* mCeMachine->PrepareFunction(callEntry.mFunction, NULL); } + if (callEntry.mFunction->mMethodInstance != NULL) + { + if (callEntry.mFunction->mMethodInstance->GetOwner()->IsDeleting()) + { + _Fail("Calling method on deleted type"); + return false; + } + } + callEntry.mBindRevision = mCeMachine->mMethodBindRevision; } @@ -6255,6 +6264,9 @@ CeMachine::~CeMachine() auto _RemoveFunctionInfo = [&](CeFunctionInfo* functionInfo) { + if (functionInfo->mMethodInstance != NULL) + functionInfo->mMethodInstance->mInCEMachine = false; + if (functionInfo->mCeFunction != NULL) { // We don't need to actually unmap it at this point @@ -6411,8 +6423,21 @@ CeErrorKind CeMachine::WriteConstant(CeConstStructData& data, BeConstant* constV if (globalVar->mName.StartsWith("__bfStrObj")) { int stringId = atoi(globalVar->mName.c_str() + 10); - addr_ce stringAddr = ceContext->GetString(stringId); + addr_ce stringAddr; + if (data.mQueueFixups) + { + stringAddr = 0; + CeConstStructFixup fixup; + fixup.mKind = CeConstStructFixup::Kind_StringPtr; + fixup.mValue = stringId; + fixup.mOffset = (int)data.mData.mSize; + data.mFixups.Add(fixup); + } + else + { + stringAddr = ceContext->GetString(stringId); + } auto ptr = data.mData.GrowUninitialized(ceModule->mSystem->mPtrSize); int64 addr64 = stringAddr; memcpy(ptr, &addr64, ceModule->mSystem->mPtrSize); @@ -6932,10 +6957,9 @@ CeFunction* CeMachine::GetFunction(BfMethodInstance* methodInstance, BfIRValue f ceFunction->mCeMachine = this; ceFunction->mIsVarReturn = methodInstance->mReturnType->IsVar(); ceFunction->mCeFunctionInfo = ceFunctionInfo; - ceFunction->mMethodInstance = methodInstance; - + ceFunction->mMethodInstance = methodInstance; ceFunctionInfo->mMethodInstance = methodInstance; - ceFunctionInfo->mCeFunction = ceFunction; + ceFunctionInfo->mCeFunction = ceFunction; MapFunctionId(ceFunction); } diff --git a/IDEHelper/Debugger.h b/IDEHelper/Debugger.h index 1b0a740e..a9416539 100644 --- a/IDEHelper/Debugger.h +++ b/IDEHelper/Debugger.h @@ -120,6 +120,7 @@ enum DwEvalExpressionFlags : int16 DwEvalExpressionFlag_MemoryWatch = 0x80, DwEvalExpressionFlag_Symbol = 0x100, DwEvalExpressionFlag_StepIntoCalls = 0x200, + DwEvalExpressionFlag_RawStr = 0x400 }; struct DwDisplayInfo diff --git a/IDEHelper/NetManager.cpp b/IDEHelper/NetManager.cpp index 7bc4edd3..c198ea6d 100644 --- a/IDEHelper/NetManager.cpp +++ b/IDEHelper/NetManager.cpp @@ -82,17 +82,14 @@ static size_t WriteMemoryCallback(void* contents, size_t size, size_t nmemb, voi void NetRequest::Cleanup() { if (mCURLMulti != NULL) - { - curl_multi_remove_handle(mCURLMulti, mCURL); - } + curl_multi_remove_handle(mCURLMulti, mCURL); + if (mCURL != NULL) + curl_easy_cleanup(mCURL); + if (mCURLMulti != NULL) + curl_multi_cleanup(mCURLMulti); - if (mCURL != NULL) - curl_easy_cleanup(mCURL); - - if (mCURLMulti != NULL) - { - curl_multi_cleanup(mCURLMulti); - } + mCURL = NULL; + mCURLMulti = NULL; } void NetRequest::DoTransfer() @@ -105,65 +102,75 @@ void NetRequest::DoTransfer() // return; // } - BfLogDbg("NetManager starting get on %s\n", mURL.c_str()); - mNetManager->mDebugManager->OutputRawMessage(StrFormat("msgLo Getting '%s'\n", mURL.c_str())); - - mOutTempPath = mOutPath + "__partial"; - - mCURLMulti = curl_multi_init(); - - mCURL = curl_easy_init(); - - if (mShowTracking) - { - mNetManager->mDebugManager->OutputRawMessage(StrFormat("symsrv Getting '%s'", mURL.c_str())); - } - - //OutputDebugStrF("Getting '%s'\n", mURL.c_str()); - - curl_easy_setopt(mCURL, CURLOPT_URL, mURL.c_str()); - curl_easy_setopt(mCURL, CURLOPT_WRITEDATA, (void*)this); - curl_easy_setopt(mCURL, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); - curl_easy_setopt(mCURL, CURLOPT_XFERINFODATA, (void*)this); - curl_easy_setopt(mCURL, CURLOPT_XFERINFOFUNCTION, TransferInfoCallback); - curl_easy_setopt(mCURL, CURLOPT_FOLLOWLOCATION, 1L); - curl_easy_setopt(mCURL, CURLOPT_NOPROGRESS, 0L); - curl_easy_setopt(mCURL, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); // Connects go slow without this - //auto result = curl_easy_perform(mCURL); - - CURLMcode mcode = curl_multi_add_handle(mCURLMulti, mCURL); - if (mcode != CURLM_OK) + long response_code = 0; + for (int pass = 0; pass < 3; pass++) { - mFailed = true; - return; - } - - while (true) - { - int activeCount = 0; - curl_multi_perform(mCURLMulti, &activeCount); - if (activeCount == 0) - break; + BfLogDbg("NetManager starting get on %s Pass:%d\n", mURL.c_str(), pass); + mNetManager->mDebugManager->OutputRawMessage(StrFormat("msgLo Getting '%s'\n", mURL.c_str())); - int waitRet = 0; - curl_multi_wait(mCURLMulti, NULL, 0, 20, &waitRet); + mOutTempPath = mOutPath + "__partial"; - if (mCancelling) + mCURLMulti = curl_multi_init(); + + mCURL = curl_easy_init(); + + if (mShowTracking) + { + mNetManager->mDebugManager->OutputRawMessage(StrFormat("symsrv Getting '%s'", mURL.c_str())); + } + + //OutputDebugStrF("Getting '%s'\n", mURL.c_str()); + + curl_easy_setopt(mCURL, CURLOPT_URL, mURL.c_str()); + curl_easy_setopt(mCURL, CURLOPT_WRITEDATA, (void*)this); + curl_easy_setopt(mCURL, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); + curl_easy_setopt(mCURL, CURLOPT_XFERINFODATA, (void*)this); + curl_easy_setopt(mCURL, CURLOPT_XFERINFOFUNCTION, TransferInfoCallback); + curl_easy_setopt(mCURL, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(mCURL, CURLOPT_NOPROGRESS, 0L); + curl_easy_setopt(mCURL, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); // Connects go slow without this + //auto result = curl_easy_perform(mCURL); + + CURLMcode mcode = curl_multi_add_handle(mCURLMulti, mCURL); + if (mcode != CURLM_OK) { mFailed = true; return; } - } -// if (result != CURLE_OK) -// { -// mFailed = true; -// return; -// } + while (true) + { + int activeCount = 0; + curl_multi_perform(mCURLMulti, &activeCount); + if (activeCount == 0) + break; + + int waitRet = 0; + curl_multi_wait(mCURLMulti, NULL, 0, 20, &waitRet); + + if (mCancelling) + { + mFailed = true; + return; + } + } + + // if (result != CURLE_OK) + // { + // mFailed = true; + // return; + // } - long response_code = 0; - curl_easy_getinfo(mCURL, CURLINFO_RESPONSE_CODE, &response_code); - mNetManager->mDebugManager->OutputRawMessage(StrFormat("msgLo Result for '%s': %d\n", mURL.c_str(), response_code)); + response_code = 0; + curl_easy_getinfo(mCURL, CURLINFO_RESPONSE_CODE, &response_code); + mNetManager->mDebugManager->OutputRawMessage(StrFormat("msgLo Result for '%s': %d\n", mURL.c_str(), response_code)); + + if ((response_code == 0) || (response_code == 200) || (response_code == 404)) + break; + + Cleanup(); + // Try again! + } if (response_code == 200) { diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 1d264f89..2fe333cd 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -80,6 +80,21 @@ namespace Tests } } + [IFaceA("C", InitVal=345)] + struct StructA + { + public int mA = 123; + + [OnCompile(.TypeInit), Comptime] + public static void Generate() + { + Compiler.EmitTypeBody(typeof(Self), """ + public int32 mB = 234; + public int32 GetValB() => mB; + """); + } + } + enum MethodAErr { ErrorA, @@ -168,6 +183,13 @@ namespace Tests Test.Assert(ca.mC == 345); Test.Assert(ca.GetValC() == 345); + StructA sa = .(); + Test.Assert(sa.mA == 123); + Test.Assert(sa.mB == 234); + Test.Assert(sa.GetValB() == 234); + Test.Assert(sa.mC == 345); + Test.Assert(sa.GetValC() == 345); + Compiler.Mixin("int val = 99;"); Test.Assert(val == 99); diff --git a/IDEHelper/Tests/src/Extensions.bf b/IDEHelper/Tests/src/Extensions.bf index f4e343db..63e5a5d0 100644 --- a/IDEHelper/Tests/src/Extensions.bf +++ b/IDEHelper/Tests/src/Extensions.bf @@ -160,6 +160,32 @@ namespace Tests return 1; } } + + class ClassF + { + public static int sVal = 3; + + public int mF0 = 1 ~ + { + sVal += 40; + }; + } + + extension ClassF + { + public int mF1 = 2 ~ + { + sVal += 500; + }; + } + + class ClassG : ClassF + { + public int mG0 = 3 ~ + { + sVal += 6000; + }; + } extension TClassA where T : IGetExVal { @@ -226,6 +252,26 @@ namespace Tests ClassE ce = scope .(); Test.Assert(ce.mD == 1); Test.Assert(ce.mE == 1); + + /// + { + ClassF cf = scope .(); + } + Test.Assert(ClassF.sVal == 543); + /// + { + ClassF.sVal = 3; + ClassG cg = scope .(); + } + Test.Assert(ClassF.sVal == 6543); + ClassF.sVal = 3; + Object obj = new ClassF(); + delete obj; + Test.Assert(ClassF.sVal == 543); + ClassF.sVal = 3; + obj = new ClassG(); + delete obj; + Test.Assert(ClassF.sVal == 6543); } [Test] diff --git a/IDEHelper/Tests/src/Generics2.bf b/IDEHelper/Tests/src/Generics2.bf index 390b6892..98ef35d3 100644 --- a/IDEHelper/Tests/src/Generics2.bf +++ b/IDEHelper/Tests/src/Generics2.bf @@ -95,6 +95,16 @@ namespace Tests } } + class IFaceA where T0 : Dictionary where T1 : IHashable + { + Dictionary mDict; + } + + public static void MethodA() where T0 : Dictionary where T1 : IHashable + { + + } + [Test] public static void TestBasics() { diff --git a/IDEHelper/Tests/src/Reflection.bf b/IDEHelper/Tests/src/Reflection.bf index 85ccaa1a..89dcc0f1 100644 --- a/IDEHelper/Tests/src/Reflection.bf +++ b/IDEHelper/Tests/src/Reflection.bf @@ -239,6 +239,32 @@ namespace Tests switch (methodIdx) { case 0: + Test.Assert(methodInfo.Name == "__BfCtor"); + Test.Assert(methodInfo.IsConstructor); + case 1: + Test.Assert(methodInfo.Name == "__BfStaticCtor"); + Test.Assert(methodInfo.IsConstructor); + case 2: + Test.Assert(methodInfo.Name == "GetA"); + var result = methodInfo.Invoke(ca, 123).Get(); + Test.Assert(result.Get() == 1123); + result.Dispose(); + result = methodInfo.Invoke(ca2, 123).Get(); + Test.Assert(result.Get() == 2123); + result.Dispose(); + result = methodInfo.Invoke(.Create(ca2), .Create(123)).Get(); + Test.Assert(result.Get() == 2123); + result.Dispose(); + case 3: + Test.Assert(methodInfo.Name == "MemberMethodA"); + var result = methodInfo.Invoke(ca, 100, (int32)20, 3.0f).Get(); + Test.Assert(result.Get() == 123); + result.Dispose(); + + result = methodInfo.Invoke(.Create(ca), .Create(100), .Create((int32)20), .Create(3.0f)).Get(); + Test.Assert(result.Get() == 123); + result.Dispose(); + case 4: StructA sa = .() { mA = 1, mB = 2 }; Test.Assert(methodInfo.Name == "StaticMethodA"); @@ -291,7 +317,7 @@ namespace Tests let attrC = methodInfo.GetCustomAttribute().Get(); Test.Assert(attrC.mA == 71); Test.Assert(attrC.mB == 72); - case 1: + case 5: Test.Assert(methodInfo.Name == "StaticMethodB"); var fieldA = typeInfo.GetField("mA").Value; @@ -337,33 +363,6 @@ namespace Tests res.Dispose(); fieldSAV.Dispose(); fieldSStrV.Dispose(); - - case 2: - Test.Assert(methodInfo.Name == "MemberMethodA"); - var result = methodInfo.Invoke(ca, 100, (int32)20, 3.0f).Get(); - Test.Assert(result.Get() == 123); - result.Dispose(); - - result = methodInfo.Invoke(.Create(ca), .Create(100), .Create((int32)20), .Create(3.0f)).Get(); - Test.Assert(result.Get() == 123); - result.Dispose(); - case 3: - Test.Assert(methodInfo.Name == "GetA"); - var result = methodInfo.Invoke(ca, 123).Get(); - Test.Assert(result.Get() == 1123); - result.Dispose(); - result = methodInfo.Invoke(ca2, 123).Get(); - Test.Assert(result.Get() == 2123); - result.Dispose(); - result = methodInfo.Invoke(.Create(ca2), .Create(123)).Get(); - Test.Assert(result.Get() == 2123); - result.Dispose(); - case 4: - Test.Assert(methodInfo.Name == "__BfStaticCtor"); - Test.Assert(methodInfo.IsConstructor); - case 5: - Test.Assert(methodInfo.Name == "__BfCtor"); - Test.Assert(methodInfo.IsConstructor); case 6: Test.FatalError(); // Shouldn't have any more } @@ -445,6 +444,8 @@ namespace Tests switch (methodIdx) { case 0: + Test.Assert(methodInfo.Name == "__BfCtor"); + case 1: Test.Assert(methodInfo.Name == "GetA"); var result = methodInfo.Invoke(sa, 34).Get(); @@ -464,7 +465,7 @@ namespace Tests result = methodInfo.Invoke(.Create(&sa), .Create(34)); Test.Assert(result.Get() == 1234); result.Dispose(); - case 1: + case 2: Test.Assert(methodInfo.Name == "GetB"); var result = methodInfo.Invoke(sa, 34).Get(); @@ -489,16 +490,15 @@ namespace Tests Test.Assert(sa.mB == 91); result.Dispose(); - case 2: - Test.Assert(methodInfo.Name == "MethodA0"); case 3: - Test.Assert(methodInfo.Name == "MethodA1"); + Test.Assert(methodInfo.Name == "MethodA0"); case 4: - Test.Assert(methodInfo.Name == "__BfCtor"); + Test.Assert(methodInfo.Name == "MethodA1"); case 5: Test.Assert(methodInfo.Name == "__Equals"); case 6: Test.Assert(methodInfo.Name == "__StrictEquals"); + default: Test.FatalError(); // Shouldn't have any more } diff --git a/IDEHelper/WinDebugger.cpp b/IDEHelper/WinDebugger.cpp index e685cd74..b443c538 100644 --- a/IDEHelper/WinDebugger.cpp +++ b/IDEHelper/WinDebugger.cpp @@ -9504,6 +9504,11 @@ String WinDebugger::Evaluate(const StringImpl& expr, DwFormatInfo formatInfo, in expressionFlags = (DwEvalExpressionFlags)(expressionFlags & ~DwEvalExpressionFlag_AllowCalls); } + if ((expressionFlags & DwEvalExpressionFlag_RawStr) != 0) + { + formatInfo.mRawString = true; + } + auto dbgModule = GetCallStackDbgModule(callStackIdx); auto dbgSubprogram = GetCallStackSubprogram(callStackIdx); DbgCompileUnit* dbgCompileUnit = NULL;