mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Merge branch 'master' into FuzzyAutoComplete
This commit is contained in:
commit
62c3998521
64 changed files with 2485 additions and 598 deletions
|
@ -47,7 +47,7 @@ BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
|
|||
BF_IMPORT void BF_CALLTYPE BfSystem_Delete(void* bfSystem);
|
||||
BF_IMPORT void* BF_CALLTYPE BfSystem_CreatePassInstance(void* bfSystem);
|
||||
BF_IMPORT void* BF_CALLTYPE BfSystem_CreateCompiler(void* bfSystem, bool isResolveOnly);
|
||||
BF_IMPORT void* BF_CALLTYPE BfSystem_CreateProject(void* bfSystem, const char* projectName);
|
||||
BF_IMPORT void* BF_CALLTYPE BfSystem_CreateProject(void* bfSystem, const char* projectName, const char* projectDir);
|
||||
BF_IMPORT void BF_CALLTYPE BfParser_Delete(void* bfParser);
|
||||
BF_IMPORT void BF_CALLTYPE BfSystem_AddTypeOptions(void* bfSystem, const char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 arrayBoundsCheck,
|
||||
int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth);
|
||||
|
@ -790,12 +790,12 @@ bool BootApp::Compile()
|
|||
projectName.RemoveToEnd(dotPos);
|
||||
if (projectName.IsEmpty())
|
||||
projectName.Append("BeefProject");
|
||||
|
||||
mProject = BfSystem_CreateProject(mSystem, projectName.c_str());
|
||||
|
||||
mProject = BfSystem_CreateProject(mSystem, projectName.c_str(), GetFileDir(mTargetPath).c_str());
|
||||
|
||||
if (mIsCERun)
|
||||
{
|
||||
mCELibProject = BfSystem_CreateProject(mSystem, "BeefLib");
|
||||
mCELibProject = BfSystem_CreateProject(mSystem, "BeefLib", GetFileDir(mTargetPath).c_str());
|
||||
|
||||
BfProjectFlags flags = BfProjectFlags_None;
|
||||
BfProject_SetOptions(mCELibProject, BfTargetType_BeefLib, "", mDefines.c_str(), mOptLevel, 0, 0, 0, flags);
|
||||
|
|
|
@ -69,6 +69,12 @@ namespace Beefy.sys
|
|||
Modify(mText, mHotKey, mBitmap, mEnabled, mCheckState, mRadioCheck);
|
||||
}
|
||||
|
||||
public void SetCheckState(int32 checkState)
|
||||
{
|
||||
mCheckState = checkState;
|
||||
Modify(mText, mHotKey, mBitmap, mEnabled, mCheckState, mRadioCheck);
|
||||
}
|
||||
|
||||
public void SetHotKey(StringView hotKey)
|
||||
{
|
||||
if (hotKey.IsNull)
|
||||
|
|
|
@ -2366,7 +2366,14 @@ namespace Beefy.widgets
|
|||
case KeyCode.Down:
|
||||
{
|
||||
int32 aDir = (keyCode == KeyCode.Up) ? -1 : 1;
|
||||
bool didSelectionMove = PrepareForCursorMove(aDir);
|
||||
if ((HasSelection()) && (!mWidgetWindow.IsKeyDown(KeyCode.Shift)))
|
||||
{
|
||||
var lineAndCol = CursorLineAndColumn;
|
||||
var usePos = (aDir < 0) ? (int32)mSelection.Value.MinPos : mSelection.Value.MaxPos;
|
||||
GetLineCharAtIdx(usePos, var selLine, var selLineChar);
|
||||
CursorLineAndColumn = .(selLine, lineAndCol.mColumn);
|
||||
mSelection = null;
|
||||
}
|
||||
|
||||
GetCursorLineChar(out lineIdx, out lineChar);
|
||||
|
||||
|
@ -2403,9 +2410,6 @@ namespace Beefy.widgets
|
|||
mCursorWantX = wantedX;
|
||||
|
||||
}
|
||||
|
||||
if (didSelectionMove)
|
||||
CursorToLineStart(false);
|
||||
}
|
||||
break;
|
||||
case KeyCode.Home:
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace Beefy.widgets
|
|||
public interface IMenu
|
||||
{
|
||||
void SetDisabled(bool enable);
|
||||
void SetCheckState(int32 checkState);
|
||||
}
|
||||
|
||||
public interface IMenuContainer
|
||||
|
|
|
@ -90,13 +90,13 @@ namespace Beefy.widgets
|
|||
Minus = 0xBD,
|
||||
Period = 0xBE,
|
||||
Slash = 0xBF,
|
||||
Tilde = 0xC0,
|
||||
Grave = 0xC0,
|
||||
LBracket = 0xDB,
|
||||
Backslash = 0xDC,
|
||||
RBracket = 0xDD,
|
||||
Apostrophe = 0xDE,
|
||||
Backtick = 0xDF,
|
||||
Tilde = 0xC0,
|
||||
Command = 0xF0,
|
||||
COUNT = 0xFF,
|
||||
|
||||
|
@ -141,6 +141,16 @@ namespace Beefy.widgets
|
|||
return (KeyCode)LBracket;
|
||||
if (c == ']')
|
||||
return (KeyCode)RBracket;
|
||||
if (c == '/')
|
||||
return (KeyCode)Slash;
|
||||
if (c == '\\')
|
||||
return (KeyCode)Backslash;
|
||||
if (c == '`')
|
||||
return (KeyCode)Tilde;
|
||||
if (c == '.')
|
||||
return (KeyCode)Period;
|
||||
if (c == ',')
|
||||
return (KeyCode)Comma;
|
||||
}
|
||||
|
||||
if (str.StartsWith("0x"))
|
||||
|
@ -168,6 +178,10 @@ namespace Beefy.widgets
|
|||
c = '[';
|
||||
case RBracket:
|
||||
c = ']';
|
||||
case .Slash:
|
||||
c = '/';
|
||||
case .Backslash:
|
||||
c = '\\';
|
||||
default:
|
||||
}
|
||||
if (c != 0)
|
||||
|
|
|
@ -616,5 +616,10 @@ namespace Beefy.widgets
|
|||
{
|
||||
mDisabled = disabled;
|
||||
}
|
||||
|
||||
public void SetCheckState(int32 checkState)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,7 +117,7 @@ namespace SDL2
|
|||
SDL.EventState(.JoyDeviceAdded, .Disable);
|
||||
SDL.EventState(.JoyDeviceRemoved, .Disable);
|
||||
|
||||
mWindow = SDL.CreateWindow(mTitle, .Undefined, .Undefined, mWidth, mHeight, .Shown);
|
||||
mWindow = SDL.CreateWindow(mTitle, .Undefined, .Undefined, mWidth, mHeight, .Hidden); // Initially hide window
|
||||
mRenderer = SDL.CreateRenderer(mWindow, -1, .Accelerated);
|
||||
mScreen = SDL.GetWindowSurface(mWindow);
|
||||
SDLImage.Init(.PNG | .JPG);
|
||||
|
@ -246,7 +246,9 @@ namespace SDL2
|
|||
if (curPhysTickCount == 0)
|
||||
{
|
||||
// Initial render
|
||||
Render();
|
||||
Render();
|
||||
// Show initially hidden window, mitigates white flash on slow startups
|
||||
SDL.ShowWindow(mWindow);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -30,6 +30,8 @@ namespace System
|
|||
Delete = 0x80000,
|
||||
Alias = 0x100000,
|
||||
Block = 0x200000,
|
||||
DelegateTypeRef = 0x400000,
|
||||
FunctionTypeRef = 0x800000,
|
||||
|
||||
Types = .Struct | .Enum | .Function | .Class | .Interface,
|
||||
ValueTypes = .Struct | .Enum | .Function,
|
||||
|
@ -227,7 +229,7 @@ namespace System
|
|||
|
||||
}
|
||||
|
||||
[AttributeUsage(.Method | .Constructor | .Delegate | .Function)]
|
||||
[AttributeUsage(.Method | .Constructor | .Delegate | .Function | .DelegateTypeRef | .FunctionTypeRef)]
|
||||
public struct CallingConventionAttribute : Attribute
|
||||
{
|
||||
public enum Kind
|
||||
|
|
|
@ -17,6 +17,11 @@ namespace System
|
|||
strBuffer.Append(((bool)this) ? TrueString : FalseString);
|
||||
}
|
||||
|
||||
public static int operator<=>(Boolean a, Boolean b)
|
||||
{
|
||||
return (SelfBase)a <=> (SelfBase)b;
|
||||
}
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return ((bool)this) ? 1 : 0;
|
||||
|
|
|
@ -311,6 +311,7 @@ namespace System.Collections
|
|||
{
|
||||
if (sizeof(int) == 4)
|
||||
return (int32)hashCode & 0x7FFFFFFF;
|
||||
#unwarn
|
||||
if (sizeof(int_cosize) == 8)
|
||||
return (int_cosize)(hashCode & 0x7FFFFFFF'FFFFFFFFL);
|
||||
return ((int32)hashCode ^ (int32)((int64)hashCode >> 33)) & 0x7FFFFFFF;
|
||||
|
|
|
@ -2,6 +2,7 @@ using System.Reflection;
|
|||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Security.Cryptography;
|
||||
using System.IO;
|
||||
|
||||
namespace System
|
||||
{
|
||||
|
@ -217,6 +218,12 @@ namespace System
|
|||
[LinkName("#CallerFileDir")]
|
||||
public static extern String CallerFileDir;
|
||||
|
||||
[LinkName("#CallerType")]
|
||||
public static extern Type CallerType;
|
||||
|
||||
[LinkName("#CallerTypeName")]
|
||||
public static extern String CallerTypeName;
|
||||
|
||||
[LinkName("#CallerMemberName")]
|
||||
public static extern String CallerMemberName;
|
||||
|
||||
|
@ -300,5 +307,21 @@ namespace System
|
|||
if (Compiler.IsComptime)
|
||||
Comptime_EmitMixin(text);
|
||||
}
|
||||
|
||||
[Comptime]
|
||||
public static Span<uint8> ReadBinary(StringView path)
|
||||
{
|
||||
List<uint8> data = scope .();
|
||||
File.ReadAll(path, data);
|
||||
return data;
|
||||
}
|
||||
|
||||
[Comptime]
|
||||
public static String ReadText(StringView path)
|
||||
{
|
||||
String data = scope .();
|
||||
File.ReadAllText(path, data);
|
||||
return data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,5 +106,24 @@ namespace System.Diagnostics
|
|||
if (gIsDebuggerPresent)
|
||||
Break();
|
||||
}
|
||||
|
||||
public static void WriteMemory(Span<uint8> mem)
|
||||
{
|
||||
String str = scope .();
|
||||
for (int i < mem.Length)
|
||||
{
|
||||
if ((i != 0) && (i % 16 == 0))
|
||||
str.Append('\n');
|
||||
str.AppendF($" {mem.[Friend]mPtr[i]:X2}");
|
||||
}
|
||||
str.Append('\n');
|
||||
Write(str);
|
||||
}
|
||||
|
||||
public static void WriteMemory<T>(T result)
|
||||
{
|
||||
#unwarn
|
||||
WriteMemory(.((.)&result, sizeof(T)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,23 @@ namespace System.Diagnostics
|
|||
|
||||
struct ProfileInstance : int32
|
||||
{
|
||||
public void Dispose()
|
||||
public bool HasValue
|
||||
{
|
||||
get
|
||||
{
|
||||
return this != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose() mut
|
||||
{
|
||||
if (this == 0)
|
||||
return;
|
||||
String str = scope String();
|
||||
str.Append("StopSampling\t");
|
||||
((int32)this).ToString(str);
|
||||
Internal.ProfilerCmd(str);
|
||||
this = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System.Reflection;
|
||||
using System.Collections;
|
||||
|
||||
namespace System
|
||||
{
|
||||
|
@ -30,12 +31,157 @@ namespace System
|
|||
return .Err;
|
||||
}
|
||||
|
||||
/*public override void ToString(String strBuffer) mut
|
||||
public static bool IsDefined<T>(T value)
|
||||
where T : enum
|
||||
{
|
||||
Type type = GetType();
|
||||
int32* iPtr = (int32*)((int)(&this) + (int)type.Size);
|
||||
EnumToString(type, strBuffer, *iPtr);
|
||||
//EnumToString(GetType(), )
|
||||
}*/
|
||||
var typeInst = (TypeInstance)typeof(T);
|
||||
for (var field in typeInst.GetFields())
|
||||
{
|
||||
if (field.[Friend]mFieldData.[Friend]mData == (.)value)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static EnumEnumerator<TEnum> GetEnumerator<TEnum>()
|
||||
where TEnum : enum
|
||||
{
|
||||
return .();
|
||||
}
|
||||
|
||||
public static EnumValuesEnumerator<TEnum> GetValues<TEnum>()
|
||||
where TEnum : enum
|
||||
{
|
||||
return .();
|
||||
}
|
||||
|
||||
public static EnumNamesEnumerator<TEnum> GetNames<TEnum>()
|
||||
where TEnum : enum
|
||||
{
|
||||
return .();
|
||||
}
|
||||
|
||||
private struct EnumFieldsEnumerator<TEnum>
|
||||
where TEnum : enum
|
||||
{
|
||||
TypeInstance mTypeInstance;
|
||||
int32 mIdx;
|
||||
|
||||
public this()
|
||||
{
|
||||
mTypeInstance = typeof(TEnum) as TypeInstance;
|
||||
mIdx = -1;
|
||||
}
|
||||
|
||||
public void Reset() mut
|
||||
{
|
||||
mIdx = -1;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public bool MoveNext() mut
|
||||
{
|
||||
if (mTypeInstance == null)
|
||||
return false;
|
||||
|
||||
TypeInstance.FieldData* fieldData = null;
|
||||
|
||||
repeat
|
||||
{
|
||||
mIdx++;
|
||||
if (mIdx == mTypeInstance.[Friend]mFieldDataCount)
|
||||
return false;
|
||||
fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
|
||||
}
|
||||
while (!fieldData.mFlags.HasFlag(.EnumCase));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public FieldInfo Current
|
||||
{
|
||||
get
|
||||
{
|
||||
var fieldData = &mTypeInstance.[Friend]mFieldDataPtr[mIdx];
|
||||
return FieldInfo(mTypeInstance, fieldData);
|
||||
}
|
||||
}
|
||||
|
||||
public int32 Index
|
||||
{
|
||||
get
|
||||
{
|
||||
return mIdx;
|
||||
}
|
||||
}
|
||||
|
||||
public Result<FieldInfo> GetNext() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public struct EnumEnumerator<TEnum> : EnumFieldsEnumerator<TEnum>, IEnumerator<(StringView name, TEnum value)>
|
||||
where TEnum : enum
|
||||
{
|
||||
public new (StringView name, TEnum value) Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((.)base.Current.[Friend]mFieldData.[Friend]mName, (.)base.Current.[Friend]mFieldData.[Friend]mData);
|
||||
}
|
||||
}
|
||||
|
||||
public new Result<(StringView name, TEnum value)> GetNext() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public struct EnumValuesEnumerator<TEnum> : EnumFieldsEnumerator<TEnum>, IEnumerator<TEnum>
|
||||
where TEnum : enum
|
||||
{
|
||||
public new TEnum Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (.)base.Current.[Friend]mFieldData.[Friend]mData;
|
||||
}
|
||||
}
|
||||
|
||||
public new Result<TEnum> GetNext() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
|
||||
public struct EnumNamesEnumerator<TEnum> : EnumFieldsEnumerator<TEnum>, IEnumerator<StringView>
|
||||
where TEnum : enum
|
||||
{
|
||||
public new StringView Current
|
||||
{
|
||||
get
|
||||
{
|
||||
return (.)base.Current.[Friend]mFieldData.[Friend]mName;
|
||||
}
|
||||
}
|
||||
|
||||
public new Result<StringView> GetNext() mut
|
||||
{
|
||||
if (!MoveNext())
|
||||
return .Err;
|
||||
return Current;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace System.IO
|
|||
{
|
||||
public struct VTable : COM_IUnknown.VTable
|
||||
{
|
||||
public function HResult(COM_IPersistFile* self, Guid* pClassID) GetClassID;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IPersistFile* self, Guid* pClassID) GetClassID;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,11 @@ namespace System.IO
|
|||
|
||||
public struct VTable : COM_IPersist.VTable
|
||||
{
|
||||
public function HResult(COM_IPersistFile* self) IsDirty;
|
||||
public function HResult(COM_IPersistFile* self, char16* pszFileName) Load;
|
||||
public function HResult(COM_IPersistFile* self, char16* pszFileName, Windows.IntBool remember) Save;
|
||||
public function HResult(COM_IPersistFile* self, char16* pszFileName) SaveCompleted;
|
||||
public function HResult(COM_IPersistFile* self, char16* pszName) GetCurFile;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IPersistFile* self) IsDirty;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IPersistFile* self, char16* pszFileName) Load;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IPersistFile* self, char16* pszFileName, Windows.IntBool remember) Save;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IPersistFile* self, char16* pszFileName) SaveCompleted;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IPersistFile* self, char16* pszName) GetCurFile;
|
||||
}
|
||||
public new VTable* VT
|
||||
{
|
||||
|
@ -43,24 +43,24 @@ namespace System.IO
|
|||
|
||||
public struct VTable : Windows.COM_IUnknown.VTable
|
||||
{
|
||||
public function HResult(COM_IShellLink* self, char16* pszFile, int32 cch, Windows.NativeFindData* pfd, uint32 fFlags) GetPath;
|
||||
public function HResult(COM_IShellLink* self, IDLIST** ppidl) GetIDList;
|
||||
public function HResult(COM_IShellLink* self, IDLIST* pidl) SetIDList;
|
||||
public function HResult(COM_IShellLink* self, char16* pszName, int32 cch) GetDescription;
|
||||
public function HResult(COM_IShellLink* self, char16* pszName) SetDescription;
|
||||
public function HResult(COM_IShellLink* self, char16* pszDir, int32 cch) GetWorkingDirectory;
|
||||
public function HResult(COM_IShellLink* self, char16* pszDir) SetWorkingDirectory;
|
||||
public function HResult(COM_IShellLink* self, char16* pszArgs, int32 cch) GetArguments;
|
||||
public function HResult(COM_IShellLink* self, char16* pszArgs) SetArguments;
|
||||
public function HResult(COM_IShellLink* self, uint16 *pwHotkey) GetHotkey;
|
||||
public function HResult(COM_IShellLink* self, uint16 wHotkey) SetHotkey;
|
||||
public function HResult(COM_IShellLink* self, int32 *piShowCmd) GetShowCmd;
|
||||
public function HResult(COM_IShellLink* self, int32 iShowCmd) SetShowCmd;
|
||||
public function HResult(COM_IShellLink* self, char16* pszIconPath, int32 cch, int32 *piIcon) GetIconLocation;
|
||||
public function HResult(COM_IShellLink* self, char16* pszIconPath, int32 iIcon) SetIconLocation;
|
||||
public function HResult(COM_IShellLink* self, char16* pszPathRel, uint32 dwReserved) SetRelativePath;
|
||||
public function HResult(COM_IShellLink* self, Windows.HWnd hwnd, uint32 fFlags) Resolve;
|
||||
public function HResult(COM_IShellLink* self, char16* pszFile) SetPath;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszFile, int32 cch, Windows.NativeFindData* pfd, uint32 fFlags) GetPath;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, IDLIST** ppidl) GetIDList;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, IDLIST* pidl) SetIDList;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszName, int32 cch) GetDescription;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszName) SetDescription;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszDir, int32 cch) GetWorkingDirectory;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszDir) SetWorkingDirectory;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszArgs, int32 cch) GetArguments;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszArgs) SetArguments;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, uint16 *pwHotkey) GetHotkey;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, uint16 wHotkey) SetHotkey;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, int32 *piShowCmd) GetShowCmd;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, int32 iShowCmd) SetShowCmd;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszIconPath, int32 cch, int32 *piIcon) GetIconLocation;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszIconPath, int32 iIcon) SetIconLocation;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszPathRel, uint32 dwReserved) SetRelativePath;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, Windows.HWnd hwnd, uint32 fFlags) Resolve;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellLink* self, char16* pszFile) SetPath;
|
||||
|
||||
}
|
||||
public new VTable* VT
|
||||
|
|
|
@ -118,6 +118,9 @@ namespace System
|
|||
|
||||
public this()
|
||||
{
|
||||
if (Compiler.IsComptime)
|
||||
return;
|
||||
|
||||
#if BF_PLATFORM_WINDOWS
|
||||
bool isWinSrv()
|
||||
{
|
||||
|
|
|
@ -105,7 +105,8 @@ namespace System.Reflection
|
|||
argIdx++;
|
||||
}
|
||||
|
||||
methodInfo.Invoke(targetAttr, params args);
|
||||
if (methodInfo.Invoke(targetAttr, params args) case .Ok(var val))
|
||||
val.Dispose();
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ namespace System
|
|||
{
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
|
||||
mLength = 0;
|
||||
}
|
||||
|
@ -82,7 +82,7 @@ namespace System
|
|||
{
|
||||
let bufferSize = 16 - sizeof(char8*);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
|
||||
mLength = 0;
|
||||
}
|
||||
|
@ -93,7 +93,7 @@ namespace System
|
|||
let count = str.mLength;
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
Internal.MemCpy(Ptr, str.Ptr, count);
|
||||
mLength = count;
|
||||
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
|
||||
|
@ -106,7 +106,7 @@ namespace System
|
|||
let count = str.mLength - offset;
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
let srcPtr = str.Ptr;
|
||||
for (int_strsize i = 0; i < count; i++)
|
||||
|
@ -123,7 +123,7 @@ namespace System
|
|||
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
let srcPtr = str.Ptr;
|
||||
for (int i = 0; i < count; i++)
|
||||
|
@ -137,7 +137,7 @@ namespace System
|
|||
{
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
for (int_strsize i = 0; i < count; i++)
|
||||
ptr[i] = c;
|
||||
|
@ -151,7 +151,7 @@ namespace System
|
|||
let count = Internal.CStrLen(char8Ptr);
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
for (int_strsize i = 0; i < count; i++)
|
||||
ptr[i] = char8Ptr[i];
|
||||
|
@ -164,7 +164,7 @@ namespace System
|
|||
{
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
for (int i = 0; i < count; i++)
|
||||
ptr[i] = char8Ptr[i];
|
||||
|
@ -178,7 +178,7 @@ namespace System
|
|||
let count = UTF16.GetLengthAsUTF8(char16Ptr);
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
|
||||
mLength = 0;
|
||||
UTF16.Decode(char16Ptr, this);
|
||||
|
@ -190,7 +190,7 @@ namespace System
|
|||
let count = UTF16.GetLengthAsUTF8(chars);
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
|
||||
mLength = 0;
|
||||
UTF16.Decode(chars, this);
|
||||
|
@ -202,7 +202,7 @@ namespace System
|
|||
let tryBufferSize = strView.Length - sizeof(char8*);
|
||||
let bufferSize = (tryBufferSize >= 0) ? tryBufferSize : 0;
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
Internal.MemCpy(ptr, strView.Ptr, strView.Length);
|
||||
mAllocSizeAndFlags = (uint_strsize)bufferSize + (int_strsize)sizeof(char8*);
|
||||
|
@ -215,7 +215,7 @@ namespace System
|
|||
let count = strView.Length + (flags.HasFlag(.NullTerminate) ? 1 : 0);
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
Internal.MemCpy(ptr, strView.Ptr, strView.Length);
|
||||
if (flags.HasFlag(.NullTerminate))
|
||||
|
@ -232,7 +232,7 @@ namespace System
|
|||
let count = strView.Length - offset;
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
let srcPtr = strView.Ptr;
|
||||
for (int i = 0; i < count; i++)
|
||||
|
@ -249,7 +249,7 @@ namespace System
|
|||
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
let srcPtr = strView.Ptr;
|
||||
for (int i = 0; i < count; i++)
|
||||
|
@ -263,7 +263,7 @@ namespace System
|
|||
{
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
for (int i = 0; i < count; i++)
|
||||
ptr[i] = chars[i + offset];
|
||||
|
@ -285,7 +285,7 @@ namespace System
|
|||
int count = StrLengths(strs);
|
||||
int bufferSize = (count == 0) ? 0 : (count - 1) & ~(sizeof(char8*) - 1);
|
||||
#unwarn
|
||||
char8* addlPtr = append char8[bufferSize]*;
|
||||
char8* addlPtr = append char8[bufferSize]*(?);
|
||||
let ptr = Ptr;
|
||||
int curIdx = 0;
|
||||
for (var str in strs)
|
||||
|
@ -1965,6 +1965,22 @@ namespace System
|
|||
return EqualsIgnoreCaseHelper(a.Ptr, b.Ptr, a.mLength);
|
||||
return EqualsHelper(a.Ptr, b.Ptr, a.mLength);
|
||||
}
|
||||
|
||||
public bool Equals(StringView str)
|
||||
{
|
||||
if (mLength != str.[Friend]mLength)
|
||||
return false;
|
||||
return EqualsHelper(str.Ptr, mPtr, mLength);
|
||||
}
|
||||
|
||||
public bool Equals(StringView str, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
if (mLength != str.[Friend]mLength)
|
||||
return false;
|
||||
if (comparisonType == StringComparison.OrdinalIgnoreCase)
|
||||
return EqualsIgnoreCaseHelper(str.Ptr, mPtr, mLength);
|
||||
return EqualsHelper(str.Ptr, mPtr, mLength);
|
||||
}
|
||||
|
||||
public bool StartsWith(StringView b, StringComparison comparisonType = StringComparison.Ordinal)
|
||||
{
|
||||
|
@ -2278,6 +2294,36 @@ namespace System
|
|||
TrimStart((.)trimChar);
|
||||
TrimEnd((.)trimChar);
|
||||
}
|
||||
|
||||
public void PadLeft(int totalWidth, char8 paddingChar)
|
||||
{
|
||||
Insert(0, paddingChar, totalWidth - Length);
|
||||
}
|
||||
|
||||
public void PadLeft(int totalWidth, char32 paddingChar)
|
||||
{
|
||||
Insert(0, paddingChar, totalWidth - Length);
|
||||
}
|
||||
|
||||
public void PadLeft(int totalWidth)
|
||||
{
|
||||
Insert(0, ' ', totalWidth - Length);
|
||||
}
|
||||
|
||||
public void PadRight(int totalWidth, char8 paddingChar)
|
||||
{
|
||||
Append(paddingChar, totalWidth - Length);
|
||||
}
|
||||
|
||||
public void PadRight(int totalWidth, char32 paddingChar)
|
||||
{
|
||||
Append(paddingChar, totalWidth - Length);
|
||||
}
|
||||
|
||||
public void PadRight(int totalWidth)
|
||||
{
|
||||
Append(' ', totalWidth - Length);
|
||||
}
|
||||
|
||||
public void Join(StringView sep, IEnumerator<String> enumerable)
|
||||
{
|
||||
|
|
|
@ -1250,7 +1250,8 @@ namespace System.Reflection
|
|||
Const = 0x0040, // Value is compile time constant.
|
||||
SpecialName = 0x0080, // field is special. Name describes how.
|
||||
EnumPayload = 0x0100,
|
||||
EnumDiscriminator = 0x0200
|
||||
EnumDiscriminator = 0x0200,
|
||||
EnumCase = 0x0400
|
||||
}
|
||||
|
||||
public enum MethodFlags : uint16
|
||||
|
|
|
@ -2,7 +2,7 @@ using System.Diagnostics;
|
|||
|
||||
namespace System
|
||||
{
|
||||
struct Variant
|
||||
struct Variant : IDisposable
|
||||
{
|
||||
enum ObjectType
|
||||
{
|
||||
|
@ -472,4 +472,4 @@ namespace System
|
|||
return variant;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,9 +47,9 @@ namespace System
|
|||
|
||||
public struct VTable
|
||||
{
|
||||
public function HResult(COM_IUnknown* self, ref Guid riid, void** result) QueryInterface;
|
||||
public function uint32(COM_IUnknown* self) AddRef;
|
||||
public function uint32(COM_IUnknown* self) Release;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IUnknown* self, ref Guid riid, void** result) QueryInterface;
|
||||
public function [CallingConvention(.Stdcall)] uint32(COM_IUnknown* self) AddRef;
|
||||
public function [CallingConvention(.Stdcall)] uint32(COM_IUnknown* self) Release;
|
||||
}
|
||||
|
||||
public enum HResult : int32
|
||||
|
@ -1124,14 +1124,13 @@ namespace System
|
|||
|
||||
public struct VTable : Windows.COM_IUnknown.VTable
|
||||
{
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFileOk;
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* psiFolder) OnFolderChanging;
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFolderChange;
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnSelectionChange;
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, FDE_SHAREVIOLATION_RESPONSE* pResponse) OnShareViolation;
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnTypeChange;
|
||||
public function HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* shellItem, FDE_OVERWRITE_RESPONSE* response) OnOverwrite;
|
||||
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFileOk;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* psiFolder) OnFolderChanging;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnFolderChange;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnSelectionChange;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, FDE_SHAREVIOLATION_RESPONSE* pResponse) OnShareViolation;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog) OnTypeChange;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialogEvents* self, COM_IFileDialog* fileDialog, COM_IShellItem* shellItem, FDE_OVERWRITE_RESPONSE* response) OnOverwrite;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1154,12 +1153,11 @@ namespace System
|
|||
|
||||
public struct VTable : Windows.COM_IUnknown.VTable
|
||||
{
|
||||
public function HResult(COM_IShellItem* self, void* pbc, ref Guid bhid, ref Guid riid, void** ppv) BindToHandler;
|
||||
public function HResult(COM_IShellItem* self, out COM_IShellItem* ppsi) GetParent;
|
||||
public function HResult(COM_IShellItem* self, SIGDN sigdnName, out char16* ppszName) GetDisplayName;
|
||||
public function HResult(COM_IShellItem* self, uint sfgaoMask, out uint psfgaoAttribs) GetAttributes;
|
||||
public function HResult(COM_IShellItem* self, COM_IShellItem* psi, uint32 hint, out int32 piOrder) Compare;
|
||||
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItem* self, void* pbc, ref Guid bhid, ref Guid riid, void** ppv) BindToHandler;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItem* self, out COM_IShellItem* ppsi) GetParent;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItem* self, SIGDN sigdnName, out char16* ppszName) GetDisplayName;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItem* self, uint sfgaoMask, out uint psfgaoAttribs) GetAttributes;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItem* self, COM_IShellItem* psi, uint32 hint, out int32 piOrder) Compare;
|
||||
}
|
||||
public new VTable* VT
|
||||
{
|
||||
|
@ -1207,13 +1205,13 @@ namespace System
|
|||
|
||||
public struct VTable : Windows.COM_IUnknown.VTable
|
||||
{
|
||||
public function HResult(COM_IShellItemArray* self, void* pbc, ref Guid rbhid, ref Guid riid, out void* ppvOut) BindToHandler;
|
||||
public function HResult(COM_IShellItemArray* self, GETPROPERTYSTOREFLAGS flags, ref Guid riid, out void* ppv) GetPropertyStore;
|
||||
public function HResult(COM_IShellItemArray* self, ref PROPERTYKEY keyType, ref Guid riid, out void* ppv) GetPropertyDescriptionList;
|
||||
public function HResult(COM_IShellItemArray* self, SIATTRIBFLAGS dwAttribFlags, uint32 sfgaoMask, out uint32 psfgaoAttribs) GetAttributes;
|
||||
public function HResult(COM_IShellItemArray* self, out uint32 pdwNumItems) GetCount;
|
||||
public function HResult(COM_IShellItemArray* self, uint32 dwIndex, out COM_IShellItem* ppsi) GetItemAt;
|
||||
public function HResult(COM_IShellItemArray* self, out void* ppenumShellItems) EnumItems;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, void* pbc, ref Guid rbhid, ref Guid riid, out void* ppvOut) BindToHandler;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, GETPROPERTYSTOREFLAGS flags, ref Guid riid, out void* ppv) GetPropertyStore;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, ref PROPERTYKEY keyType, ref Guid riid, out void* ppv) GetPropertyDescriptionList;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, SIATTRIBFLAGS dwAttribFlags, uint32 sfgaoMask, out uint32 psfgaoAttribs) GetAttributes;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, out uint32 pdwNumItems) GetCount;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, uint32 dwIndex, out COM_IShellItem* ppsi) GetItemAt;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IShellItemArray* self, out void* ppenumShellItems) EnumItems;
|
||||
}
|
||||
public new VTable* VT
|
||||
{
|
||||
|
@ -1268,30 +1266,30 @@ namespace System
|
|||
|
||||
public struct VTable : Windows.COM_IUnknown.VTable
|
||||
{
|
||||
public function HResult(COM_IFileDialog* self, Windows.HWnd parent) Show;
|
||||
public function HResult(COM_IFileDialog* self, uint cFileTypes, COMDLG_FILTERSPEC* rgFilterSpec) SetFileTypes;
|
||||
public function HResult(COM_IFileDialog* self, uint iFileType) SetFileTypeIndex;
|
||||
public function HResult(COM_IFileDialog* self, out uint piFileType) GetFileTypeIndex;
|
||||
public function HResult(COM_IFileDialog* self, COM_IFileDialogEvents* pfde, out uint pdwCookie) Advise;
|
||||
public function HResult(COM_IFileDialog* self, uint dwCookie) Unadvise;
|
||||
public function HResult(COM_IFileDialog* self, FOS fos) SetOptions;
|
||||
public function HResult(COM_IFileDialog* self, out FOS pfos) GetOptions;
|
||||
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetDefaultFolder;
|
||||
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetFolder;
|
||||
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetFolder;
|
||||
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetCurrentSelection;
|
||||
public function HResult(COM_IFileDialog* self, char16* pszName) SetFileName;
|
||||
public function HResult(COM_IFileDialog* self, out char16* pszName) GetFileName;
|
||||
public function HResult(COM_IFileDialog* self, char16* pszTitle) SetTitle;
|
||||
public function HResult(COM_IFileDialog* self, char16* pszText) SetOkButtonLabel;
|
||||
public function HResult(COM_IFileDialog* self, char16* pszLabel) SetFileNameLabel;
|
||||
public function HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetResult;
|
||||
public function HResult(COM_IFileDialog* self, COM_IShellItem* psi, FDAP fdap) AddPlace;
|
||||
public function HResult(COM_IFileDialog* self, char16* pszDefaultExtension) SetDefaultExtension;
|
||||
public function HResult(COM_IFileDialog* self, int hr) Close;
|
||||
public function HResult(COM_IFileDialog* self, ref Guid guid) SetClientGuid;
|
||||
public function HResult(COM_IFileDialog* self) ClearClientData;
|
||||
public function HResult(COM_IFileDialog* self, void* pFilter) SetFilter;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, Windows.HWnd parent) Show;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, uint cFileTypes, COMDLG_FILTERSPEC* rgFilterSpec) SetFileTypes;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, uint iFileType) SetFileTypeIndex;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, out uint piFileType) GetFileTypeIndex;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, COM_IFileDialogEvents* pfde, out uint pdwCookie) Advise;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, uint dwCookie) Unadvise;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, FOS fos) SetOptions;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, out FOS pfos) GetOptions;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetDefaultFolder;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, COM_IShellItem* psi) SetFolder;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetFolder;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetCurrentSelection;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, char16* pszName) SetFileName;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, out char16* pszName) GetFileName;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, char16* pszTitle) SetTitle;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, char16* pszText) SetOkButtonLabel;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, char16* pszLabel) SetFileNameLabel;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, out COM_IShellItem* ppsi) GetResult;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, COM_IShellItem* psi, FDAP fdap) AddPlace;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, char16* pszDefaultExtension) SetDefaultExtension;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, int hr) Close;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, ref Guid guid) SetClientGuid;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self) ClearClientData;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileDialog* self, void* pFilter) SetFilter;
|
||||
}
|
||||
public new VTable* VT
|
||||
{
|
||||
|
@ -1314,8 +1312,8 @@ namespace System
|
|||
|
||||
public struct VTable : COM_IFileDialog.VTable
|
||||
{
|
||||
public function HResult(COM_IFileOpenDialog* self, out COM_IShellItemArray* ppenum) GetResults;
|
||||
public function HResult(COM_IFileOpenDialog* self, out COM_IShellItemArray* ppsai) GetSelectedItems;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileOpenDialog* self, out COM_IShellItemArray* ppenum) GetResults;
|
||||
public function [CallingConvention(.Stdcall)] HResult(COM_IFileOpenDialog* self, out COM_IShellItemArray* ppsai) GetSelectedItems;
|
||||
}
|
||||
public new VTable* VT
|
||||
{
|
||||
|
|
|
@ -505,7 +505,7 @@ namespace BeefPerf
|
|||
subMenu = root.AddMenuItem("&Debug");
|
||||
subMenu.AddMenuItem("GC Collect", null, new (menu) =>
|
||||
{
|
||||
if (Profiler.StartSampling() case .Ok(let id))
|
||||
if (Profiler.StartSampling() case .Ok(var id))
|
||||
{
|
||||
GC.Collect();
|
||||
id.Dispose();
|
||||
|
|
|
@ -2909,6 +2909,12 @@ BFP_EXPORT intptr BFP_CALLTYPE BfpFile_Read(BfpFile* file, void* buffer, intptr
|
|||
//TODO: this doesn't set file stream location. It only works for streams like pipes, sockets, etc
|
||||
if (::ReadFileEx(file->mHandle, buffer, (uint32)size, &overlapped, OverlappedReadComplete))
|
||||
{
|
||||
if (file->mAsyncData == NULL)
|
||||
{
|
||||
OUTRESULT(BfpFileResult_InvalidParameter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!file->mAsyncData->WaitAndResetEvent(timeoutMS))
|
||||
{
|
||||
::CancelIoEx(file->mHandle, &overlapped);
|
||||
|
|
|
@ -622,7 +622,17 @@ public:
|
|||
str.mLength = (int_strsize)strlen(charPtr);
|
||||
str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
|
||||
return str;
|
||||
}
|
||||
}
|
||||
|
||||
static StringImpl MakeRef(const char* charPtr, intptr length)
|
||||
{
|
||||
StringImpl str;
|
||||
// This is just a ref - called when we pass a literal to a method (for example)
|
||||
str.mPtr = (char*)charPtr;
|
||||
str.mLength = (int_strsize)length;
|
||||
str.mAllocSizeAndFlags = str.mLength | StrPtrFlag;
|
||||
return str;
|
||||
}
|
||||
|
||||
static StringImpl MakeRef(const StringView& strView)
|
||||
{
|
||||
|
|
|
@ -9,7 +9,7 @@ namespace IDE
|
|||
{
|
||||
public KeyCode mKeyCode;
|
||||
public KeyFlags mKeyFlags;
|
||||
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return (int)mKeyCode | (int)mKeyFlags << 16;
|
||||
|
@ -121,10 +121,21 @@ namespace IDE
|
|||
class CommandMap : IDECommandBase
|
||||
{
|
||||
public Dictionary<KeyState, IDECommandBase> mMap = new .() ~ delete _;
|
||||
public List<IDECommandBase> mFailValues ~ delete _;
|
||||
|
||||
public List<IDECommandBase> FailValues
|
||||
{
|
||||
get
|
||||
{
|
||||
if (mFailValues == null)
|
||||
mFailValues = new .();
|
||||
return mFailValues;
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
for (let val in mMap.Values)
|
||||
void Release(IDECommandBase val)
|
||||
{
|
||||
if (var cmdMap = val as CommandMap)
|
||||
delete cmdMap;
|
||||
|
@ -136,6 +147,15 @@ namespace IDE
|
|||
ideCommand.mNext = null;
|
||||
}
|
||||
}
|
||||
|
||||
for (let val in mMap.Values)
|
||||
Release(val);
|
||||
if (mFailValues != null)
|
||||
{
|
||||
for (var val in mFailValues)
|
||||
Release(val);
|
||||
mFailValues.Clear();
|
||||
}
|
||||
mMap.Clear();
|
||||
}
|
||||
|
||||
|
@ -194,7 +214,9 @@ namespace IDE
|
|||
Add("Close Document", new () => { gApp.[Friend]TryCloseCurrentDocument(); });
|
||||
Add("Close Panel", new () => { gApp.[Friend]TryCloseCurrentPanel(); });
|
||||
Add("Close Workspace", new => gApp.[Friend]Cmd_CloseWorkspaceAndSetupNew);
|
||||
Add("Comment Selection", new => gApp.[Friend]CommentSelection);
|
||||
Add("Comment Block", new => gApp.[Friend]CommentBlock, .Editor);
|
||||
Add("Comment Lines", new => gApp.[Friend]CommentLines, .Editor);
|
||||
Add("Comment Toggle", new => gApp.[Friend]CommentToggle, .Editor);
|
||||
Add("Compile File", new => gApp.Cmd_CompileFile);
|
||||
Add("Debug All Tests", new () => { gApp.[Friend]RunTests(true, true); });
|
||||
Add("Debug Normal Tests", new () => { gApp.[Friend]RunTests(false, true); });
|
||||
|
@ -251,6 +273,7 @@ namespace IDE
|
|||
Add("Run Normal Tests", new () => { gApp.[Friend]RunTests(false, false); });
|
||||
Add("Run To Cursor", new => gApp.[Friend]RunToCursor);
|
||||
Add("Run Without Compiling", new => gApp.[Friend]RunWithoutCompiling);
|
||||
Add("Safe Mode Toggle", new () => { gApp.SafeModeToggle(); });
|
||||
Add("Save All", new () => { gApp.SaveAll(); });
|
||||
Add("Save As", new () => { gApp.SaveAs(); });
|
||||
Add("Save File", new => gApp.SaveFile);
|
||||
|
|
|
@ -76,6 +76,9 @@ namespace IDE.Compiler
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern int32 BfCompiler_GetCurConstEvalExecuteId(void* bfCompiler);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern bool BfCompiler_GetLastHadComptimeRebuilds(void* bfCompiler);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern void BfCompiler_Delete(void* bfCompiler);
|
||||
|
||||
|
@ -834,5 +837,10 @@ namespace IDE.Compiler
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool GetLastHadComptimeRebuilds()
|
||||
{
|
||||
return BfCompiler_GetLastHadComptimeRebuilds(mNativeBfCompiler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,8 +78,9 @@ namespace IDE.Compiler
|
|||
public bool mCancelled;
|
||||
public int32 mTextVersion = -1;
|
||||
public bool mIsUserRequested;
|
||||
|
||||
public bool mDoFuzzyAutoComplete;
|
||||
public Stopwatch mStopwatch ~ delete _;
|
||||
public ProfileInstance mProfileInstance ~ _.Dispose();
|
||||
}
|
||||
|
||||
public class BfParser : ILeakIdentifiable
|
||||
|
@ -122,7 +123,7 @@ namespace IDE.Compiler
|
|||
static extern bool BfParser_Reduce(void* bfParser, void* bfPassInstance);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern char8* BfParser_Format(void* bfParser, int32 formatEnd, int32 formatStart, out int32* outCharMapping);
|
||||
static extern char8* BfParser_Format(void* bfParser, int32 formatEnd, int32 formatStart, out int32* outCharMapping, int32 maxCol);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern char8* BfParser_GetDebugExpressionAt(void* bfParser, int32 cursorIdx);
|
||||
|
@ -209,8 +210,9 @@ namespace IDE.Compiler
|
|||
public void Reformat(int formatStart, int formatEnd, out int32[] char8Mapping, String str)
|
||||
{
|
||||
int32* char8MappingPtr;
|
||||
var stringPtr = BfParser_Format(mNativeBfParser, (int32)formatStart, (int32)formatEnd, out char8MappingPtr);
|
||||
str.Append(stringPtr);
|
||||
var maxCol = gApp.mSettings.mEditorSettings.mWrapCommentsAt;
|
||||
var stringPtr = BfParser_Format(mNativeBfParser, (int32)formatStart, (int32)formatEnd, out char8MappingPtr, maxCol);
|
||||
str.Append(stringPtr);
|
||||
|
||||
char8Mapping = new int32[str.Length];
|
||||
for (int32 i = 0; i < char8Mapping.Count; i++)
|
||||
|
|
|
@ -51,7 +51,7 @@ namespace IDE.Compiler
|
|||
static extern char8* BfSystem_GetNamespaceSearch(void* bfSystem, char8* typeName, void* project);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern void* BfSystem_CreateProject(void* bfSystem, char8* projectName);
|
||||
static extern void* BfSystem_CreateProject(void* bfSystem, char8* projectName, char8* projectDir);
|
||||
|
||||
[CallingConvention(.Stdcall), CLink]
|
||||
static extern void BfSystem_ClearTypeOptions(void* bfSystem);
|
||||
|
@ -142,7 +142,7 @@ namespace IDE.Compiler
|
|||
{
|
||||
using (mMonitor.Enter())
|
||||
{
|
||||
var bfProject = CreateProject(project.mProjectName);
|
||||
var bfProject = CreateProject(project.mProjectName, project.mProjectDir);
|
||||
mProjectMap[project] = bfProject;
|
||||
}
|
||||
}
|
||||
|
@ -188,10 +188,10 @@ namespace IDE.Compiler
|
|||
outNamespaceSearch.Append(namespaceSearch);
|
||||
}
|
||||
|
||||
public BfProject CreateProject(String projectName)
|
||||
public BfProject CreateProject(String projectName, String projectDir)
|
||||
{
|
||||
BfProject project = new BfProject();
|
||||
project.mNativeBfProject = BfSystem_CreateProject(mNativeBfSystem, projectName);
|
||||
project.mNativeBfProject = BfSystem_CreateProject(mNativeBfSystem, projectName, projectDir);
|
||||
return project;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,6 +169,8 @@ namespace IDE
|
|||
public bool mLastCompileHadMessages;
|
||||
public bool mPauseOnExit;
|
||||
public bool mDbgDelayedAutocomplete;
|
||||
public bool mDbgTimeAutocomplete;
|
||||
public bool mDbgPerfAutocomplete;
|
||||
public BeefConfig mBeefConfig = new BeefConfig() ~ delete _;
|
||||
public List<String> mDeferredFails = new .() ~ DeleteContainerAndItems!(_);
|
||||
public String mInitialCWD = new .() ~ delete _;
|
||||
|
@ -2314,6 +2316,11 @@ namespace IDE
|
|||
widget.RemoveSelf();
|
||||
}
|
||||
|
||||
WithSourceViewPanels(scope (sourceViewPanel) =>
|
||||
{
|
||||
sourceViewPanel.Dispose();
|
||||
});
|
||||
|
||||
if (!mRunningTestScript)
|
||||
{
|
||||
mActiveDocumentsTabbedView = null;
|
||||
|
@ -2425,11 +2432,27 @@ namespace IDE
|
|||
}
|
||||
|
||||
[IDECommand]
|
||||
void CommentSelection()
|
||||
void CommentBlock()
|
||||
{
|
||||
var sewc = GetActiveSourceEditWidgetContent();
|
||||
if (sewc != null)
|
||||
sewc.ToggleComment(true);
|
||||
sewc.CommentBlock();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CommentLines()
|
||||
{
|
||||
var sewc = GetActiveSourceEditWidgetContent();
|
||||
if (sewc != null)
|
||||
sewc.CommentLines();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
void CommentToggle()
|
||||
{
|
||||
var sewc = GetActiveSourceEditWidgetContent();
|
||||
if (sewc != null)
|
||||
sewc.ToggleComment();
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
|
@ -3936,7 +3959,7 @@ namespace IDE
|
|||
if (sourceViewPanel != null)
|
||||
{
|
||||
if (sourceViewPanel.mEditWidget.mEditWidgetContent.GetCursorLineChar(var line, var lineChar))
|
||||
sourceViewPanel.UpdateMouseover(true, true, line, lineChar);
|
||||
sourceViewPanel.UpdateMouseover(true, true, line, lineChar, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4874,6 +4897,14 @@ namespace IDE
|
|||
CreateDefaultLayout(false);
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
public void SafeModeToggle()
|
||||
{
|
||||
mSafeMode = !mSafeMode;
|
||||
mNoResolve = mSafeMode;
|
||||
mWantsBeefClean = true;
|
||||
}
|
||||
|
||||
[IDECommand]
|
||||
public void ShowKeyboardShortcuts()
|
||||
{
|
||||
|
@ -5240,6 +5271,11 @@ namespace IDE
|
|||
menu.SetDisabled(!mDebugger.mIsRunning);
|
||||
}
|
||||
|
||||
public void UpdateMenuItem_DebugOrTestRunning(IMenu menu)
|
||||
{
|
||||
menu.SetDisabled(!mDebugger.mIsRunning && (mTestManager == null));
|
||||
}
|
||||
|
||||
public void UpdateMenuItem_DebugStopped_HasWorkspace(IMenu menu)
|
||||
{
|
||||
menu.SetDisabled(mDebugger.mIsRunning || !mWorkspace.IsInitialized);
|
||||
|
@ -5310,6 +5346,7 @@ namespace IDE
|
|||
AddMenuItem(prefMenu, "&Settings", "Settings");
|
||||
AddMenuItem(prefMenu, "Reload Settings", "Reload Settings");
|
||||
AddMenuItem(prefMenu, "Reset UI", "Reset UI");
|
||||
AddMenuItem(prefMenu, "Safe Mode", "Safe Mode Toggle", new (menu) => { menu.SetCheckState(mSafeMode ? 1 : 0); }, null, true, mSafeMode ? 1 : 0);
|
||||
AddMenuItem(subMenu, "Close Workspace", "Close Workspace", new => UpdateMenuItem_HasWorkspace);
|
||||
AddMenuItem(subMenu, "E&xit", "Exit");
|
||||
|
||||
|
@ -5386,7 +5423,9 @@ namespace IDE
|
|||
advancedEditMenu.AddMenuItem(null);
|
||||
AddMenuItem(advancedEditMenu, "Make Uppercase", "Make Uppercase");
|
||||
AddMenuItem(advancedEditMenu, "Make Lowercase", "Make Lowercase");
|
||||
AddMenuItem(advancedEditMenu, "Comment Selection", "Comment Selection");
|
||||
AddMenuItem(advancedEditMenu, "Comment Block", "Comment Block");
|
||||
AddMenuItem(advancedEditMenu, "Comment Lines", "Comment Lines");
|
||||
AddMenuItem(advancedEditMenu, "Comment Toggle", "Comment Toggle");
|
||||
AddMenuItem(advancedEditMenu, "Uncomment Selection", "Uncomment Selection");
|
||||
AddMenuItem(advancedEditMenu, "Reformat Document", "Reformat Document");
|
||||
mViewWhiteSpace.mMenu = AddMenuItem(advancedEditMenu, "View White Space", "View White Space", null, null, true, mViewWhiteSpace.Bool ? 1 : 0);
|
||||
|
@ -5397,6 +5436,8 @@ namespace IDE
|
|||
var internalEditMenu = subMenu.AddMenuItem("Internal");
|
||||
internalEditMenu.AddMenuItem("Hilight Cursor References", null, new (menu) => { ToggleCheck(menu, ref gApp.mSettings.mEditorSettings.mHiliteCursorReferences); }, null, null, true, gApp.mSettings.mEditorSettings.mHiliteCursorReferences ? 1 : 0);
|
||||
internalEditMenu.AddMenuItem("Delayed Autocomplete", null, new (menu) => { ToggleCheck(menu, ref gApp.mDbgDelayedAutocomplete); }, null, null, true, gApp.mDbgDelayedAutocomplete ? 1 : 0);
|
||||
internalEditMenu.AddMenuItem("Time Autocomplete", null, new (menu) => { ToggleCheck(menu, ref gApp.mDbgTimeAutocomplete); }, null, null, true, gApp.mDbgTimeAutocomplete ? 1 : 0);
|
||||
internalEditMenu.AddMenuItem("Perf Autocomplete", null, new (menu) => { ToggleCheck(menu, ref gApp.mDbgPerfAutocomplete); }, null, null, true, gApp.mDbgPerfAutocomplete ? 1 : 0);
|
||||
}
|
||||
|
||||
//////////
|
||||
|
@ -5456,7 +5497,7 @@ namespace IDE
|
|||
AddMenuItem(subMenu, "Start With&out Compiling", "Start Without Compiling", new => UpdateMenuItem_DebugStopped_HasWorkspace);
|
||||
AddMenuItem(subMenu, "&Launch Process...", "Launch Process", new => UpdateMenuItem_DebugStopped);
|
||||
AddMenuItem(subMenu, "&Attach to Process...", "Attach to Process", new => UpdateMenuItem_DebugStopped);
|
||||
AddMenuItem(subMenu, "&Stop Debugging", "Stop Debugging", new => UpdateMenuItem_DebugRunning);
|
||||
AddMenuItem(subMenu, "&Stop Debugging", "Stop Debugging", new => UpdateMenuItem_DebugOrTestRunning);
|
||||
AddMenuItem(subMenu, "Break All", "Break All", new => UpdateMenuItem_DebugNotPaused);
|
||||
AddMenuItem(subMenu, "Remove All Breakpoints", "Remove All Breakpoints");
|
||||
AddMenuItem(subMenu, "Show &Disassembly", "Show Disassembly");
|
||||
|
@ -5712,14 +5753,20 @@ namespace IDE
|
|||
{
|
||||
let sewc = editWidget.mEditWidgetContent as SourceEditWidgetContent;
|
||||
if (sewc != null)
|
||||
return sewc;
|
||||
{
|
||||
if (sewc.mEditWidget.mHasFocus)
|
||||
return sewc;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var activeTextPanel = GetActivePanel() as TextPanel;
|
||||
if (activeTextPanel != null)
|
||||
{
|
||||
return activeTextPanel.EditWidget.mEditWidgetContent as SourceEditWidgetContent;
|
||||
let sewc = activeTextPanel.EditWidget.mEditWidgetContent as SourceEditWidgetContent;
|
||||
if ((sewc != null) && (sewc.mEditWidget.mHasFocus))
|
||||
return sewc;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -9167,6 +9214,9 @@ namespace IDE
|
|||
bool doCompile = false;
|
||||
if (lastCompileHadMessages)
|
||||
doCompile = true;
|
||||
|
||||
bool needsComptime = bfCompiler.GetLastHadComptimeRebuilds();
|
||||
|
||||
if ((!workspaceOptions.mIncrementalBuild) && (!lastCompileHadMessages))
|
||||
{
|
||||
tryQueueFiles = false;
|
||||
|
@ -9177,6 +9227,9 @@ namespace IDE
|
|||
}
|
||||
}
|
||||
|
||||
if (needsComptime)
|
||||
tryQueueFiles = true;
|
||||
|
||||
if (hotProject != null)
|
||||
{
|
||||
mWorkspace.mHadHotCompileSinceLastFullCompile = true;
|
||||
|
@ -9210,6 +9263,9 @@ namespace IDE
|
|||
}
|
||||
}
|
||||
|
||||
if (needsComptime)
|
||||
doCompile = true;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
bfCompiler.QueueDeletePassInstance(passInstance);
|
||||
|
@ -10748,7 +10804,7 @@ namespace IDE
|
|||
Beef requires the Microsoft C++ build tools for Visual Studio 2013 or later, but they don't seem to be installed.
|
||||
|
||||
Install just Microsoft Visual C++ Build Tools or the entire Visual Studio suite from:
|
||||
https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019
|
||||
https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022
|
||||
""";
|
||||
|
||||
#if CLI
|
||||
|
@ -10759,7 +10815,7 @@ namespace IDE
|
|||
dlg.AddOkCancelButtons(new (dlg) =>
|
||||
{
|
||||
ProcessStartInfo psi = scope ProcessStartInfo();
|
||||
psi.SetFileName("https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019");
|
||||
psi.SetFileName("https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2022");
|
||||
psi.UseShellExecute = true;
|
||||
psi.SetVerb("Open");
|
||||
var process = scope SpawnedProcess();
|
||||
|
@ -12040,11 +12096,11 @@ namespace IDE
|
|||
if (mErrorsPanel != null)
|
||||
mErrorsPanel.ClearParserErrors(null);
|
||||
|
||||
delete mBfResolveCompiler;
|
||||
delete mBfResolveSystem;
|
||||
delete mBfResolveHelper;
|
||||
delete mBfBuildCompiler;
|
||||
delete mBfBuildSystem;
|
||||
DeleteAndNullify!(mBfResolveCompiler);
|
||||
DeleteAndNullify!(mBfResolveSystem);
|
||||
DeleteAndNullify!(mBfResolveHelper);
|
||||
DeleteAndNullify!(mBfBuildCompiler);
|
||||
DeleteAndNullify!(mBfBuildSystem);
|
||||
|
||||
///
|
||||
mDebugger.FullReportMemory();
|
||||
|
@ -13698,7 +13754,6 @@ namespace IDE
|
|||
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||
public static extern bool MessageBeep(MessageBeepType type);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
static
|
||||
|
|
|
@ -626,6 +626,7 @@ namespace IDE
|
|||
public FileRecoveryKind mEnableFileRecovery = .Yes;
|
||||
public bool mFormatOnSave = false;
|
||||
public bool mSyncWithWorkspacePanel = false;
|
||||
public int32 mWrapCommentsAt = 0;
|
||||
|
||||
public void Serialize(StructuredData sd)
|
||||
{
|
||||
|
@ -652,6 +653,7 @@ namespace IDE
|
|||
sd.Add("EnableFileRecovery", mEnableFileRecovery);
|
||||
sd.Add("FormatOnSave", mFormatOnSave);
|
||||
sd.Add("SyncWithWorkspacePanel", mSyncWithWorkspacePanel);
|
||||
sd.Add("WrapCommentsAt", mWrapCommentsAt);
|
||||
}
|
||||
|
||||
public void Deserialize(StructuredData sd)
|
||||
|
@ -682,6 +684,7 @@ namespace IDE
|
|||
sd.GetEnum<FileRecoveryKind>("EnableFileRecovery", ref mEnableFileRecovery);
|
||||
sd.Get("FormatOnSave", ref mFormatOnSave);
|
||||
sd.Get("SyncWithWorkspacePanel", ref mSyncWithWorkspacePanel);
|
||||
sd.Get("WrapCommentsAt", ref mWrapCommentsAt);
|
||||
}
|
||||
|
||||
public void SetDefaults()
|
||||
|
@ -756,7 +759,9 @@ namespace IDE
|
|||
Add("Cancel Build", "Ctrl+Break");
|
||||
Add("Close Document", "Ctrl+W");
|
||||
Add("Compile File", "Ctrl+F7");
|
||||
Add("Comment Selection", "Ctrl+K, Ctrl+C");
|
||||
Add("Comment Block", "Ctrl+K, Ctrl+C");
|
||||
Add("Comment Lines", "Ctrl+K, Ctrl+/");
|
||||
Add("Comment Toggle", "Ctrl+K, Ctrl+T");
|
||||
Add("Duplicate Line", "Ctrl+D");
|
||||
Add("Find Class", "Alt+Shift+L");
|
||||
Add("Find in Document", "Ctrl+F");
|
||||
|
@ -892,7 +897,10 @@ namespace IDE
|
|||
{
|
||||
curCmdMap = (*valuePtr) as CommandMap;
|
||||
if (curCmdMap == null)
|
||||
{
|
||||
curCmdMap.FailValues.Add(ideCommand);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -905,7 +913,10 @@ namespace IDE
|
|||
if (checkPrevCmd.mContextFlags == ideCommand.mContextFlags)
|
||||
gApp.OutputLineSmart("ERROR: The same key is bound for '{0}' and '{1}'", checkPrevCmd.mName, entry.mCommand);
|
||||
if (checkPrevCmd.mNext == null)
|
||||
{
|
||||
curCmdMap.FailValues.Add(ideCommand);
|
||||
break;
|
||||
}
|
||||
checkPrevCmd = checkPrevCmd.mNext;
|
||||
}
|
||||
checkPrevCmd.mNext = ideCommand;
|
||||
|
|
|
@ -1165,6 +1165,7 @@ namespace IDE.ui
|
|||
}
|
||||
}
|
||||
|
||||
public Stopwatch mStopwatch ~ delete _;
|
||||
public EditWidget mTargetEditWidget;
|
||||
public Event<Action> mOnAutoCompleteInserted ~ _.Dispose();
|
||||
public Event<Action> mOnClosed ~ _.Dispose();
|
||||
|
|
|
@ -136,17 +136,15 @@ namespace IDE.ui
|
|||
ClearAndDeleteItems(mResolveErrors);
|
||||
mResolveErrors.Capacity = mResolveErrors.Count;
|
||||
}
|
||||
|
||||
var bfl = scope:: List<BfPassInstance.BfError>();
|
||||
for (int32 errorIdx = 0; errorIdx < errorCount; errorIdx++)
|
||||
{
|
||||
BfPassInstance.BfError bfError = new BfPassInstance.BfError();
|
||||
passInstance.GetErrorData(errorIdx, bfError, true);
|
||||
if (bfError.mFilePath == null)
|
||||
bfError.mFilePath = new String(""); //for sort below
|
||||
|
||||
if (bfError.mIsWarning)
|
||||
mWarningCount++;
|
||||
else
|
||||
mErrorCount++;
|
||||
|
||||
bfl.Add(bfError);
|
||||
for (int32 moreInfoIdx < bfError.mMoreInfoCount)
|
||||
{
|
||||
BfPassInstance.BfError moreInfo = new BfPassInstance.BfError();
|
||||
|
@ -155,12 +153,26 @@ namespace IDE.ui
|
|||
bfError.mMoreInfo = new List<BfPassInstance.BfError>();
|
||||
bfError.mMoreInfo.Add(moreInfo);
|
||||
}
|
||||
}
|
||||
|
||||
function int(int lhs, int rhs) ascLambda = (lhs, rhs) => lhs <=> rhs;
|
||||
bfl.Sort(scope (lhs, rhs) => ascLambda(lhs.mFilePath.GetHashCode()+lhs.mSrcStart, rhs.mFilePath.GetHashCode()+rhs.mSrcStart));
|
||||
|
||||
for (int32 errorIdx = 0; errorIdx < bfl.Count; errorIdx++)
|
||||
{
|
||||
var bfError = bfl[errorIdx];
|
||||
|
||||
if (bfError.mIsWarning)
|
||||
{
|
||||
mWarningCount++;
|
||||
}
|
||||
else
|
||||
mErrorCount++;
|
||||
|
||||
if (passKind == .Parse)
|
||||
{
|
||||
if (bfError.mFilePath == null)
|
||||
bfError.mFilePath = new String("");
|
||||
|
||||
bool added = mParseErrors.TryAdd(bfError.mFilePath, var keyPtr, var valuePtr);
|
||||
if (added)
|
||||
{
|
||||
|
@ -170,7 +182,7 @@ namespace IDE.ui
|
|||
(*valuePtr).Add(bfError);
|
||||
}
|
||||
else
|
||||
mResolveErrors.Add(bfError);
|
||||
mResolveErrors.Add(bfError);
|
||||
|
||||
mDataId++;
|
||||
}
|
||||
|
@ -354,7 +366,7 @@ namespace IDE.ui
|
|||
public override void Update()
|
||||
{
|
||||
base.Update();
|
||||
|
||||
|
||||
if (!mVisible)
|
||||
{
|
||||
// Very dirty
|
||||
|
@ -369,7 +381,8 @@ namespace IDE.ui
|
|||
else
|
||||
mDirtyTicks++;
|
||||
|
||||
ProcessErrors();
|
||||
if(mDirtyTicks==0)
|
||||
ProcessErrors();
|
||||
}
|
||||
|
||||
public void SetNeedsResolveAll()
|
||||
|
@ -379,7 +392,8 @@ namespace IDE.ui
|
|||
|
||||
public void ShowErrorNext()
|
||||
{
|
||||
ProcessErrors();
|
||||
if(mDirtyTicks==0)
|
||||
ProcessErrors();
|
||||
|
||||
bool foundFocused = false;
|
||||
let root = mErrorLV.GetRoot();
|
||||
|
|
|
@ -139,7 +139,8 @@ namespace IDE.ui
|
|||
mOutputWidget.SetText("");
|
||||
for (var widgetEntry in mInlineWidgets)
|
||||
{
|
||||
widgetEntry.mWidget.RemoveSelf();
|
||||
if (widgetEntry.mWidget.mParent != null)
|
||||
widgetEntry.mWidget.RemoveSelf();
|
||||
delete widgetEntry.mWidget;
|
||||
}
|
||||
mInlineWidgets.Clear();
|
||||
|
|
|
@ -293,6 +293,10 @@ namespace IDE.ui
|
|||
}
|
||||
}
|
||||
|
||||
struct ThreadEntry : this(int32 mThreadId, int32 mCPUUsage, StringView mName)
|
||||
{
|
||||
}
|
||||
|
||||
void PopulateThreadList(Menu menu)
|
||||
{
|
||||
if (mProfiler == null)
|
||||
|
@ -307,6 +311,7 @@ namespace IDE.ui
|
|||
var threadListStr = scope String();
|
||||
mProfiler.GetThreadList(threadListStr);
|
||||
|
||||
List<ThreadEntry> entries = scope .();
|
||||
for (var entry in threadListStr.Split('\n'))
|
||||
{
|
||||
if (entry.Length == 0)
|
||||
|
@ -314,20 +319,35 @@ namespace IDE.ui
|
|||
|
||||
var dataItr = entry.Split('\t');
|
||||
|
||||
int32 threadId = int32.Parse(dataItr.GetNext());
|
||||
StringView threadName = dataItr.GetNext();
|
||||
ThreadEntry threadEntry = default;
|
||||
threadEntry.mThreadId = int32.Parse(dataItr.GetNext());
|
||||
threadEntry.mCPUUsage = int32.Parse(dataItr.GetNext());
|
||||
threadEntry.mName = dataItr.GetNext();
|
||||
entries.Add(threadEntry);
|
||||
}
|
||||
|
||||
entries.Sort(scope (lhs, rhs) =>
|
||||
{
|
||||
int cmp = rhs.mCPUUsage <=> lhs.mCPUUsage;
|
||||
if (cmp == 0)
|
||||
cmp = lhs.mThreadId <=> rhs.mThreadId;
|
||||
return cmp;
|
||||
});
|
||||
|
||||
for (var entry in entries)
|
||||
{
|
||||
String threadStr = null;
|
||||
var str = scope String();
|
||||
str.AppendF("{0}", threadId);
|
||||
if (!threadName.IsEmpty)
|
||||
str.AppendF("{0}", entry.mThreadId);
|
||||
str.AppendF($" ({entry.mCPUUsage}%)");
|
||||
if (!entry.mName.IsEmpty)
|
||||
{
|
||||
threadStr = new String(threadName);
|
||||
str.AppendF(" - {0}", threadName);
|
||||
threadStr = new String(entry.mName);
|
||||
str.AppendF($" - {entry.mName}");
|
||||
}
|
||||
|
||||
subItem = menu.AddItem(str);
|
||||
subItem.mOnMenuItemSelected.Add(new (item) => { Show(threadId, threadStr); } ~ delete threadStr);
|
||||
subItem.mOnMenuItemSelected.Add(new (item) => { Show(entry.mThreadId, threadStr); } ~ delete threadStr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -127,7 +127,8 @@ namespace IDE.ui
|
|||
AddPropertiesItem(category, "Enable File Recovery", "mEnableFileRecovery");
|
||||
AddPropertiesItem(category, "Format on Save", "mFormatOnSave");
|
||||
AddPropertiesItem(category, "Sync with Workspace Panel", "mSyncWithWorkspacePanel");
|
||||
|
||||
AddPropertiesItem(category, "Wrap Comments at Column", "mWrapCommentsAt");
|
||||
|
||||
category.Open(true, true);
|
||||
}
|
||||
|
||||
|
|
|
@ -2160,11 +2160,18 @@ namespace IDE.ui
|
|||
return true;
|
||||
}
|
||||
|
||||
public bool ToggleComment(bool? doComment = null)
|
||||
public bool CommentBlock()
|
||||
{
|
||||
bool? doComment = true;
|
||||
|
||||
if (CheckReadOnly())
|
||||
return false;
|
||||
|
||||
var startLineAndCol = CursorLineAndColumn;
|
||||
int startTextPos = CursorTextPos;
|
||||
var prevSelection = mSelection;
|
||||
bool hadSelection = HasSelection();
|
||||
|
||||
if ((!HasSelection()) && (doComment != null))
|
||||
{
|
||||
CursorToLineEnd();
|
||||
|
@ -2173,14 +2180,15 @@ namespace IDE.ui
|
|||
mSelection = .(CursorTextPos, cursorEndPos);
|
||||
}
|
||||
|
||||
if ((HasSelection()) && (mSelection.Value.Length > 1))
|
||||
{
|
||||
var startLineAndCol = CursorLineAndColumn;
|
||||
|
||||
UndoBatchStart undoBatchStart = new UndoBatchStart("embeddedToggleComment");
|
||||
if ((HasSelection()) && (mSelection.Value.Length > 1))
|
||||
{
|
||||
UndoBatchStart undoBatchStart = new UndoBatchStart("embeddedCommentBlock");
|
||||
mData.mUndoManager.Add(undoBatchStart);
|
||||
|
||||
mData.mUndoManager.Add(new SetCursorAction(this));
|
||||
var setCursorAction = new SetCursorAction(this);
|
||||
setCursorAction.mSelection = prevSelection;
|
||||
setCursorAction.mCursorTextPos = (.)startTextPos;
|
||||
mData.mUndoManager.Add(setCursorAction);
|
||||
|
||||
int minPos = mSelection.GetValueOrDefault().MinPos;
|
||||
int maxPos = mSelection.GetValueOrDefault().MaxPos;
|
||||
|
@ -2200,20 +2208,7 @@ namespace IDE.ui
|
|||
int firstCharPos = minPos + (startLen - afterTrimStart);
|
||||
int lastCharPos = maxPos - (afterTrimStart - afterTrimEnd);
|
||||
|
||||
if ((doComment != true) && (trimmedStr.StartsWith("/*")))
|
||||
{
|
||||
if (trimmedStr.EndsWith("*/"))
|
||||
{
|
||||
mSelection = EditSelection(firstCharPos, firstCharPos + 2);
|
||||
DeleteChar();
|
||||
mSelection = EditSelection(lastCharPos - 4, lastCharPos - 2);
|
||||
DeleteChar();
|
||||
|
||||
if (doComment != null)
|
||||
mSelection = EditSelection(firstCharPos, lastCharPos - 4);
|
||||
}
|
||||
}
|
||||
else if (doComment != false)
|
||||
if (doComment != false)
|
||||
{
|
||||
CursorTextPos = firstCharPos;
|
||||
InsertAtCursor("/*");
|
||||
|
@ -2227,13 +2222,320 @@ namespace IDE.ui
|
|||
if (undoBatchStart != null)
|
||||
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
|
||||
|
||||
CursorLineAndColumn = startLineAndCol;
|
||||
if (startTextPos <= minPos)
|
||||
CursorLineAndColumn = startLineAndCol;
|
||||
else if (startTextPos < maxPos)
|
||||
CursorTextPos = startTextPos + 2;
|
||||
|
||||
if (doComment == null)
|
||||
if ((doComment == null) || (!hadSelection))
|
||||
mSelection = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool CommentLines()
|
||||
{
|
||||
if (CheckReadOnly())
|
||||
return false;
|
||||
|
||||
int startTextPos = CursorTextPos;
|
||||
var prevSelection = mSelection;
|
||||
bool hadSelection = HasSelection();
|
||||
var startLineAndCol = CursorLineAndColumn;
|
||||
if (!HasSelection())
|
||||
{
|
||||
CursorToLineEnd();
|
||||
int cursorEndPos = CursorTextPos;
|
||||
CursorToLineStart(false);
|
||||
mSelection = .(CursorTextPos, cursorEndPos);
|
||||
}
|
||||
|
||||
UndoBatchStart undoBatchStart = new UndoBatchStart("embeddedCommentLines");
|
||||
mData.mUndoManager.Add(undoBatchStart);
|
||||
|
||||
var setCursorAction = new SetCursorAction(this);
|
||||
setCursorAction.mSelection = prevSelection;
|
||||
setCursorAction.mCursorTextPos = (.)startTextPos;
|
||||
mData.mUndoManager.Add(setCursorAction);
|
||||
|
||||
int minPos = mSelection.GetValueOrDefault().MinPos;
|
||||
int maxPos = mSelection.GetValueOrDefault().MaxPos;
|
||||
mSelection = null;
|
||||
|
||||
while (minPos > 0)
|
||||
{
|
||||
var c = mData.mText[minPos - 1].mChar;
|
||||
if (c == '\n')
|
||||
break;
|
||||
minPos--;
|
||||
}
|
||||
|
||||
bool hadMaxChar = false;
|
||||
int checkMaxPos = maxPos;
|
||||
while (checkMaxPos > 0)
|
||||
{
|
||||
var c = mData.mText[checkMaxPos - 1].mChar;
|
||||
if (c == '\n')
|
||||
break;
|
||||
if ((c != '\t') && (c != ' '))
|
||||
{
|
||||
hadMaxChar = true;
|
||||
break;
|
||||
}
|
||||
checkMaxPos--;
|
||||
}
|
||||
|
||||
if (!hadMaxChar)
|
||||
{
|
||||
checkMaxPos = maxPos;
|
||||
while (checkMaxPos < mData.mTextLength)
|
||||
{
|
||||
var c = mData.mText[checkMaxPos].mChar;
|
||||
if (c == '\n')
|
||||
break;
|
||||
if ((c != '\t') && (c != ' '))
|
||||
{
|
||||
maxPos = checkMaxPos + 1;
|
||||
break;
|
||||
}
|
||||
checkMaxPos++;
|
||||
}
|
||||
}
|
||||
|
||||
int wantLineCol = -1;
|
||||
int lineStartCol = 0;
|
||||
bool didLineComment = false;
|
||||
|
||||
for (int i = minPos; i < maxPos; i++)
|
||||
{
|
||||
var c = mData.mText[i].mChar;
|
||||
if (didLineComment)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
didLineComment = false;
|
||||
lineStartCol = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (c == '\t')
|
||||
lineStartCol += 4;
|
||||
else if (c == ' ')
|
||||
lineStartCol++;
|
||||
else
|
||||
{
|
||||
if (wantLineCol == -1)
|
||||
wantLineCol = lineStartCol;
|
||||
else
|
||||
wantLineCol = Math.Min(wantLineCol, lineStartCol);
|
||||
didLineComment = true;
|
||||
}
|
||||
}
|
||||
wantLineCol = Math.Max(0, wantLineCol);
|
||||
|
||||
didLineComment = false;
|
||||
lineStartCol = 0;
|
||||
for (int i = minPos; i < maxPos; i++)
|
||||
{
|
||||
var c = mData.mText[i].mChar;
|
||||
if (didLineComment)
|
||||
{
|
||||
if (c == '\n')
|
||||
{
|
||||
didLineComment = false;
|
||||
lineStartCol = 0;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
bool commentNow = false;
|
||||
if ((wantLineCol != -1) && (lineStartCol >= wantLineCol))
|
||||
commentNow = true;
|
||||
|
||||
if (c == '\t')
|
||||
lineStartCol += 4;
|
||||
else if (c == ' ')
|
||||
lineStartCol++;
|
||||
else
|
||||
commentNow = true;
|
||||
|
||||
if (commentNow)
|
||||
{
|
||||
CursorTextPos = i;
|
||||
String str = scope .();
|
||||
while (lineStartCol + 4 <= wantLineCol)
|
||||
{
|
||||
lineStartCol += 4;
|
||||
str.Append("\t");
|
||||
}
|
||||
str.Append("//");
|
||||
InsertAtCursor(str);
|
||||
didLineComment = true;
|
||||
maxPos += str.Length;
|
||||
}
|
||||
}
|
||||
mSelection = EditSelection(minPos, maxPos);
|
||||
|
||||
if (undoBatchStart != null)
|
||||
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
|
||||
|
||||
CursorLineAndColumn = startLineAndCol;
|
||||
|
||||
if (!hadSelection)
|
||||
mSelection = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FixSelection()
|
||||
{
|
||||
if (!HasSelection())
|
||||
return;
|
||||
if (CursorTextPos >= mSelection.Value.MaxPos)
|
||||
CursorTextPos = mSelection.Value.MaxPos;
|
||||
if (mSelection.Value.MaxPos - mSelection.Value.MinPos <= 1)
|
||||
{
|
||||
mSelection = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public bool ToggleComment(bool? doComment = null)
|
||||
{
|
||||
if (CheckReadOnly())
|
||||
return false;
|
||||
|
||||
int startTextPos = CursorTextPos;
|
||||
bool doLineComment = false;
|
||||
var prevSelection = mSelection;
|
||||
|
||||
LineAndColumn? startLineAndCol = CursorLineAndColumn;
|
||||
if (!HasSelection())
|
||||
{
|
||||
CursorToLineEnd();
|
||||
int cursorEndPos = CursorTextPos;
|
||||
CursorToLineStart(false);
|
||||
mSelection = .(CursorTextPos, cursorEndPos);
|
||||
doLineComment = true;
|
||||
}
|
||||
|
||||
if ((HasSelection()) && (mSelection.Value.Length > 0))
|
||||
{
|
||||
UndoBatchStart undoBatchStart = new UndoBatchStart("embeddedToggleComment");
|
||||
mData.mUndoManager.Add(undoBatchStart);
|
||||
|
||||
var setCursorAction = new SetCursorAction(this);
|
||||
setCursorAction.mSelection = prevSelection;
|
||||
setCursorAction.mCursorTextPos = (.)startTextPos;
|
||||
mData.mUndoManager.Add(setCursorAction);
|
||||
|
||||
int minPos = mSelection.GetValueOrDefault().MinPos;
|
||||
int maxPos = mSelection.GetValueOrDefault().MaxPos;
|
||||
mSelection = null;
|
||||
|
||||
var str = scope String();
|
||||
ExtractString(minPos, maxPos - minPos, str);
|
||||
var trimmedStr = scope String();
|
||||
trimmedStr.Append(str);
|
||||
int32 startLen = (int32)trimmedStr.Length;
|
||||
trimmedStr.TrimStart();
|
||||
int32 afterTrimStart = (int32)trimmedStr.Length;
|
||||
trimmedStr.TrimEnd();
|
||||
int32 afterTrimEnd = (int32)trimmedStr.Length;
|
||||
trimmedStr.Append('\n');
|
||||
|
||||
int firstCharPos = minPos + (startLen - afterTrimStart);
|
||||
int lastCharPos = maxPos - (afterTrimStart - afterTrimEnd);
|
||||
|
||||
if (afterTrimEnd == 0)
|
||||
{
|
||||
if (undoBatchStart != null)
|
||||
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
|
||||
|
||||
CursorLineAndColumn = startLineAndCol.Value;
|
||||
|
||||
if (doComment == null)
|
||||
mSelection = null;
|
||||
|
||||
return false; // not sure if this should be false in blank/only whitespace selection case
|
||||
}
|
||||
else if ((doComment != true) && (trimmedStr.StartsWith("//")))
|
||||
{
|
||||
for (int i = firstCharPos; i <= lastCharPos; i++)
|
||||
{
|
||||
if ((minPos == 0 && i == 0) || (minPos>=0 && SafeGetChar(i - 1) == '\n' || SafeGetChar(i - 1) == '\t'))
|
||||
if (SafeGetChar(i - 0) == '/' && SafeGetChar(i + 1) == '/')
|
||||
{
|
||||
mSelection = EditSelection(i - 0, i + 2);
|
||||
DeleteSelection();
|
||||
lastCharPos -= 2;
|
||||
while (i < maxPos && SafeGetChar(i) != '\n')
|
||||
{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CursorToLineEnd();
|
||||
int cursorEndPos = CursorTextPos;
|
||||
mSelection = .(minPos, cursorEndPos);
|
||||
}
|
||||
else if ((doComment != true) && (trimmedStr.StartsWith("/*")))
|
||||
{
|
||||
if (trimmedStr.EndsWith("*/\n"))
|
||||
{
|
||||
mSelection = EditSelection(firstCharPos, firstCharPos + 2);
|
||||
DeleteChar();
|
||||
mSelection = EditSelection(lastCharPos - 4, lastCharPos - 2);
|
||||
DeleteChar();
|
||||
|
||||
if (prevSelection != null)
|
||||
mSelection = EditSelection(firstCharPos, lastCharPos - 4);
|
||||
}
|
||||
}
|
||||
else if (doComment != false)
|
||||
{ //if selection is from beginning of the line then we want to use // comment, that's why the check for line count and ' ' and tab
|
||||
if (doLineComment)
|
||||
{
|
||||
CursorTextPos = minPos;
|
||||
InsertAtCursor("//"); //goes here if no selection
|
||||
}
|
||||
else
|
||||
{
|
||||
CursorTextPos = firstCharPos;
|
||||
InsertAtCursor("/*");
|
||||
CursorTextPos = lastCharPos + 2;
|
||||
InsertAtCursor("*/");
|
||||
}
|
||||
|
||||
mSelection = EditSelection(firstCharPos, lastCharPos + 4);
|
||||
if (startTextPos <= minPos)
|
||||
CursorLineAndColumn = startLineAndCol.Value;
|
||||
else
|
||||
CursorTextPos = startTextPos + 2;
|
||||
startLineAndCol = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelection = prevSelection;
|
||||
}
|
||||
|
||||
if (undoBatchStart != null)
|
||||
mData.mUndoManager.Add(undoBatchStart.mBatchEnd);
|
||||
|
||||
if (startLineAndCol != null)
|
||||
CursorLineAndColumn = startLineAndCol.Value;
|
||||
|
||||
if (prevSelection == null)
|
||||
mSelection = null;
|
||||
|
||||
FixSelection();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -2275,6 +2577,9 @@ namespace IDE.ui
|
|||
|
||||
public void DuplicateLine()
|
||||
{
|
||||
if ((CheckReadOnly()) || (!mAllowVirtualCursor))
|
||||
return;
|
||||
|
||||
UndoBatchStart undoBatchStart = new UndoBatchStart("duplicateLine");
|
||||
mData.mUndoManager.Add(undoBatchStart);
|
||||
|
||||
|
@ -3103,7 +3408,7 @@ namespace IDE.ui
|
|||
return;
|
||||
}
|
||||
|
||||
if ((keyChar == '/') && (ToggleComment()))
|
||||
if ((keyChar == '/') && (HasSelection()) && (ToggleComment()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -160,6 +160,8 @@ namespace IDE.ui
|
|||
{
|
||||
public int32 mCursorPos;
|
||||
public String mResult ~ delete _;
|
||||
public int32? mLine;
|
||||
public int32? mLineChar;
|
||||
|
||||
public ~this()
|
||||
{
|
||||
|
@ -621,6 +623,10 @@ namespace IDE.ui
|
|||
//Classify(options.HasFlag(.HighPriority) ? ResolveType.Autocomplete_HighPri : ResolveType.Autocomplete);
|
||||
|
||||
ResolveParams resolveParams = new ResolveParams();
|
||||
if (gApp.mDbgTimeAutocomplete)
|
||||
resolveParams.mStopwatch = new .()..Start();
|
||||
if (gApp.mDbgPerfAutocomplete)
|
||||
resolveParams.mProfileInstance = Profiler.StartSampling("Autocomplete").GetValueOrDefault();
|
||||
resolveParams.mIsUserRequested = options.HasFlag(.UserRequested);
|
||||
resolveParams.mDoFuzzyAutoComplete = gApp.mSettings.mEditorSettings.mFuzzyAutoComplete;
|
||||
Classify(.Autocomplete, resolveParams);
|
||||
|
@ -1186,7 +1192,7 @@ namespace IDE.ui
|
|||
//if (mCurParser != null)
|
||||
{
|
||||
if (gApp.mWorkspace.mProjectLoadState != .Loaded)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
if (!isHi)
|
||||
Debug.Assert(!mIsPerformingBackgroundClassify);
|
||||
|
@ -2336,6 +2342,11 @@ namespace IDE.ui
|
|||
if (mDisposed)
|
||||
return;
|
||||
|
||||
if (mProjectSource?.mEditData?.HasTextChanged() == true)
|
||||
{
|
||||
mProjectSource.ClearEditData();
|
||||
}
|
||||
|
||||
ProcessDeferredResolveResults(-1);
|
||||
|
||||
if (IDEApp.sApp.mLastActiveSourceViewPanel == this)
|
||||
|
@ -4725,7 +4736,7 @@ namespace IDE.ui
|
|||
delete parser;
|
||||
}
|
||||
|
||||
public void UpdateMouseover(bool mouseoverFired, bool mouseInbounds, int line, int lineChar)
|
||||
public void UpdateMouseover(bool mouseoverFired, bool mouseInbounds, int line, int lineChar, bool isManual = false)
|
||||
{
|
||||
|
||||
|
||||
|
@ -5011,6 +5022,11 @@ namespace IDE.ui
|
|||
|
||||
mHoverResolveTask = new HoverResolveTask();
|
||||
mHoverResolveTask.mCursorPos = (int32)textIdx;
|
||||
if (isManual)
|
||||
{
|
||||
mHoverResolveTask.mLine = (.)line;
|
||||
mHoverResolveTask.mLineChar = (.)lineChar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5204,6 +5220,16 @@ namespace IDE.ui
|
|||
#if IDE_C_SUPPORT
|
||||
hasClangHoverErrorData = mClangHoverErrorData != null;
|
||||
#endif
|
||||
|
||||
if (mHoverResolveTask != null)
|
||||
{
|
||||
if (mHoverResolveTask.mLine != null)
|
||||
{
|
||||
UpdateMouseover(true, true, mHoverResolveTask.mLine.Value, mHoverResolveTask.mLineChar.Value, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (((mouseoverFired) || (mHoverWatch != null) || (hasClangHoverErrorData) || (mHoverResolveTask?.mResult != null)) &&
|
||||
(mousePos.x >= 0))
|
||||
{
|
||||
|
@ -5526,6 +5552,13 @@ namespace IDE.ui
|
|||
|
||||
HandleResolveResult(resolveResult.mResolveType, resolveResult.mAutocompleteInfo, resolveResult);
|
||||
|
||||
if (resolveResult.mStopwatch != null)
|
||||
{
|
||||
resolveResult.mStopwatch.Stop();
|
||||
if (var autoComplete = GetAutoComplete())
|
||||
Debug.WriteLine($"Autocomplete {resolveResult.mStopwatch.ElapsedMilliseconds}ms entries: {autoComplete.mAutoCompleteListWidget.mEntryList.Count}");
|
||||
}
|
||||
|
||||
//Debug.WriteLine("ProcessDeferredResolveResults finished {0}", resolveResult.mResolveType);
|
||||
|
||||
//bool checkIt = (mFilePath.Contains("Program.bf")) && (mEditWidget.mEditWidgetContent.mData.mCurTextVersionId > 3);
|
||||
|
|
|
@ -2765,7 +2765,10 @@ namespace IDE.ui
|
|||
{
|
||||
String evalStr = scope String();
|
||||
CompactChildExpression(listViewItem, evalStr);
|
||||
evalStr.Insert(0, "&");
|
||||
if (evalStr.StartsWith("*"))
|
||||
evalStr.Remove(0, 1);
|
||||
else
|
||||
evalStr.Insert(0, "&");
|
||||
gApp.mBreakpointPanel.CreateMemoryBreakpoint(evalStr);
|
||||
gApp.MarkDirty();
|
||||
});
|
||||
|
|
|
@ -2171,6 +2171,8 @@ BeMCOperand BeMCContext::GetOperand(BeValue* value, bool allowMetaResult, bool a
|
|||
auto vregInfo = GetVRegInfo(tlsVReg);
|
||||
vregInfo->mMustExist = true;
|
||||
vregInfo->mForceReg = true;
|
||||
vregInfo->mDisableR12 = true;
|
||||
vregInfo->mDisableR13 = true;
|
||||
mTLSVRegIdx = tlsVReg.mVRegIdx;
|
||||
}
|
||||
|
||||
|
@ -15930,7 +15932,7 @@ void BeMCContext::Generate(BeFunction* function)
|
|||
mDbgPreferredRegs[32] = X64Reg_R8;*/
|
||||
|
||||
//mDbgPreferredRegs[8] = X64Reg_RAX;
|
||||
//mDebugging = (function->mName == "?Load@TestProgram@BeefTest@bf@@SA?AUHandle@23@XZ");
|
||||
//mDebugging = (function->mName == "?InitThread@Foo@BeefTest@bf@@CA?AU?$Result@X@System@3@H@Z");
|
||||
// || (function->mName == "?MethodA@TestProgram@BeefTest@bf@@CAXXZ");
|
||||
// || (function->mName == "?Hey@Blurg@bf@@SAXXZ")
|
||||
// ;
|
||||
|
|
|
@ -122,7 +122,7 @@ if(MSVC)
|
|||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /W3 /GL /Od /Oi /Gy /EHsc")
|
||||
endif(MSVC)
|
||||
if(NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-rtti -Wno-multichar -Wno-invalid-offsetof")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -fno-rtti -Wno-multichar -Wno-invalid-offsetof")
|
||||
endif(NOT MSVC)
|
||||
|
||||
################ Files ################
|
||||
|
|
|
@ -360,6 +360,8 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
//mMaxInterfaceSlots = 16;
|
||||
mMaxInterfaceSlots = -1;
|
||||
mInterfaceSlotCountChanged = false;
|
||||
mLastHadComptimeRebuilds = false;
|
||||
mHasComptimeRebuilds = false;
|
||||
|
||||
mHSPreserveIdx = 0;
|
||||
mCompileLogFP = NULL;
|
||||
|
@ -825,7 +827,7 @@ void BfCompiler::GetTestMethods(BfVDataModule* bfModule, Array<TestMethod>& test
|
|||
|
||||
auto _CheckMethod = [&](BfTypeInstance* typeInstance, BfMethodInstance* methodInstance)
|
||||
{
|
||||
auto project = typeInstance->mTypeDef->mProject;
|
||||
auto project = methodInstance->mMethodDef->mDeclaringType->mProject;
|
||||
if (project->mTargetType != BfTargetType_BeefTest)
|
||||
return;
|
||||
if (project != bfModule->mProject)
|
||||
|
@ -913,7 +915,8 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& test
|
|||
auto methodInstance = testMethod.mMethodInstance;
|
||||
auto typeInstance = methodInstance->GetOwner();
|
||||
testMethod.mName += bfModule->TypeToString(typeInstance);
|
||||
testMethod.mName += ".";
|
||||
if (!testMethod.mName.IsEmpty())
|
||||
testMethod.mName += ".";
|
||||
testMethod.mName += methodInstance->mMethodDef->mName;
|
||||
|
||||
testMethod.mName += "\t";
|
||||
|
@ -1021,8 +1024,11 @@ void BfCompiler::EmitTestMethod(BfVDataModule* bfModule, Array<TestMethod>& test
|
|||
else
|
||||
{
|
||||
for (int defaultIdx = 0; defaultIdx < (int)methodInstance->mDefaultValues.size(); defaultIdx++)
|
||||
{
|
||||
auto castedVal = bfModule->Cast(methodInstance->mMethodDef->GetRefNode(), methodInstance->mDefaultValues[defaultIdx], methodInstance->GetParamType(defaultIdx));
|
||||
{
|
||||
auto constHolder = methodInstance->GetOwner()->mConstHolder;
|
||||
auto defaultTypedValue = methodInstance->mDefaultValues[defaultIdx];
|
||||
auto defaultVal = bfModule->ConstantToCurrent(constHolder->GetConstant(defaultTypedValue.mValue), constHolder, defaultTypedValue.mType);
|
||||
auto castedVal = bfModule->Cast(methodInstance->mMethodDef->GetRefNode(), BfTypedValue(defaultVal, defaultTypedValue.mType), methodInstance->GetParamType(defaultIdx));
|
||||
if (castedVal)
|
||||
{
|
||||
BfExprEvaluator exprEvaluator(bfModule);
|
||||
|
@ -2927,7 +2933,7 @@ void BfCompiler::GenerateDynCastData()
|
|||
|
||||
void BfCompiler::UpdateRevisedTypes()
|
||||
{
|
||||
BfLogSysM("UpdateRevisedTypes\n");
|
||||
BfLogSysM("BfCompiler::UpdateRevisedTypes\n");
|
||||
BP_ZONE("BfCompiler::UpdateRevisedTypes");
|
||||
|
||||
// See if we have any name conflicts and remove those
|
||||
|
@ -6561,6 +6567,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
|
||||
// Inc revision for next run through Compile
|
||||
mRevision++;
|
||||
mHasComptimeRebuilds = false;
|
||||
int revision = mRevision;
|
||||
BfLogSysM("Compile Start. Revision: %d. HasParser:%d AutoComplete:%d\n", revision,
|
||||
(mResolvePassData != NULL) && (mResolvePassData->mParser != NULL),
|
||||
|
@ -7021,27 +7028,34 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
|
||||
if (hasTests)
|
||||
{
|
||||
HashSet<BfProject*> projectSet;
|
||||
|
||||
for (auto type : mContext->mResolvedTypes)
|
||||
{
|
||||
auto typeInstance = type->ToTypeInstance();
|
||||
if ((typeInstance != NULL) &&
|
||||
(typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest))
|
||||
{
|
||||
bool typeHasTest = false;
|
||||
if (typeInstance != NULL)
|
||||
{
|
||||
for (auto& methodInstanceGroup : typeInstance->mMethodInstanceGroups)
|
||||
{
|
||||
if (methodInstanceGroup.mDefault != NULL)
|
||||
{
|
||||
auto methodInstance = methodInstanceGroup.mDefault;
|
||||
auto project = methodInstance->mMethodDef->mDeclaringType->mProject;
|
||||
if (project->mTargetType != BfTargetType_BeefTest)
|
||||
continue;
|
||||
if ((methodInstance->GetCustomAttributes() != NULL) &&
|
||||
(methodInstance->GetCustomAttributes()->Contains(mTestAttributeTypeDef)))
|
||||
{
|
||||
typeHasTest = true;
|
||||
projectSet.Add(project);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeHasTest)
|
||||
mContext->MarkUsedModules(typeInstance->mTypeDef->mProject, typeInstance->mModule);
|
||||
if (!projectSet.IsEmpty())
|
||||
{
|
||||
for (auto project : projectSet)
|
||||
mContext->MarkUsedModules(project, typeInstance->mModule);
|
||||
projectSet.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7494,6 +7508,11 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (didCancel)
|
||||
mLastHadComptimeRebuilds = mHasComptimeRebuilds || mLastHadComptimeRebuilds;
|
||||
else
|
||||
mLastHadComptimeRebuilds = mHasComptimeRebuilds;
|
||||
|
||||
return !didCancel && !mHasQueuedTypeRebuilds;
|
||||
}
|
||||
|
||||
|
@ -9104,6 +9123,11 @@ BF_EXPORT int BF_CALLTYPE BfCompiler_GetCurConstEvalExecuteId(BfCompiler* bfComp
|
|||
return bfCompiler->mCEMachine->mExecuteId;
|
||||
}
|
||||
|
||||
BF_EXPORT float BF_CALLTYPE BfCompiler_GetLastHadComptimeRebuilds(BfCompiler* bfCompiler)
|
||||
{
|
||||
return bfCompiler->mLastHadComptimeRebuilds;
|
||||
}
|
||||
|
||||
BF_EXPORT void BF_CALLTYPE BfCompiler_Cancel(BfCompiler* bfCompiler)
|
||||
{
|
||||
bfCompiler->Cancel();
|
||||
|
|
|
@ -328,7 +328,9 @@ public:
|
|||
bool mFastFinish;
|
||||
bool mHasQueuedTypeRebuilds; // Infers we had a fast finish that requires a type rebuild
|
||||
bool mHadCancel;
|
||||
bool mWantsDeferMethodDecls;
|
||||
bool mWantsDeferMethodDecls;
|
||||
bool mLastHadComptimeRebuilds;
|
||||
bool mHasComptimeRebuilds;
|
||||
bool mInInvalidState;
|
||||
float mCompletionPct;
|
||||
int mHSPreserveIdx;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "BfSourceClassifier.h"
|
||||
#include "BfAutoComplete.h"
|
||||
#include "BfResolvePass.h"
|
||||
#include "CeMachine.h"
|
||||
|
||||
#pragma warning(pop)
|
||||
|
||||
|
@ -1850,6 +1851,7 @@ void BfContext::PreUpdateRevisedTypes()
|
|||
void BfContext::UpdateRevisedTypes()
|
||||
{
|
||||
BP_ZONE("BfContext::UpdateRevisedTypes");
|
||||
BfLogSysM("BfContext::UpdateRevisedTypes\n");
|
||||
|
||||
int wantPtrSize;
|
||||
if ((mCompiler->mOptions.mMachineType == BfMachineType_x86) |
|
||||
|
@ -1889,6 +1891,9 @@ void BfContext::UpdateRevisedTypes()
|
|||
bool wantsDebugInfo = (mCompiler->mOptions.mEmitDebugInfo);
|
||||
|
||||
Array<BfTypeInstance*> defStateChangedQueue;
|
||||
Array<BfTypeInstance*> defEmitParentCheckQueue;
|
||||
|
||||
Dictionary<String, uint64> lastWriteTimeMap;
|
||||
|
||||
// Do primary 'rebuild' scan
|
||||
for (auto type : mResolvedTypes)
|
||||
|
@ -1917,20 +1922,8 @@ void BfContext::UpdateRevisedTypes()
|
|||
|
||||
auto typeDef = typeInst->mTypeDef;
|
||||
|
||||
if (typeDef->mEmitParent != NULL)
|
||||
{
|
||||
if (typeDef->mDefState == BfTypeDef::DefState_Deleted)
|
||||
{
|
||||
typeInst->mTypeDef = typeDef->mEmitParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto emitTypeDef = typeDef;
|
||||
typeDef = typeDef->mEmitParent;
|
||||
if (typeDef->mNextRevision != NULL)
|
||||
emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty;
|
||||
}
|
||||
}
|
||||
if (typeDef->mEmitParent != NULL)
|
||||
defEmitParentCheckQueue.Add(typeInst);
|
||||
|
||||
if (typeDef->mProject->mDisabled)
|
||||
{
|
||||
|
@ -1939,7 +1932,7 @@ void BfContext::UpdateRevisedTypes()
|
|||
}
|
||||
|
||||
typeInst->mRebuildFlags = BfTypeRebuildFlag_None;
|
||||
|
||||
|
||||
if (typeDef->mIsPartial)
|
||||
{
|
||||
// This was a type that wasn't marked as partial before but now it is, so it doesn't need its own typedef
|
||||
|
@ -1948,6 +1941,32 @@ void BfContext::UpdateRevisedTypes()
|
|||
continue;
|
||||
}
|
||||
|
||||
if (typeInst->mCeTypeInfo != NULL)
|
||||
{
|
||||
bool changed = false;
|
||||
|
||||
for (auto& kv : typeInst->mCeTypeInfo->mRebuildMap)
|
||||
{
|
||||
mCompiler->mHasComptimeRebuilds = true;
|
||||
if (kv.mKey.mKind == CeRebuildKey::Kind_File)
|
||||
{
|
||||
String* keyPtr = NULL;
|
||||
uint64* valuePtr = NULL;
|
||||
if (lastWriteTimeMap.TryAdd(kv.mKey.mString, &keyPtr, &valuePtr))
|
||||
{
|
||||
*valuePtr = BfpFile_GetTime_LastWrite(kv.mKey.mString.c_str());
|
||||
}
|
||||
if (*valuePtr != kv.mValue.mInt)
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (changed)
|
||||
{
|
||||
RebuildType(typeInst);
|
||||
}
|
||||
}
|
||||
|
||||
if ((typeInst->mHotTypeData != NULL) && (!mCompiler->IsHotCompile()))
|
||||
{
|
||||
if (typeInst->mHotTypeData->GetLatestVersion()->mDeclHotCompileIdx != 0)
|
||||
|
@ -2042,6 +2061,31 @@ void BfContext::UpdateRevisedTypes()
|
|||
}
|
||||
}
|
||||
|
||||
for (auto typeInst : defEmitParentCheckQueue)
|
||||
{
|
||||
if (typeInst->IsDeleting())
|
||||
continue;
|
||||
auto typeDef = typeInst->mTypeDef;
|
||||
if (typeDef->mEmitParent != NULL)
|
||||
{
|
||||
if (typeDef->mDefState == BfTypeDef::DefState_Deleted)
|
||||
{
|
||||
BfLogSysM("Type %p typeDef %p deleted, setting to emitParent %p\n", typeInst, typeDef, typeDef->mEmitParent);
|
||||
typeInst->mTypeDef = typeDef->mEmitParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto emitTypeDef = typeDef;
|
||||
typeDef = typeDef->mEmitParent;
|
||||
if (typeDef->mNextRevision != NULL)
|
||||
{
|
||||
BfLogSysM("Type %p typeDef %p emitparent %p has next revision, setting emittedDirty\n", typeInst, emitTypeDef, typeDef);
|
||||
emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
{
|
||||
AutoCrit autoCrit(mSystem->mDataLock);
|
||||
|
|
|
@ -4919,7 +4919,10 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
|
|||
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(targetSrc)))
|
||||
{
|
||||
if (autoComplete->mIsGetDefinition)
|
||||
autoComplete->SetDefinitionLocation(basePropDef->GetRefNode(), true);
|
||||
{
|
||||
//NOTE: passing 'force=true' in here causes https://github.com/beefytech/Beef/issues/1064
|
||||
autoComplete->SetDefinitionLocation(basePropDef->GetRefNode());
|
||||
}
|
||||
autoComplete->mDefProp = basePropDef;
|
||||
autoComplete->mDefType = baseTypeInst->mTypeDef;
|
||||
}
|
||||
|
@ -5407,7 +5410,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, BfMethodInstance*
|
|||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
auto val = mModule->GetDefaultTypedValue(returnType, true, (GetStructRetIdx(methodInstance) != -1) ? BfDefaultValueKind_Addr : BfDefaultValueKind_Value);
|
||||
if (val.mKind == BfTypedValueKind_Addr)
|
||||
val.mKind = BfTypedValueKind_RestrictedTempAddr;
|
||||
|
@ -6973,7 +6976,7 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
filePath = mModule->mCurFilePosition.mFileInstance->mParser->mFileName;
|
||||
argValue = BfTypedValue(mModule->GetStringObjectValue(filePath),
|
||||
mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef));
|
||||
}
|
||||
}
|
||||
else if (strcmp(globalVar->mName, "#CallerFileName") == 0)
|
||||
{
|
||||
String filePath = "";
|
||||
|
@ -6990,6 +6993,24 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
argValue = BfTypedValue(mModule->GetStringObjectValue(GetFileDir(filePath)),
|
||||
mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef));
|
||||
}
|
||||
else if (strcmp(globalVar->mName, "#CallerTypeName") == 0)
|
||||
{
|
||||
String typeName = "";
|
||||
if (mModule->mCurTypeInstance != NULL)
|
||||
typeName = mModule->TypeToString(mModule->mCurTypeInstance);
|
||||
argValue = BfTypedValue(mModule->GetStringObjectValue(typeName),
|
||||
mModule->ResolveTypeDef(mModule->mCompiler->mStringTypeDef));
|
||||
}
|
||||
else if (strcmp(globalVar->mName, "#CallerType") == 0)
|
||||
{
|
||||
auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
|
||||
BfType* type = mModule->mCurTypeInstance;
|
||||
if (type != NULL)
|
||||
{
|
||||
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
|
||||
argValue = BfTypedValue(mModule->CreateTypeDataRef(type), typeType);
|
||||
}
|
||||
}
|
||||
else if (strcmp(globalVar->mName, "#CallerMemberName") == 0)
|
||||
{
|
||||
String memberName = "";
|
||||
|
@ -7095,7 +7116,11 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
if (methodRefType->WantsDataPassedAsSplat(dataIdx))
|
||||
SplatArgs(lookupVal, irArgs);
|
||||
else
|
||||
{
|
||||
if (lookupVal.mType->IsComposite())
|
||||
lookupVal = mModule->MakeAddressable(lookupVal, false);
|
||||
irArgs.push_back(lookupVal.mValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10182,6 +10207,17 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
|||
|
||||
if ((fieldResult) || (mPropDef != NULL))
|
||||
{
|
||||
if (mResultFieldInstance != NULL)
|
||||
{
|
||||
auto autoComplete = GetAutoComplete();
|
||||
if ((autoComplete != NULL) && (autoComplete->IsAutocompleteNode(identifierNode)))
|
||||
{
|
||||
auto fieldDef = mResultFieldInstance->GetFieldDef();
|
||||
if (fieldDef != NULL)
|
||||
autoComplete->SetDefinitionLocation(fieldDef->GetRefNode());
|
||||
}
|
||||
}
|
||||
|
||||
mResult = fieldResult;
|
||||
PerformAssignment(assignExpr, true, BfTypedValue());
|
||||
mResult = BfTypedValue();
|
||||
|
@ -11423,7 +11459,7 @@ BfTypedValue BfExprEvaluator::DoImplicitArgCapture(BfAstNode* refNode, BfMethodI
|
|||
BfMethodInstance* methodRefMethodInst = methodRefType->mMethodRef;
|
||||
|
||||
BF_ASSERT(methodRefMethodInst == methodInstance);
|
||||
|
||||
|
||||
auto paramType = methodInstance->GetParamType(paramIdx);
|
||||
|
||||
int dataIdx = methodRefType->GetDataIdxFromParamIdx(paramIdx);
|
||||
|
@ -11462,9 +11498,8 @@ BfTypedValue BfExprEvaluator::DoImplicitArgCapture(BfAstNode* refNode, BfMethodI
|
|||
lookupVal = mModule->LoadValue(lookupVal);
|
||||
return lookupVal;
|
||||
}
|
||||
}
|
||||
BF_ASSERT(methodRefTarget.IsAddr());
|
||||
if (paramType->IsComposite())
|
||||
}
|
||||
if ((paramType->IsComposite()) && (methodRefTarget.IsAddr()))
|
||||
return BfTypedValue(mModule->mBfIRBuilder->CreateInBoundsGEP(methodRefTarget.mValue, 0, dataIdx), paramType, true);
|
||||
return BfTypedValue(mModule->ExtractValue(methodRefTarget, dataIdx), paramType);
|
||||
}
|
||||
|
@ -11922,8 +11957,8 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
if (bindResult.mTarget.IsSplat())
|
||||
target = mModule->AggregateSplat(bindResult.mTarget, &bindResult.mIRArgs[0]);
|
||||
else
|
||||
target = mModule->LoadValue(bindResult.mTarget);
|
||||
|
||||
target = bindResult.mTarget;
|
||||
|
||||
mModule->mBfIRBuilder->CreateStore(target.mValue, elemPtr);
|
||||
|
||||
mResult = BfTypedValue(methodRefPtr, methodRefType, true);
|
||||
|
@ -14525,8 +14560,10 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
{
|
||||
if (typeInstance->IsObject())
|
||||
{
|
||||
bool hasRealtimeLeakCheck = (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck) && (!IsComptime());
|
||||
|
||||
bool wantsCtorClear = true;
|
||||
if (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck)
|
||||
if (hasRealtimeLeakCheck)
|
||||
{
|
||||
// Dbg_ObjectAlloc clears internally so we don't need to call CtorClear for those
|
||||
if ((!isStackAlloc) && (!allocTarget.mCustomAllocator) && (allocTarget.mScopedInvocationTarget == NULL))
|
||||
|
@ -14548,7 +14585,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
}
|
||||
}
|
||||
|
||||
if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (mModule->mCompiler->mOptions.mEnableRealtimeLeakCheck))
|
||||
if ((!mModule->mIsComptimeModule) && (isStackAlloc) && (hasRealtimeLeakCheck))
|
||||
{
|
||||
BfMethodInstance* markMethod = mModule->GetRawMethodByName(mModule->mContext->mBfObjectType, "GCMarkMembers");
|
||||
BF_ASSERT(markMethod != NULL);
|
||||
|
@ -14750,7 +14787,7 @@ BfAllocTarget BfExprEvaluator::ResolveAllocTarget(BfAstNode* allocNode, BfTokenN
|
|||
|
||||
if (attributeDirective != NULL)
|
||||
{
|
||||
auto customAttrs = mModule->GetCustomAttributes(attributeDirective, BfAttributeTargets_Alloc, true, &allocTarget.mCaptureInfo);
|
||||
auto customAttrs = mModule->GetCustomAttributes(attributeDirective, BfAttributeTargets_Alloc, BfGetCustomAttributesFlags_AllowNonConstArgs, &allocTarget.mCaptureInfo);
|
||||
if (customAttrs != NULL)
|
||||
{
|
||||
for (auto& attrib : customAttrs->mAttributes)
|
||||
|
@ -19750,7 +19787,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
|||
|
||||
auto indexType = (BfPrimitiveType*)indexArgument.mType;
|
||||
|
||||
if (!mModule->mSystem->DoesLiteralFit(indexType->mTypeDef->mTypeCode, sizedArrayType->mElementCount))
|
||||
if (!mModule->mSystem->DoesLiteralFit(indexType->mTypeDef->mTypeCode, (int64)sizedArrayType->mElementCount))
|
||||
{
|
||||
// We need to upsize the index so we can compare it against the larger elementCount
|
||||
indexType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||
|
@ -22427,6 +22464,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Boolean, 0),
|
||||
mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22438,6 +22477,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
auto primType = (BfPrimitiveType*)resultType;
|
||||
if (primType->mTypeDef->mTypeCode == BfTypeCode_Boolean)
|
||||
{
|
||||
bool passThrough = false;
|
||||
switch (binaryOp)
|
||||
{
|
||||
case BfBinaryOp_Equality:
|
||||
|
@ -22464,16 +22504,20 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateXor(convLeftValue, convRightValue),
|
||||
mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
break;
|
||||
case BfBinaryOp_Compare:
|
||||
passThrough = true;
|
||||
break;
|
||||
default:
|
||||
if (mModule->PreFail())
|
||||
mModule->Fail("Invalid operation for booleans", opToken);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
if (!passThrough)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if ((!resultType->IsIntegral()) && (!resultType->IsFloat()))
|
||||
if ((!resultType->IsIntegralOrBool()) && (!resultType->IsFloat()))
|
||||
{
|
||||
if (mModule->PreFail())
|
||||
mModule->Fail(StrFormat("Cannot perform operation on type '%s'", mModule->TypeToString(resultType).c_str()), opToken);
|
||||
|
@ -22578,7 +22622,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateCmpGTE(convLeftValue, convRightValue, resultType->IsSigned()),
|
||||
mModule->GetPrimitiveType(BfTypeCode_Boolean));
|
||||
break;
|
||||
case BfBinaryOp_Compare:
|
||||
case BfBinaryOp_Compare:
|
||||
{
|
||||
auto intType = mModule->GetPrimitiveType(BfTypeCode_IntPtr);
|
||||
if ((convLeftValue.IsConst()) && (convRightValue.IsConst()))
|
||||
|
@ -22599,7 +22643,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
|
|||
mResult = BfTypedValue(mModule->GetConstValue(0, mModule->GetPrimitiveType(BfTypeCode_IntPtr)), intType);
|
||||
}
|
||||
}
|
||||
else if ((resultType->IsIntegral()) && (resultType->mSize < intType->mSize))
|
||||
else if ((resultType->IsIntegralOrBool()) && (resultType->mSize < intType->mSize))
|
||||
{
|
||||
auto leftIntValue = mModule->mBfIRBuilder->CreateNumericCast(convLeftValue, resultType->IsSigned(), BfTypeCode_IntPtr);
|
||||
auto rightIntValue = mModule->mBfIRBuilder->CreateNumericCast(convRightValue, resultType->IsSigned(), BfTypeCode_IntPtr);
|
||||
|
|
|
@ -2627,9 +2627,13 @@ void BfIRBuilder::CreateTypeDeclaration(BfType* type, bool forceDbgDefine)
|
|||
BfMethodInstance* methodInstance = methodRefType->mMethodRef;
|
||||
|
||||
String name = "_BF_MethodRef_";
|
||||
name += BfTypeUtils::HashEncode64(methodInstance->mIdHash).c_str();
|
||||
|
||||
if (wantDIData)
|
||||
if (methodInstance != NULL)
|
||||
name += BfTypeUtils::HashEncode64(methodInstance->mIdHash).c_str();
|
||||
|
||||
BF_ASSERT(methodInstance != NULL);
|
||||
|
||||
if ((wantDIData) && (methodInstance != NULL))
|
||||
{
|
||||
auto typeDeclaration = methodInstance->GetOwner()->mTypeDef->mTypeDeclaration;
|
||||
|
||||
|
|
|
@ -3913,7 +3913,7 @@ void BfModule::ResolveConstField(BfTypeInstance* typeInstance, BfFieldInstance*
|
|||
if (isLet || isVar)
|
||||
fieldType = GetPrimitiveType(BfTypeCode_Var);
|
||||
else
|
||||
fieldType = ResolveTypeRef(fieldDef->mTypeRef);
|
||||
fieldType = ResolveTypeRef(fieldDef->mTypeRef,BfPopulateType_Identity, BfResolveTypeRefFlag_AllowInferredSizedArray);
|
||||
if (fieldType == NULL)
|
||||
fieldType = mContext->mBfObjectType;
|
||||
}
|
||||
|
@ -4297,7 +4297,7 @@ BfTypedValue BfModule::GetFieldInitializerValue(BfFieldInstance* fieldInstance,
|
|||
int ceExecuteId = -1;
|
||||
if (mCompiler->mCEMachine != NULL)
|
||||
ceExecuteId = mCompiler->mCEMachine->mExecuteId;
|
||||
|
||||
|
||||
BfTypeState typeState;
|
||||
typeState.mType = mCurTypeInstance;
|
||||
typeState.mCurTypeDef = fieldDef->mDeclaringType;
|
||||
|
@ -6368,7 +6368,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
FieldFlags_Const = 0x40,
|
||||
FieldFlags_SpecialName = 0x80,
|
||||
FieldFlags_EnumPayload = 0x100,
|
||||
FieldFlags_EnumDiscriminator = 0x200
|
||||
FieldFlags_EnumDiscriminator = 0x200,
|
||||
FieldFlags_EnumCase = 0x400
|
||||
};
|
||||
|
||||
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
|
||||
|
@ -6434,6 +6435,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Static);
|
||||
if (fieldDef->mIsConst)
|
||||
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_Const);
|
||||
if (fieldDef->IsEnumCaseEntry())
|
||||
fieldFlags = (FieldFlags)(fieldFlags | FieldFlags_EnumCase);
|
||||
|
||||
int customAttrIdx = _HandleCustomAttrs(fieldInstance->mCustomAttributes);
|
||||
BfIRValue constValue;
|
||||
|
@ -7787,9 +7790,16 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
|||
}
|
||||
}
|
||||
|
||||
if (checkArgType->IsPointer())
|
||||
{
|
||||
auto ptrType = (BfPointerType*)checkArgType;
|
||||
checkArgType = ptrType->mElementType;
|
||||
}
|
||||
|
||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_New) != 0)
|
||||
{
|
||||
bool canAlloc = false;
|
||||
|
||||
if (auto checkTypeInst = checkArgType->ToTypeInstance())
|
||||
{
|
||||
if (checkTypeInst->IsObjectOrStruct())
|
||||
|
@ -7857,13 +7867,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
|||
}
|
||||
|
||||
if ((genericParamInst->mInterfaceConstraints.IsEmpty()) && (genericParamInst->mOperatorConstraints.IsEmpty()) && (genericParamInst->mTypeConstraint == NULL))
|
||||
return true;
|
||||
|
||||
if (checkArgType->IsPointer())
|
||||
{
|
||||
auto ptrType = (BfPointerType*)checkArgType;
|
||||
checkArgType = ptrType->mElementType;
|
||||
}
|
||||
return true;
|
||||
|
||||
if (genericParamInst->mTypeConstraint != NULL)
|
||||
{
|
||||
|
@ -8469,10 +8473,10 @@ void BfModule::InitTypeInst(BfTypedValue typedValue, BfScopeData* scopeData, boo
|
|||
mBfIRBuilder->PopulateType(typedValue.mType);
|
||||
auto vObjectAddr = mBfIRBuilder->CreateInBoundsGEP(typedValue.mValue, 0, 0);
|
||||
bool isAutocomplete = mCompiler->IsAutocomplete();
|
||||
|
||||
|
||||
BfIRValue vDataRef;
|
||||
if (!isAutocomplete)
|
||||
{
|
||||
{
|
||||
vDataRef = GetClassVDataPtr(typeInstance);
|
||||
}
|
||||
|
||||
|
@ -11143,8 +11147,11 @@ void BfModule::ValidateCustomAttributes(BfCustomAttributes* customAttributes, Bf
|
|||
}
|
||||
}
|
||||
|
||||
void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget, bool allowNonConstArgs, BfCaptureInfo* captureInfo)
|
||||
void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrTarget, BfGetCustomAttributesFlags flags, BfCaptureInfo* captureInfo)
|
||||
{
|
||||
bool allowNonConstArgs = (flags & BfGetCustomAttributesFlags_AllowNonConstArgs) != 0;
|
||||
bool keepConstsInModule = (flags & BfGetCustomAttributesFlags_KeepConstsInModule) != 0;
|
||||
|
||||
if (!mCompiler->mHasRequiredTypes)
|
||||
return;
|
||||
|
||||
|
@ -11388,7 +11395,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
|
|||
BfTypedValue result = constResolver.Resolve(assignExpr->mRight, fieldTypeInst.mResolvedType, BfConstResolveFlag_NoActualizeValues);
|
||||
if (result)
|
||||
{
|
||||
CurrentAddToConstHolder(result.mValue);
|
||||
if (!keepConstsInModule)
|
||||
CurrentAddToConstHolder(result.mValue);
|
||||
setField.mParam = result;
|
||||
customAttribute.mSetField.push_back(setField);
|
||||
}
|
||||
|
@ -11450,7 +11458,8 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
|
|||
if (!result.mValue.IsConst())
|
||||
result = GetDefaultTypedValue(result.mType);
|
||||
BF_ASSERT(result.mType == propType);
|
||||
CurrentAddToConstHolder(result.mValue);
|
||||
if (!keepConstsInModule)
|
||||
CurrentAddToConstHolder(result.mValue);
|
||||
setProperty.mParam = result;
|
||||
customAttribute.mSetProperties.push_back(setProperty);
|
||||
}
|
||||
|
@ -11566,10 +11575,13 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
|
|||
}
|
||||
|
||||
// Move all those to the constHolder
|
||||
for (auto& ctorArg : customAttribute.mCtorArgs)
|
||||
{
|
||||
if (ctorArg.IsConst())
|
||||
CurrentAddToConstHolder(ctorArg);
|
||||
if (!keepConstsInModule)
|
||||
{
|
||||
for (auto& ctorArg : customAttribute.mCtorArgs)
|
||||
{
|
||||
if (ctorArg.IsConst())
|
||||
CurrentAddToConstHolder(ctorArg);
|
||||
}
|
||||
}
|
||||
|
||||
if (attributesDirective->mAttributeTargetSpecifier != NULL)
|
||||
|
@ -11626,10 +11638,10 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri
|
|||
ValidateCustomAttributes(customAttributes, attrTarget);
|
||||
}
|
||||
|
||||
BfCustomAttributes* BfModule::GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs, BfCaptureInfo* captureInfo)
|
||||
BfCustomAttributes* BfModule::GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, BfGetCustomAttributesFlags flags, BfCaptureInfo* captureInfo)
|
||||
{
|
||||
BfCustomAttributes* customAttributes = new BfCustomAttributes();
|
||||
GetCustomAttributes(customAttributes, attributesDirective, attrType, allowNonConstArgs, captureInfo);
|
||||
GetCustomAttributes(customAttributes, attributesDirective, attrType, flags, captureInfo);
|
||||
return customAttributes;
|
||||
}
|
||||
|
||||
|
@ -11834,7 +11846,7 @@ bool BfModule::TryGetConstString(BfIRConstHolder* constHolder, BfIRValue irValue
|
|||
BfStringPoolEntry* entry = NULL;
|
||||
if (mContext->mStringObjectIdMap.TryGetValue(stringId, &entry))
|
||||
{
|
||||
str = entry->mString;
|
||||
str += entry->mString;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -15479,7 +15491,11 @@ void BfModule::CreateDelegateInvokeMethod()
|
|||
|
||||
mBfIRBuilder->AddBlock(doneBB);
|
||||
mBfIRBuilder->SetInsertPoint(doneBB);
|
||||
if ((mCurMethodInstance->mReturnType->IsValuelessType()) ||
|
||||
if (mCurMethodInstance->mReturnType->IsVar())
|
||||
{
|
||||
// Do nothing
|
||||
}
|
||||
else if ((mCurMethodInstance->mReturnType->IsValuelessType()) ||
|
||||
((!mIsComptimeModule) && (mCurMethodInstance->GetStructRetIdx() != -1)))
|
||||
{
|
||||
mBfIRBuilder->CreateRetVoid();
|
||||
|
@ -18477,6 +18493,11 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
{
|
||||
BP_ZONE_F("BfModule::ProcessMethod %s", BP_DYN_STR(methodInstance->mMethodDef->mName.c_str()));
|
||||
|
||||
if (mIsComptimeModule)
|
||||
{
|
||||
BF_ASSERT(!mCompiler->IsAutocomplete());
|
||||
}
|
||||
|
||||
if (mAwaitingInitFinish)
|
||||
FinishInit();
|
||||
|
||||
|
@ -21547,6 +21568,10 @@ void BfModule::GetMethodCustomAttributes(BfMethodInstance* methodInstance)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto delegateInfo = typeInstance->GetDelegateInfo();
|
||||
if ((delegateInfo != NULL) && (methodInstance->mMethodDef->mMethodType == BfMethodType_Normal) && (methodInstance->mMethodDef->mName == "Invoke"))
|
||||
methodInstance->mCallingConvention = delegateInfo->mCallingConvention;
|
||||
}
|
||||
|
||||
void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& mangledName, bool isTemporaryFunc, bool* outIsIntrinsic)
|
||||
|
@ -22157,6 +22182,13 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
|||
|
||||
if (resolvedReturnType == NULL)
|
||||
resolvedReturnType = GetPrimitiveType(BfTypeCode_Var);
|
||||
|
||||
if ((methodDef->mIsReadOnly) && (!resolvedReturnType->IsRef()))
|
||||
{
|
||||
if (auto methodDeclaration = BfNodeDynCast<BfMethodDeclaration>(methodInstance->mMethodDef->mMethodDeclaration))
|
||||
if (methodDeclaration->mReadOnlySpecifier != NULL)
|
||||
Fail("Readonly specifier is only valid on 'ref' return types", methodDeclaration->mReadOnlySpecifier);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1383,6 +1383,13 @@ enum BfDeferredBlockFlags
|
|||
BfDeferredBlockFlag_MoveNewBlocksToEnd = 8,
|
||||
};
|
||||
|
||||
enum BfGetCustomAttributesFlags
|
||||
{
|
||||
BfGetCustomAttributesFlags_None = 0,
|
||||
BfGetCustomAttributesFlags_AllowNonConstArgs = 1,
|
||||
BfGetCustomAttributesFlags_KeepConstsInModule = 2
|
||||
};
|
||||
|
||||
class BfVDataExtEntry
|
||||
{
|
||||
public:
|
||||
|
@ -1567,8 +1574,8 @@ public:
|
|||
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);
|
||||
void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, BfGetCustomAttributesFlags flags = BfGetCustomAttributesFlags_None, BfCaptureInfo* captureInfo = NULL);
|
||||
BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, BfGetCustomAttributesFlags flags = BfGetCustomAttributesFlags_None, BfCaptureInfo* captureInfo = NULL);
|
||||
BfCustomAttributes* GetCustomAttributes(BfTypeDef* typeDef);
|
||||
void FinishAttributeState(BfAttributeState* attributeState);
|
||||
void ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered, int& alignOverride, BfType*& underlyingArrayType, int& underlyingArraySize);
|
||||
|
@ -1744,13 +1751,15 @@ public:
|
|||
void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
|
||||
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src);
|
||||
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode);
|
||||
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes);
|
||||
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes, bool underlyingTypeDeferred);
|
||||
void CEMixin(BfAstNode* refNode, const StringImpl& src);
|
||||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind);
|
||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
|
||||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
|
||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);
|
||||
void DoCEEmit(BfMethodInstance* methodInstance);
|
||||
void DoPopulateType_TypeAlias(BfTypeInstance* typeAlias);
|
||||
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
||||
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
||||
void DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType);
|
||||
void DoPopulateType_CeCheckEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred);
|
||||
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
||||
static BfModule* GetModuleFor(BfType* type);
|
||||
void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance);
|
||||
|
@ -1844,6 +1853,7 @@ public:
|
|||
void CheckIdentifierFixit(BfAstNode* node);
|
||||
void TypeRefNotFound(BfTypeReference* typeRef, const char* appendName = NULL);
|
||||
bool ValidateTypeWildcard(BfTypeReference* typeRef, bool isAttributeRef);
|
||||
void GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention);
|
||||
BfType* ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0, int numGenericArgs = 0);
|
||||
BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true);
|
||||
BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray<BfTypeReference*>* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0);
|
||||
|
|
|
@ -704,23 +704,13 @@ void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
|||
|
||||
void BfModule::AddFieldDependency(BfTypeInstance* typeInstance, BfFieldInstance* fieldInstance, BfType* fieldType)
|
||||
{
|
||||
auto fieldTypeInstance = fieldType->ToTypeInstance();
|
||||
auto depFlag = fieldType->IsValueType() ? BfDependencyMap::DependencyFlag_ValueTypeMemberData : BfDependencyMap::DependencyFlag_PtrMemberData;
|
||||
AddDependency(fieldType, typeInstance, depFlag);
|
||||
|
||||
if (fieldTypeInstance == NULL)
|
||||
{
|
||||
auto underlyingType = fieldType->GetUnderlyingType();
|
||||
if (underlyingType != NULL)
|
||||
AddFieldDependency(typeInstance, fieldInstance, underlyingType);
|
||||
return;
|
||||
}
|
||||
|
||||
auto depFlag = fieldTypeInstance->IsValueType() ? BfDependencyMap::DependencyFlag_ValueTypeMemberData : BfDependencyMap::DependencyFlag_PtrMemberData;
|
||||
AddDependency(fieldTypeInstance, typeInstance, depFlag);
|
||||
|
||||
if ((fieldTypeInstance->IsStruct()) && (fieldTypeInstance->IsGenericTypeInstance()))
|
||||
if ((fieldType->IsStruct()) && (fieldType->IsGenericTypeInstance()))
|
||||
{
|
||||
// When we're a generic struct, our data layout can depend on our generic parameters as well
|
||||
auto genericTypeInstance = (BfTypeInstance*)fieldTypeInstance;
|
||||
auto genericTypeInstance = (BfTypeInstance*)fieldType;
|
||||
for (auto typeGenericArg : genericTypeInstance->mGenericTypeInfo->mTypeGenericArguments)
|
||||
AddFieldDependency(typeInstance, fieldInstance, typeGenericArg);
|
||||
}
|
||||
|
@ -1189,7 +1179,10 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
|
|||
}
|
||||
}
|
||||
|
||||
BfLogSysM("PopulateType: %p %s populateType:%d ResolveOnly:%d Reified:%d AutoComplete:%d Ctx:%p Mod:%p TypeId:%d\n", resolvedTypeRef, TypeToString(resolvedTypeRef, BfTypeNameFlags_None).c_str(), populateType, mCompiler->mIsResolveOnly, mIsReified, mCompiler->IsAutocomplete(), mContext, this, resolvedTypeRef->mTypeId);
|
||||
BfTypeDef* typeDef = NULL;
|
||||
if (typeInstance != NULL)
|
||||
typeDef = typeInstance->mTypeDef;
|
||||
BfLogSysM("PopulateType: %p %s populateType:%d ResolveOnly:%d Reified:%d AutoComplete:%d Ctx:%p Mod:%p TypeId:%d TypeDef:%p\n", resolvedTypeRef, TypeToString(resolvedTypeRef, BfTypeNameFlags_None).c_str(), populateType, mCompiler->mIsResolveOnly, mIsReified, mCompiler->IsAutocomplete(), mContext, this, resolvedTypeRef->mTypeId, typeDef);
|
||||
|
||||
BF_ASSERT(!resolvedTypeRef->IsDeleting());
|
||||
}
|
||||
|
@ -2078,7 +2071,7 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
|||
{
|
||||
for (int ifaceTypeId : ceEmitContext->mInterfaces)
|
||||
typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId);
|
||||
|
||||
|
||||
if (ceEmitContext->mEmitData.IsEmpty())
|
||||
return;
|
||||
|
||||
|
@ -2133,7 +2126,7 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
|||
}
|
||||
}
|
||||
|
||||
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes)
|
||||
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes, bool underlyingTypeDeferred)
|
||||
{
|
||||
BfTypeInstance* iComptimeTypeApply = NULL;
|
||||
for (auto& customAttribute : customAttributes->mAttributes)
|
||||
|
@ -2166,12 +2159,8 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
|||
if (!attrType->IsValuelessType())
|
||||
args.Add(attrVal);
|
||||
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
|
||||
|
||||
//TESTING
|
||||
// mCompiler->mCEMachine->ReleaseContext(ceContext);
|
||||
// ceContext = mCompiler->mCEMachine->AllocContext();
|
||||
// ceContext->mMemory.mSize = ceContext->mMemory.mAllocSize;
|
||||
|
||||
|
||||
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
|
||||
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
|
||||
|
||||
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
|
||||
|
@ -2182,7 +2171,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
|||
// We populated before we could finish
|
||||
AssertErrorState();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
auto owner = methodInstance->GetOwner();
|
||||
int typeId = owner->mTypeId;
|
||||
|
@ -2302,18 +2291,18 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
|
|||
FinishCEParseContext(refNode, mCurTypeInstance, &ceParseContext);
|
||||
}
|
||||
|
||||
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind)
|
||||
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred)
|
||||
{
|
||||
HashSet<BfTypeInstance*> foundAttributes;
|
||||
if (ceEmitContext != NULL)
|
||||
{
|
||||
if (typeInstance->mCustomAttributes != NULL)
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes);
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes, underlyingTypeDeferred);
|
||||
|
||||
for (auto& fieldInstance : typeInstance->mFieldInstances)
|
||||
{
|
||||
if (fieldInstance.mCustomAttributes != NULL)
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes);
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes, underlyingTypeDeferred);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2355,7 +2344,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
|||
if (onCompileAttribute == NULL)
|
||||
continue;
|
||||
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes);
|
||||
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes, underlyingTypeDeferred);
|
||||
|
||||
if (onCompileAttribute->mCtorArgs.size() < 1)
|
||||
continue;
|
||||
|
@ -2383,6 +2372,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
|||
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
|
||||
}
|
||||
|
||||
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
|
||||
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
|
||||
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
|
||||
|
||||
|
@ -2451,11 +2441,11 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
|||
// }
|
||||
}
|
||||
|
||||
void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers)
|
||||
void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred)
|
||||
{
|
||||
CeEmitContext ceEmitContext;
|
||||
ceEmitContext.mType = typeInstance;
|
||||
ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit);
|
||||
ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit, underlyingTypeDeferred);
|
||||
hadNewMembers = (typeInstance->mTypeDef->mEmitParent != NULL);
|
||||
|
||||
if (ceEmitContext.mFailed)
|
||||
|
@ -2609,7 +2599,7 @@ void BfModule::DoPopulateType_SetGenericDependencies(BfTypeInstance* genericType
|
|||
}
|
||||
|
||||
void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
||||
{
|
||||
{
|
||||
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCurTypeInstance, typeAlias);
|
||||
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCurMethodInstance, NULL);
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodState(mCurMethodState, NULL);
|
||||
|
@ -2685,6 +2675,176 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
|||
DoPopulateType_SetGenericDependencies(typeAlias);
|
||||
}
|
||||
|
||||
void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType)
|
||||
{
|
||||
if (typeInstance->IsEnum())
|
||||
{
|
||||
int64 min = 0;
|
||||
int64 max = 0;
|
||||
|
||||
bool isFirst = true;
|
||||
|
||||
if (typeInstance->mTypeInfoEx == NULL)
|
||||
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
|
||||
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
auto fieldDef = fieldInstance->GetFieldDef();
|
||||
if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()))
|
||||
{
|
||||
if (fieldInstance->mConstIdx == -1)
|
||||
continue;
|
||||
|
||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||
BF_ASSERT((constant->mTypeCode == BfTypeCode_Int64) || (!underlyingTypeDeferred));
|
||||
|
||||
if (isFirst)
|
||||
{
|
||||
min = constant->mInt64;
|
||||
max = constant->mInt64;
|
||||
isFirst = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = BF_MIN(constant->mInt64, min);
|
||||
max = BF_MAX(constant->mInt64, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typeInstance->mTypeInfoEx->mMinValue = min;
|
||||
typeInstance->mTypeInfoEx->mMaxValue = max;
|
||||
|
||||
if (underlyingTypeDeferred)
|
||||
{
|
||||
BfTypeCode typeCode;
|
||||
|
||||
if ((min >= -0x80) && (max <= 0x7F))
|
||||
typeCode = BfTypeCode_Int8;
|
||||
else if ((min >= 0) && (max <= 0xFF))
|
||||
typeCode = BfTypeCode_UInt8;
|
||||
else if ((min >= -0x8000) && (max <= 0x7FFF))
|
||||
typeCode = BfTypeCode_Int16;
|
||||
else if ((min >= 0) && (max <= 0xFFFF))
|
||||
typeCode = BfTypeCode_UInt16;
|
||||
else if ((min >= -0x80000000LL) && (max <= 0x7FFFFFFF))
|
||||
typeCode = BfTypeCode_Int32;
|
||||
else if ((min >= 0) && (max <= 0xFFFFFFFFLL))
|
||||
typeCode = BfTypeCode_UInt32;
|
||||
else
|
||||
typeCode = BfTypeCode_Int64;
|
||||
|
||||
if (typeCode != BfTypeCode_Int64)
|
||||
{
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
if (fieldInstance->mConstIdx == -1)
|
||||
continue;
|
||||
if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry())
|
||||
continue;
|
||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||
BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64);
|
||||
fieldInstance->mConstIdx = newConstant.mId;
|
||||
}
|
||||
}
|
||||
|
||||
BfType* underlyingType = GetPrimitiveType(typeCode);
|
||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||
fieldInstance->mResolvedType = underlyingType;
|
||||
fieldInstance->mDataSize = underlyingType->mSize;
|
||||
|
||||
typeInstance->mTypeInfoEx->mUnderlyingType = underlyingType;
|
||||
|
||||
typeInstance->mSize = underlyingType->mSize;
|
||||
typeInstance->mAlign = underlyingType->mAlign;
|
||||
typeInstance->mInstSize = underlyingType->mSize;
|
||||
typeInstance->mInstAlign = underlyingType->mAlign;
|
||||
|
||||
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags & ~BfTypeRebuildFlag_UnderlyingTypeDeferred);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BF_ASSERT(!underlyingTypeDeferred);
|
||||
}
|
||||
|
||||
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
|
||||
{
|
||||
typeInstance->mAlign = unionInnerType->mAlign;
|
||||
|
||||
int lastTagId = -1;
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
auto fieldDef = fieldInstance->GetFieldDef();
|
||||
if ((fieldDef != NULL) && (fieldInstance->mDataIdx < 0))
|
||||
{
|
||||
BF_ASSERT(fieldInstance->mResolvedType->mAlign >= 1);
|
||||
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, fieldInstance->mResolvedType->mAlign);
|
||||
lastTagId = -fieldInstance->mDataIdx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||
//BF_ASSERT(fieldInstance->mResolvedType == NULL);
|
||||
BfPrimitiveType* discriminatorType;
|
||||
if (lastTagId > 0x7FFFFFFF) // HOW?
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int64);
|
||||
else if (lastTagId > 0x7FFF)
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int32);
|
||||
else if (lastTagId > 0x7F)
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int16);
|
||||
else
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int8);
|
||||
fieldInstance->mResolvedType = discriminatorType;
|
||||
|
||||
fieldInstance->mDataOffset = unionInnerType->mSize;
|
||||
fieldInstance->mDataIdx = 2; // 0 = base, 1 = payload, 2 = discriminator
|
||||
if (!typeInstance->mIsPacked)
|
||||
{
|
||||
if ((fieldInstance->mDataOffset % discriminatorType->mAlign) != 0)
|
||||
{
|
||||
fieldInstance->mDataOffset = BF_ALIGN(fieldInstance->mDataOffset, discriminatorType->mAlign);
|
||||
fieldInstance->mDataIdx++; // Add room for explicit padding
|
||||
}
|
||||
}
|
||||
|
||||
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, discriminatorType->mAlign);
|
||||
typeInstance->mSize = fieldInstance->mDataOffset + discriminatorType->mSize;
|
||||
|
||||
typeInstance->mInstSize = typeInstance->mSize;
|
||||
typeInstance->mInstAlign = typeInstance->mAlign;
|
||||
|
||||
if (dataMemberHashCtx != NULL)
|
||||
{
|
||||
dataMemberHashCtx->Mixin(unionInnerType->mTypeId);
|
||||
dataMemberHashCtx->Mixin(discriminatorType->mTypeId);
|
||||
}
|
||||
|
||||
typeInstance->mMergedFieldDataCount = 1; // Track it as a single entry
|
||||
}
|
||||
}
|
||||
|
||||
void BfModule::DoPopulateType_CeCheckEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred)
|
||||
{
|
||||
if (!typeInstance->IsEnum())
|
||||
return;
|
||||
if ((!underlyingTypeDeferred) && (!typeInstance->IsPayloadEnum()))
|
||||
return;
|
||||
if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL))
|
||||
return;
|
||||
|
||||
BfType* unionInnerType = NULL;
|
||||
if (typeInstance->mIsUnion)
|
||||
{
|
||||
SetAndRestoreValue<BfTypeState::ResolveKind> prevResolveKind(mContext->mCurTypeState->mResolveKind, BfTypeState::ResolveKind_UnionInnerType);
|
||||
unionInnerType = typeInstance->GetUnionInnerType();
|
||||
}
|
||||
DoPopulateType_FinishEnum(typeInstance, underlyingTypeDeferred, NULL, unionInnerType);
|
||||
}
|
||||
|
||||
void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
||||
{
|
||||
if (populateType == BfPopulateType_Identity)
|
||||
|
@ -3732,6 +3892,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
if (typeInstance->mTypeDef != innerTypeInst->mTypeDef)
|
||||
{
|
||||
// Rebuild with proper typedef (generally from inner type comptime emission)
|
||||
BfLogSysM("Boxed type %p overriding typeDef to %p from inner type %p\n", typeInstance, innerTypeInst->mTypeDef, innerType);
|
||||
typeInstance->mTypeDef = innerTypeInst->mTypeDef;
|
||||
DoPopulateType(resolvedTypeRef, populateType);
|
||||
return;
|
||||
|
@ -4056,7 +4217,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
|
||||
typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
|
||||
bool hadNewMembers = false;
|
||||
DoCEEmit(typeInstance, hadNewMembers);
|
||||
DoCEEmit(typeInstance, hadNewMembers, underlyingTypeDeferred);
|
||||
|
||||
if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
|
||||
typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit;
|
||||
|
@ -4660,7 +4821,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
typeInstance->mDefineState = BfTypeDefineState_Defined;
|
||||
if (!typeInstance->IsBoxed())
|
||||
{
|
||||
ExecuteCEOnCompile(NULL, typeInstance, BfCEOnCompileKind_TypeDone);
|
||||
ExecuteCEOnCompile(NULL, typeInstance, BfCEOnCompileKind_TypeDone, underlyingTypeDeferred);
|
||||
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
|
||||
return;
|
||||
}
|
||||
|
@ -4831,151 +4992,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
BfLogSysM("Setting underlying type %p %d\n", typeInstance, underlyingTypeDeferred);
|
||||
}
|
||||
|
||||
if (typeInstance->IsEnum())
|
||||
{
|
||||
int64 min = 0;
|
||||
int64 max = 0;
|
||||
|
||||
bool isFirst = true;
|
||||
|
||||
if (typeInstance->mTypeInfoEx == NULL)
|
||||
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
|
||||
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
auto fieldDef = fieldInstance->GetFieldDef();
|
||||
if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()))
|
||||
{
|
||||
if (fieldInstance->mConstIdx == -1)
|
||||
continue;
|
||||
|
||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||
BF_ASSERT((constant->mTypeCode == BfTypeCode_Int64) || (!underlyingTypeDeferred));
|
||||
|
||||
if (isFirst)
|
||||
{
|
||||
min = constant->mInt64;
|
||||
max = constant->mInt64;
|
||||
isFirst = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = BF_MIN(constant->mInt64, min);
|
||||
max = BF_MAX(constant->mInt64, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typeInstance->mTypeInfoEx->mMinValue = min;
|
||||
typeInstance->mTypeInfoEx->mMaxValue = max;
|
||||
|
||||
if (underlyingTypeDeferred)
|
||||
{
|
||||
BfTypeCode typeCode;
|
||||
|
||||
if ((min >= -0x80) && (max <= 0x7F))
|
||||
typeCode = BfTypeCode_Int8;
|
||||
else if ((min >= 0) && (max <= 0xFF))
|
||||
typeCode = BfTypeCode_UInt8;
|
||||
else if ((min >= -0x8000) && (max <= 0x7FFF))
|
||||
typeCode = BfTypeCode_Int16;
|
||||
else if ((min >= 0) && (max <= 0xFFFF))
|
||||
typeCode = BfTypeCode_UInt16;
|
||||
else if ((min >= -0x80000000LL) && (max <= 0x7FFFFFFF))
|
||||
typeCode = BfTypeCode_Int32;
|
||||
else if ((min >= 0) && (max <= 0xFFFFFFFFLL))
|
||||
typeCode = BfTypeCode_UInt32;
|
||||
else
|
||||
typeCode = BfTypeCode_Int64;
|
||||
|
||||
if (typeCode != BfTypeCode_Int64)
|
||||
{
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
if (fieldInstance->mConstIdx == -1)
|
||||
continue;
|
||||
if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry())
|
||||
continue;
|
||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||
BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64);
|
||||
fieldInstance->mConstIdx = newConstant.mId;
|
||||
}
|
||||
}
|
||||
|
||||
underlyingType = GetPrimitiveType(typeCode);
|
||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||
fieldInstance->mResolvedType = underlyingType;
|
||||
fieldInstance->mDataSize = underlyingType->mSize;
|
||||
|
||||
typeInstance->mTypeInfoEx->mUnderlyingType = underlyingType;
|
||||
|
||||
typeInstance->mSize = underlyingType->mSize;
|
||||
typeInstance->mAlign = underlyingType->mAlign;
|
||||
typeInstance->mInstSize = underlyingType->mSize;
|
||||
typeInstance->mInstAlign = underlyingType->mAlign;
|
||||
|
||||
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags & ~BfTypeRebuildFlag_UnderlyingTypeDeferred);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BF_ASSERT(!underlyingTypeDeferred);
|
||||
}
|
||||
|
||||
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
|
||||
{
|
||||
typeInstance->mAlign = unionInnerType->mAlign;
|
||||
|
||||
int lastTagId = -1;
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
auto fieldDef = fieldInstance->GetFieldDef();
|
||||
if ((fieldDef != NULL) && (fieldInstance->mDataIdx < 0))
|
||||
{
|
||||
BF_ASSERT(fieldInstance->mResolvedType->mAlign >= 1);
|
||||
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, fieldInstance->mResolvedType->mAlign);
|
||||
lastTagId = -fieldInstance->mDataIdx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||
BF_ASSERT(fieldInstance->mResolvedType == NULL);
|
||||
BfPrimitiveType* discriminatorType;
|
||||
if (lastTagId > 0x7FFFFFFF) // HOW?
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int64);
|
||||
else if (lastTagId > 0x7FFF)
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int32);
|
||||
else if (lastTagId > 0x7F)
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int16);
|
||||
else
|
||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int8);
|
||||
fieldInstance->mResolvedType = discriminatorType;
|
||||
|
||||
fieldInstance->mDataOffset = unionInnerType->mSize;
|
||||
fieldInstance->mDataIdx = 2; // 0 = base, 1 = payload, 2 = discriminator
|
||||
if (!isPacked)
|
||||
{
|
||||
if ((fieldInstance->mDataOffset % discriminatorType->mAlign) != 0)
|
||||
{
|
||||
fieldInstance->mDataOffset = BF_ALIGN(fieldInstance->mDataOffset, discriminatorType->mAlign);
|
||||
fieldInstance->mDataIdx++; // Add room for explicit padding
|
||||
}
|
||||
}
|
||||
|
||||
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, discriminatorType->mAlign);
|
||||
typeInstance->mSize = fieldInstance->mDataOffset + discriminatorType->mSize;
|
||||
|
||||
typeInstance->mInstSize = typeInstance->mSize;
|
||||
typeInstance->mInstAlign = typeInstance->mAlign;
|
||||
|
||||
dataMemberHashCtx.Mixin(unionInnerType->mTypeId);
|
||||
dataMemberHashCtx.Mixin(discriminatorType->mTypeId);
|
||||
|
||||
typeInstance->mMergedFieldDataCount = 1; // Track it as a single entry
|
||||
}
|
||||
DoPopulateType_FinishEnum(typeInstance, underlyingTypeDeferred, &dataMemberHashCtx, unionInnerType);
|
||||
|
||||
if (!typeInstance->IsBoxed())
|
||||
{
|
||||
|
@ -5633,7 +5650,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
}
|
||||
}
|
||||
|
||||
if (typeInstance->mTypeDef->mProject->mTargetType == BfTargetType_BeefTest)
|
||||
if (methodInstance->mMethodDef->mDeclaringType->mProject->mTargetType == BfTargetType_BeefTest)
|
||||
{
|
||||
if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mTestAttributeTypeDef)))
|
||||
{
|
||||
|
@ -7556,7 +7573,7 @@ BfTypeDef* BfModule::ResolveGenericInstanceDef(BfGenericInstanceTypeRef* generic
|
|||
{
|
||||
BfTypeLookupError error;
|
||||
error.mRefNode = typeRef;
|
||||
BfTypeDef* typeDef = FindTypeDef(typeRef, NULL, &error, numGenericParams);
|
||||
BfTypeDef* typeDef = FindTypeDef(typeRef, NULL, &error, numGenericParams, resolveFlags);
|
||||
if (typeDef != NULL)
|
||||
{
|
||||
BfAutoComplete* autoComplete = NULL;
|
||||
|
@ -7587,6 +7604,8 @@ BfTypeDef* BfModule::ResolveGenericInstanceDef(BfGenericInstanceTypeRef* generic
|
|||
if (typeRef->IsA<BfNamedTypeReference>())
|
||||
{
|
||||
String findName = typeRef->ToString();
|
||||
if ((resolveFlags & BfResolveTypeRefFlag_Attribute) != 0)
|
||||
findName += "Attribute";
|
||||
if ((mCurTypeInstance != NULL) && (mCurTypeInstance->IsGenericTypeInstance()))
|
||||
{
|
||||
auto genericTypeInst = (BfTypeInstance*)mCurTypeInstance;
|
||||
|
@ -9341,6 +9360,28 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod
|
|||
return BfTypedValue();
|
||||
}
|
||||
|
||||
void BfModule::GetDelegateTypeRefAttributes(BfDelegateTypeRef* delegateTypeRef, BfCallingConvention& callingConvention)
|
||||
{
|
||||
if (delegateTypeRef->mAttributes == NULL)
|
||||
return;
|
||||
|
||||
BfCaptureInfo captureInfo;
|
||||
auto customAttributes = GetCustomAttributes(delegateTypeRef->mAttributes, (BfAttributeTargets)(BfAttributeTargets_DelegateTypeRef | BfAttributeTargets_FunctionTypeRef), BfGetCustomAttributesFlags_KeepConstsInModule);
|
||||
if (customAttributes != NULL)
|
||||
{
|
||||
auto linkNameAttr = customAttributes->Get(mCompiler->mCallingConventionAttributeTypeDef);
|
||||
if (linkNameAttr != NULL)
|
||||
{
|
||||
if (linkNameAttr->mCtorArgs.size() == 1)
|
||||
{
|
||||
auto constant = mBfIRBuilder->GetConstant(linkNameAttr->mCtorArgs[0]);
|
||||
if (constant != NULL)
|
||||
callingConvention = (BfCallingConvention)constant->mInt32;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags, int numGenericArgs)
|
||||
{
|
||||
BP_ZONE("BfModule::ResolveTypeRef");
|
||||
|
@ -10078,11 +10119,15 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
}
|
||||
|
||||
BfResolvedTypeSet::LookupContext lookupCtx;
|
||||
lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & (BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_IgnoreLookupError | BfResolveTypeRefFlag_DisallowComptime | BfResolveTypeRefFlag_AllowInferredSizedArray));
|
||||
lookupCtx.mResolveFlags = (BfResolveTypeRefFlags)(resolveFlags & (BfResolveTypeRefFlag_NoCreate | BfResolveTypeRefFlag_IgnoreLookupError |
|
||||
BfResolveTypeRefFlag_DisallowComptime | BfResolveTypeRefFlag_AllowInferredSizedArray | BfResolveTypeRefFlag_Attribute));
|
||||
lookupCtx.mRootTypeRef = typeRef;
|
||||
lookupCtx.mRootTypeDef = typeDef;
|
||||
lookupCtx.mModule = this;
|
||||
BfResolvedTypeSet::Entry* resolvedEntry = NULL;
|
||||
if (auto delegateTypeRef = BfNodeDynCastExact<BfDelegateTypeRef>(typeRef))
|
||||
GetDelegateTypeRefAttributes(delegateTypeRef, lookupCtx.mCallingConvention);
|
||||
|
||||
auto inserted = mContext->mResolvedTypes.Insert(typeRef, &lookupCtx, &resolvedEntry);
|
||||
|
||||
if (resolvedEntry == NULL)
|
||||
|
@ -10355,7 +10400,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
BfTypeVector genericArgs;
|
||||
|
||||
BfType* type = NULL;
|
||||
BfTypeDef* typeDef = ResolveGenericInstanceDef(genericTypeInstRef, &type);
|
||||
BfTypeDef* typeDef = ResolveGenericInstanceDef(genericTypeInstRef, &type, resolveFlags);
|
||||
if(ambiguousTypeDef != NULL)
|
||||
ShowAmbiguousTypeError(typeRef, typeDef, ambiguousTypeDef);
|
||||
if (typeDef == NULL)
|
||||
|
@ -10542,8 +10587,11 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
wantGeneric = true;
|
||||
if (type->IsUnspecializedType())
|
||||
isUnspecialized = true;
|
||||
BF_ASSERT(!type->IsVar());
|
||||
|
||||
if (type->IsVar())
|
||||
{
|
||||
mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
|
||||
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
|
||||
}
|
||||
types.push_back(type);
|
||||
names.push_back(fieldName);
|
||||
}
|
||||
|
@ -10834,7 +10882,9 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
dlgType->mIsUnspecializedTypeVariation = isUnspecialized;
|
||||
delegateType = dlgType;
|
||||
}
|
||||
|
||||
|
||||
delegateInfo->mCallingConvention = lookupCtx.mCallingConvention;
|
||||
|
||||
Val128 hashContext;
|
||||
|
||||
BfTypeDef* typeDef = new BfTypeDef();
|
||||
|
@ -13090,9 +13140,11 @@ BfTypedValue BfModule::Cast(BfAstNode* srcNode, const BfTypedValue& typedVal, Bf
|
|||
|
||||
auto fromMethodInst = GetRawMethodByName(fromTypeInst, "Invoke", -1, true);
|
||||
auto toMethodInst = GetRawMethodByName(toTypeInst, "Invoke", -1, true);
|
||||
|
||||
|
||||
auto toDelegateInfo = toTypeInst->GetDelegateInfo();
|
||||
|
||||
if ((fromMethodInst != NULL) && (toMethodInst != NULL) &&
|
||||
(fromMethodInst->mMethodDef->mCallingConvention == toMethodInst->mMethodDef->mCallingConvention) &&
|
||||
(fromMethodInst->mCallingConvention == toMethodInst->mCallingConvention) &&
|
||||
(fromMethodInst->mMethodDef->mIsMutating == toMethodInst->mMethodDef->mIsMutating) &&
|
||||
(fromMethodInst->mReturnType == toMethodInst->mReturnType) &&
|
||||
(fromMethodInst->GetParamCount() == toMethodInst->GetParamCount()))
|
||||
|
@ -13673,6 +13725,25 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
|||
str += "delegate ";
|
||||
else
|
||||
str += "function ";
|
||||
|
||||
if (delegateInfo->mCallingConvention != BfCallingConvention_Unspecified)
|
||||
{
|
||||
str += "[CallingConvention(";
|
||||
switch (delegateInfo->mCallingConvention)
|
||||
{
|
||||
case BfCallingConvention_Cdecl:
|
||||
str += ".Cdecl";
|
||||
break;
|
||||
case BfCallingConvention_Stdcall:
|
||||
str += ".Stdcall";
|
||||
break;
|
||||
case BfCallingConvention_Fastcall:
|
||||
str += ".Fastcall";
|
||||
break;
|
||||
}
|
||||
str += ")] ";
|
||||
}
|
||||
|
||||
DoTypeToString(str, delegateInfo->mReturnType, typeNameFlags, genericMethodNameOverrides);
|
||||
str += "(";
|
||||
|
||||
|
|
|
@ -3800,13 +3800,14 @@ BF_EXPORT bool BF_CALLTYPE BfParser_Reduce(BfParser* bfParser, BfPassInstance* b
|
|||
}
|
||||
|
||||
static Array<int> gCharMapping;
|
||||
BF_EXPORT const char* BF_CALLTYPE BfParser_Format(BfParser* bfParser, int formatStart, int formatEnd, int** outCharMapping)
|
||||
BF_EXPORT const char* BF_CALLTYPE BfParser_Format(BfParser* bfParser, int formatStart, int formatEnd, int** outCharMapping, int maxCol)
|
||||
{
|
||||
BP_ZONE("BfParser_Reduce");
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
outString.clear();
|
||||
gCharMapping.Clear();
|
||||
BfPrinter bfPrinter(bfParser->mRootNode, bfParser->mSidechannelRootNode, bfParser->mErrorRootNode);
|
||||
bfPrinter.mMaxCol = maxCol;
|
||||
bfPrinter.mFormatStart = formatStart;
|
||||
bfPrinter.mFormatEnd = formatEnd;
|
||||
bfPrinter.mCharMapping = &gCharMapping;
|
||||
|
|
|
@ -300,11 +300,8 @@ int BfPrinter::CalcOrigLineSpacing(BfAstNode* bfAstNode, int* lineStartIdx)
|
|||
|
||||
void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
||||
{
|
||||
if ((!mOutString.IsEmpty()) && (!isspace((uint8)mOutString[mOutString.mLength - 1])))
|
||||
{
|
||||
Write(" ");
|
||||
}
|
||||
|
||||
bool startsWithSpace = false;
|
||||
|
||||
bool wasExpectingNewLine = mExpectingNewLine;
|
||||
|
||||
mTriviaIdx = std::max(mTriviaIdx, node->GetTriviaStart());
|
||||
|
@ -315,12 +312,17 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
|||
for (int i = mTriviaIdx; i < srcEnd; i++)
|
||||
{
|
||||
char c = astNodeSrc->mSrc[i];
|
||||
if ((i == mTriviaIdx) && (isspace((uint8)c)))
|
||||
startsWithSpace = true;
|
||||
|
||||
if ((c == '\n') && (i < node->GetSrcStart()))
|
||||
crCount++;
|
||||
if (((c != ' ') && (c != '\t')) || (!mReformatting))
|
||||
endIdx = i + 1;
|
||||
}
|
||||
|
||||
bool wantsPrefixSpace = (!mOutString.IsEmpty()) && (!isspace((uint8)mOutString[mOutString.mLength - 1]));
|
||||
|
||||
bool expectingNewLine = mNextStateModify.mWantNewLineIdx != mVirtualNewLineIdx;
|
||||
|
||||
int startIdx = mTriviaIdx;
|
||||
|
@ -333,7 +335,10 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
|||
if ((origLineSpacing != -1) && (lineStart != -1))
|
||||
{
|
||||
for (int i = 0; i < crCount; i++)
|
||||
{
|
||||
Write("\n");
|
||||
wantsPrefixSpace = false;
|
||||
}
|
||||
startIdx = node->GetSrcStart();
|
||||
// Leave left-aligned preprocessor nodes
|
||||
if ((node->GetSourceData()->mSrc[node->GetSrcStart()] != '#') || (origLineSpacing > 0))
|
||||
|
@ -439,6 +444,10 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
|||
bool emitChar = true;
|
||||
|
||||
char c = astNodeSrc->mSrc[srcIdx];
|
||||
|
||||
if ((wantsPrefixSpace) && (isspace((uint8)c)))
|
||||
wantsPrefixSpace = false;
|
||||
|
||||
if (c == '\n')
|
||||
{
|
||||
isNewLine = true;
|
||||
|
@ -592,7 +601,12 @@ void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
|||
}
|
||||
}
|
||||
|
||||
FlushIndent();
|
||||
if (wantsPrefixSpace)
|
||||
{
|
||||
mQueuedSpaceCount++;
|
||||
wantsPrefixSpace = false;
|
||||
}
|
||||
FlushIndent();
|
||||
|
||||
for (int idx = startIdx; idx <= BF_MIN(srcIdx, endIdx - 1); idx++)
|
||||
{
|
||||
|
@ -1038,6 +1052,8 @@ void BfPrinter::Visit(BfLabelableStatement* labelableStmt)
|
|||
void BfPrinter::Visit(BfCommentNode* commentNode)
|
||||
{
|
||||
WriteIgnoredNode(commentNode);
|
||||
if (commentNode->mCommentKind == BfCommentKind_Line)
|
||||
ExpectNewLine();
|
||||
}
|
||||
|
||||
void BfPrinter::Visit(BfPreprocesorIgnoredSectionNode* preprocesorIgnoredSection)
|
||||
|
@ -1569,8 +1585,9 @@ void BfPrinter::Visit(BfDelegateTypeRef* typeRef)
|
|||
|
||||
VisitChild(typeRef->mTypeToken);
|
||||
ExpectSpace();
|
||||
VisitChild(typeRef->mReturnType);
|
||||
VisitChild(typeRef->mAttributes);
|
||||
ExpectSpace();
|
||||
VisitChild(typeRef->mReturnType);
|
||||
VisitChild(typeRef->mOpenParen);
|
||||
|
||||
for (int i = 0; i < (int)typeRef->mParams.size(); i++)
|
||||
|
|
|
@ -281,9 +281,52 @@ bool BfReducer::IsTypeReference(BfAstNode* checkNode, BfToken successToken, int*
|
|||
|
||||
int endNode = -1;
|
||||
|
||||
bool failed = false;
|
||||
|
||||
// Return type
|
||||
auto checkNode = mVisitorPos.GetCurrent();
|
||||
if ((checkNode == NULL) || (!IsTypeReference(checkNode, BfToken_LParen, &endNode, couldBeExpr, isGenericType, isTuple)))
|
||||
if (auto checkToken = BfNodeDynCast<BfTokenNode>(checkNode))
|
||||
{
|
||||
if (checkToken->mToken == BfToken_LBracket)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
mVisitorPos.mReadPos++;
|
||||
checkNode = mVisitorPos.GetCurrent();
|
||||
if (checkNode == NULL)
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (BfNodeIsA<BfBlock>(checkNode))
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (checkToken = BfNodeDynCast<BfTokenNode>(checkNode))
|
||||
{
|
||||
if (checkToken->mToken == BfToken_RBracket)
|
||||
{
|
||||
mVisitorPos.mReadPos++;
|
||||
checkNode = mVisitorPos.GetCurrent();
|
||||
break;
|
||||
}
|
||||
if ((checkToken->mToken != BfToken_Comma) &&
|
||||
(checkToken->mToken != BfToken_Dot) &&
|
||||
(checkToken->mToken != BfToken_LParen) &&
|
||||
(checkToken->mToken != BfToken_RParen))
|
||||
{
|
||||
failed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((failed) || (checkNode == NULL) || (!IsTypeReference(checkNode, BfToken_LParen, &endNode, couldBeExpr, isGenericType, isTuple)))
|
||||
{
|
||||
if (outEndNode != NULL)
|
||||
*outEndNode = endNode;
|
||||
|
@ -4806,6 +4849,14 @@ BfTypeReference* BfReducer::DoCreateTypeRef(BfAstNode* firstNode, CreateTypeRefF
|
|||
ReplaceNode(firstNode, delegateTypeRef);
|
||||
MEMBER_SET(delegateTypeRef, mTypeToken, tokenNode);
|
||||
|
||||
auto nextToken = BfNodeDynCast<BfTokenNode>(mVisitorPos.GetNext());
|
||||
if ((nextToken != NULL) && (nextToken->mToken == BfToken_LBracket))
|
||||
{
|
||||
mVisitorPos.MoveNext();
|
||||
auto attribs = CreateAttributeDirective(nextToken);
|
||||
MEMBER_SET_CHECKED(delegateTypeRef, mAttributes, attribs);
|
||||
}
|
||||
|
||||
auto returnType = CreateTypeRefAfter(delegateTypeRef);
|
||||
MEMBER_SET_CHECKED(delegateTypeRef, mReturnType, returnType);
|
||||
|
||||
|
|
|
@ -2664,6 +2664,8 @@ int BfArrayType::GetLengthBitCount()
|
|||
|
||||
int BfMethodRefType::GetCaptureDataCount()
|
||||
{
|
||||
if (mMethodRef == NULL)
|
||||
return 0;
|
||||
return (int)mDataToParamIdx.size();
|
||||
}
|
||||
|
||||
|
@ -3021,7 +3023,8 @@ int BfResolvedTypeSet::DirectHash(BfTypeReference* typeRef, LookupContext* ctx,
|
|||
BfResolveTypeRefFlags resolveFlags = ctx->mResolveFlags;
|
||||
if ((flags & BfHashFlag_AllowGenericParamConstValue) != 0)
|
||||
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags | BfResolveTypeRefFlag_AllowGenericParamConstValue);
|
||||
|
||||
if (!isHeadType)
|
||||
resolveFlags = (BfResolveTypeRefFlags)(resolveFlags &~ BfResolveTypeRefFlag_Attribute);
|
||||
auto resolvedType = ctx->mModule->ResolveTypeRef(typeRef, BfPopulateType_Identity, resolveFlags);
|
||||
if (resolvedType == NULL)
|
||||
{
|
||||
|
@ -3669,6 +3672,8 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
|
|||
BfDelegateInfo* rhsDelegateInfo = rhs->GetDelegateInfo();
|
||||
if (lhsInst->mTypeDef->mIsDelegate != rhsInst->mTypeDef->mIsDelegate)
|
||||
return false;
|
||||
if (lhsDelegateInfo->mCallingConvention != rhsDelegateInfo->mCallingConvention)
|
||||
return false;
|
||||
|
||||
auto lhsMethodDef = lhsInst->mTypeDef->mMethods[0];
|
||||
auto rhsMethodDef = rhsInst->mTypeDef->mMethods[0];
|
||||
|
@ -3917,7 +3922,9 @@ bool BfResolvedTypeSet::GenericTypeEquals(BfTypeInstance* lhsGenericType, BfType
|
|||
return false;
|
||||
}
|
||||
|
||||
BfTypeDef* elementTypeDef = ctx->mModule->ResolveGenericInstanceDef(rhsGenericTypeInstRef);
|
||||
BfTypeDef* elementTypeDef = ctx->mModule->ResolveGenericInstanceDef(rhsGenericTypeInstRef, NULL, ctx->mResolveFlags);
|
||||
if (elementTypeDef == NULL)
|
||||
return false;
|
||||
if (elementTypeDef->GetDefinition() != lhsGenericType->mTypeDef->GetDefinition())
|
||||
return false;
|
||||
|
||||
|
@ -4088,8 +4095,16 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
|
|||
|
||||
if ((lhs->IsDelegate()) != rhsIsDelegate)
|
||||
return false;
|
||||
|
||||
BfCallingConvention rhsCallingConvention = BfCallingConvention_Unspecified;
|
||||
if (ctx->mRootTypeRef == rhsDelegateType)
|
||||
rhsCallingConvention = ctx->mCallingConvention;
|
||||
else
|
||||
ctx->mModule->GetDelegateTypeRefAttributes(rhsDelegateType, rhsCallingConvention);
|
||||
if (lhsDelegateInfo->mCallingConvention != rhsCallingConvention)
|
||||
return false;
|
||||
if (!Equals(lhsDelegateInfo->mReturnType, rhsDelegateType->mReturnType, ctx))
|
||||
return false;
|
||||
return false;
|
||||
|
||||
bool isMutating = true;
|
||||
|
||||
|
|
|
@ -452,6 +452,7 @@ public:
|
|||
Array<BfType*> mParams;
|
||||
bool mHasExplicitThis;
|
||||
bool mHasVarArgs;
|
||||
BfCallingConvention mCallingConvention;
|
||||
|
||||
public:
|
||||
BfDelegateInfo()
|
||||
|
@ -459,6 +460,7 @@ public:
|
|||
mReturnType = NULL;
|
||||
mHasExplicitThis = false;
|
||||
mHasVarArgs = false;
|
||||
mCallingConvention = BfCallingConvention_Unspecified;
|
||||
}
|
||||
|
||||
~BfDelegateInfo()
|
||||
|
@ -569,6 +571,7 @@ public:
|
|||
virtual bool IsBoolean() { return false; }
|
||||
virtual bool IsInteger() { return false; }
|
||||
virtual bool IsIntegral() { return false; }
|
||||
virtual bool IsIntegralOrBool() { return false; }
|
||||
virtual bool IsIntPtr() { return false; }
|
||||
virtual bool IsSigned() { return false; }
|
||||
virtual bool IsSignedInt() { return false; }
|
||||
|
@ -625,6 +628,7 @@ public:
|
|||
virtual bool IsValueTypeOrValueTypePtr() override { return true; }
|
||||
virtual bool IsBoolean() override { return mTypeDef->mTypeCode == BfTypeCode_Boolean; }
|
||||
virtual bool IsIntegral() override { return (mTypeDef->mTypeCode >= BfTypeCode_Int8) && (mTypeDef->mTypeCode <= BfTypeCode_Char32); }
|
||||
virtual bool IsIntegralOrBool() override { return (mTypeDef->mTypeCode >= BfTypeCode_Boolean) && (mTypeDef->mTypeCode <= BfTypeCode_Char32); }
|
||||
virtual bool IsInteger() override { return (mTypeDef->mTypeCode >= BfTypeCode_Int8) && (mTypeDef->mTypeCode <= BfTypeCode_UIntUnknown); }
|
||||
virtual bool IsIntPtr() override { return (mTypeDef->mTypeCode == BfTypeCode_IntPtr) || (mTypeDef->mTypeCode == BfTypeCode_UIntPtr); }
|
||||
virtual bool IsIntPtrable() override
|
||||
|
@ -1582,7 +1586,9 @@ enum BfAttributeTargets : int32
|
|||
BfAttributeTargets_Delete = 0x80000,
|
||||
BfAttributeTargets_Alias = 0x100000,
|
||||
BfAttributeTargets_Block = 0x200000,
|
||||
BfAttributeTargets_All = 0x3FFFFF
|
||||
BfAttributeTargets_DelegateTypeRef = 0x400000,
|
||||
BfAttributeTargets_FunctionTypeRef = 0x800000,
|
||||
BfAttributeTargets_All = 0xFFFFFF
|
||||
};
|
||||
|
||||
enum BfAttributeFlags : int8
|
||||
|
@ -1823,23 +1829,7 @@ public:
|
|||
String mEmitData;
|
||||
};
|
||||
|
||||
class BfCeTypeInfo
|
||||
{
|
||||
public:
|
||||
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
|
||||
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
|
||||
Array<int> mPendingInterfaces;
|
||||
Val128 mHash;
|
||||
bool mFailed;
|
||||
BfCeTypeInfo* mNext;
|
||||
|
||||
public:
|
||||
BfCeTypeInfo()
|
||||
{
|
||||
mFailed = false;
|
||||
mNext = NULL;
|
||||
}
|
||||
};
|
||||
class BfCeTypeInfo;
|
||||
|
||||
// Instance of struct or class
|
||||
class BfTypeInstance : public BfDependedType
|
||||
|
@ -2526,6 +2516,7 @@ public:
|
|||
BfType* mRootResolvedType;
|
||||
Dictionary<BfTypeReference*, BfType*> mResolvedTypeMap;
|
||||
BfResolveTypeRefFlags mResolveFlags;
|
||||
BfCallingConvention mCallingConvention;
|
||||
bool mHadVar;
|
||||
bool mFailed;
|
||||
|
||||
|
@ -2540,6 +2531,7 @@ public:
|
|||
mFailed = false;
|
||||
mHadVar = false;
|
||||
mResolveFlags = BfResolveTypeRefFlag_None;
|
||||
mCallingConvention = BfCallingConvention_Unspecified;
|
||||
}
|
||||
|
||||
BfType* GetCachedResolvedType(BfTypeReference* typeReference);
|
||||
|
|
|
@ -3455,7 +3455,9 @@ void BfModule::VisitCodeBlock(BfBlock* block)
|
|||
}
|
||||
else if ((mCurMethodInstance->IsMixin()) && (mCurMethodState->mCurScope == &mCurMethodState->mHeadScope))
|
||||
{
|
||||
// Silently allow...
|
||||
// Only in mixin definition - result ignored
|
||||
CreateValueFromExpression(expr);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -3925,6 +3927,10 @@ void BfModule::Visit(BfDeleteStatement* deleteStmt)
|
|||
{
|
||||
if (genericParamInst->mGenericParamFlags & (BfGenericParamFlag_Delete | BfGenericParamFlag_Var))
|
||||
return;
|
||||
if (genericParamInst->mGenericParamFlags & BfGenericParamFlag_StructPtr)
|
||||
return;
|
||||
if ((genericParamInst->mGenericParamFlags & BfGenericParamFlag_Struct) && (checkType->IsPointer()))
|
||||
return;
|
||||
Fail(StrFormat("Must add 'where %s : delete' constraint to generic parameter to delete generic type '%s'",
|
||||
genericParamInst->GetGenericParamDef()->mName.c_str(), TypeToString(val.mType).c_str()), deleteStmt->mExpression);
|
||||
return;
|
||||
|
|
|
@ -498,7 +498,9 @@ BfImportKind BfMethodDef::GetImportKindFromPath(const StringImpl& filePath)
|
|||
{
|
||||
String fileExt = GetFileExtension(filePath);
|
||||
|
||||
if ((fileExt.Equals(".DLL", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
|
||||
if ((fileExt.Equals(".DYLIB", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
|
||||
(fileExt.Equals(".SO", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
|
||||
(fileExt.Equals(".DLL", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
|
||||
(fileExt.Equals(".EXE", StringImpl::CompareKind_OrdinalIgnoreCase)))
|
||||
{
|
||||
return BfImportKind_Import_Dynamic;
|
||||
|
@ -4159,11 +4161,12 @@ BF_EXPORT const char* BF_CALLTYPE BfSystem_GetNamespaceSearch(BfSystem* bfSystem
|
|||
return outString.c_str();
|
||||
}
|
||||
|
||||
BF_EXPORT BfProject* BF_CALLTYPE BfSystem_CreateProject(BfSystem* bfSystem, const char* projectName)
|
||||
BF_EXPORT BfProject* BF_CALLTYPE BfSystem_CreateProject(BfSystem* bfSystem, const char* projectName, const char* projectDir)
|
||||
{
|
||||
AutoCrit autoCrit(bfSystem->mDataLock);
|
||||
BfProject* bfProject = new BfProject();
|
||||
bfProject->mName = projectName;
|
||||
bfProject->mDirectory = projectDir;
|
||||
bfProject->mSystem = bfSystem;
|
||||
bfProject->mIdx = (int)bfSystem->mProjects.size();
|
||||
bfSystem->mProjects.push_back(bfProject);
|
||||
|
|
|
@ -1180,6 +1180,7 @@ public:
|
|||
BfSystem* mSystem;
|
||||
String mName;
|
||||
String mSafeName;
|
||||
String mDirectory;
|
||||
Array<BfProject*> mDependencies;
|
||||
BfTargetType mTargetType;
|
||||
BfCodeGenOptions mCodeGenOptions;
|
||||
|
|
|
@ -5,7 +5,10 @@
|
|||
#include "BfParser.h"
|
||||
#include "BfReducer.h"
|
||||
#include "BfExprEvaluator.h"
|
||||
#include "BfResolvePass.h"
|
||||
#include "../Backend/BeIRCodeGen.h"
|
||||
#include "BeefySysLib/platform/PlatformHelper.h"
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "BeefySysLib/third_party/utf8proc/utf8proc.h"
|
||||
|
@ -301,6 +304,24 @@ static int DoubleToString(double d, char* outStr)
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CeInternalData::~CeInternalData()
|
||||
{
|
||||
switch (mKind)
|
||||
{
|
||||
case Kind_File:
|
||||
BfpFile_Release(mFile);
|
||||
break;
|
||||
case Kind_FindFileData:
|
||||
BfpFindFileData_Release(mFindFileData);
|
||||
break;
|
||||
case Kind_Spawn:
|
||||
BfpSpawn_Release(mSpawn);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CeFunction::~CeFunction()
|
||||
{
|
||||
BF_ASSERT(mId == -1);
|
||||
|
@ -1261,6 +1282,12 @@ void CeBuilder::HandleParams()
|
|||
void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance* dupMethodInstance)
|
||||
{
|
||||
SetAndRestoreValue<BfMethodState*> prevMethodStateInConstEval(mCeMachine->mCeModule->mCurMethodState, NULL);
|
||||
BfAutoComplete* prevAutoComplete = NULL;
|
||||
if (mCeMachine->mCeModule->mCompiler->mResolvePassData != NULL)
|
||||
{
|
||||
prevAutoComplete = mCeMachine->mCeModule->mCompiler->mResolvePassData->mAutoComplete;
|
||||
mCeMachine->mCeModule->mCompiler->mResolvePassData->mAutoComplete = NULL;
|
||||
}
|
||||
|
||||
auto irCodeGen = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen;
|
||||
auto irBuilder = mCeMachine->mCeModule->mBfIRBuilder;
|
||||
|
@ -1275,6 +1302,9 @@ void CeBuilder::ProcessMethod(BfMethodInstance* methodInstance, BfMethodInstance
|
|||
mCeMachine->mCeModule->ProcessMethod(dupMethodInstance, true);
|
||||
irCodeGen->SetState(beState);
|
||||
irBuilder->SetState(irState);
|
||||
|
||||
if (mCeMachine->mCeModule->mCompiler->mResolvePassData != NULL)
|
||||
mCeMachine->mCeModule->mCompiler->mResolvePassData->mAutoComplete = prevAutoComplete;
|
||||
}
|
||||
|
||||
void CeBuilder::Build()
|
||||
|
@ -1312,7 +1342,7 @@ void CeBuilder::Build()
|
|||
mCeMachine->mCeModule->mStaticFieldRefs.Clear();
|
||||
|
||||
int startFunctionCount = (int)beModule->mFunctions.size();
|
||||
ProcessMethod(methodInstance, &dupMethodInstance);
|
||||
ProcessMethod(methodInstance, &dupMethodInstance);
|
||||
if (mCeFunction->mInitializeState == CeFunction::InitializeState_Initialized)
|
||||
return;
|
||||
|
||||
|
@ -2873,6 +2903,7 @@ CeContext::CeContext()
|
|||
mCeMachine = NULL;
|
||||
mReflectTypeIdOffset = -1;
|
||||
mExecuteId = -1;
|
||||
mStackSize = -1;
|
||||
|
||||
mCurTargetSrc = NULL;
|
||||
mHeap = new ContiguousHeap();
|
||||
|
@ -2886,6 +2917,7 @@ CeContext::CeContext()
|
|||
CeContext::~CeContext()
|
||||
{
|
||||
delete mHeap;
|
||||
BF_ASSERT(mInternalDataMap.IsEmpty());
|
||||
}
|
||||
|
||||
BfError* CeContext::Fail(const StringImpl& error)
|
||||
|
@ -2996,11 +3028,23 @@ BfError* CeContext::Fail(const CeFrame& curFrame, const StringImpl& str)
|
|||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
void CeContext::AddRebuild(const CeRebuildKey& key, const CeRebuildValue& value)
|
||||
{
|
||||
if (mCurModule == NULL)
|
||||
return;
|
||||
if (mCurModule->mCurTypeInstance == NULL)
|
||||
return;
|
||||
if (mCurModule->mCurTypeInstance->mCeTypeInfo == NULL)
|
||||
mCurModule->mCurTypeInstance->mCeTypeInfo = new BfCeTypeInfo();
|
||||
mCurModule->mCurTypeInstance->mCeTypeInfo->mRebuildMap[key] = value;
|
||||
mCurModule->mCompiler->mHasComptimeRebuilds = true;
|
||||
}
|
||||
|
||||
uint8* CeContext::CeMalloc(int size)
|
||||
{
|
||||
#ifdef CE_ENABLE_HEAP
|
||||
auto heapRef = mHeap->Alloc(size);
|
||||
auto ceAddr = BF_CE_STACK_SIZE + heapRef;
|
||||
auto ceAddr = mStackSize + heapRef;
|
||||
int sizeDelta = (ceAddr + size) - mMemory.mSize;
|
||||
if (sizeDelta > 0)
|
||||
mMemory.GrowUninitialized(sizeDelta);
|
||||
|
@ -3013,7 +3057,7 @@ uint8* CeContext::CeMalloc(int size)
|
|||
bool CeContext::CeFree(addr_ce addr)
|
||||
{
|
||||
#ifdef CE_ENABLE_HEAP
|
||||
ContiguousHeap::AllocRef heapRef = addr - BF_CE_STACK_SIZE;
|
||||
ContiguousHeap::AllocRef heapRef = addr - mStackSize;
|
||||
return mHeap->Free(heapRef);
|
||||
#else
|
||||
return true;
|
||||
|
@ -3702,6 +3746,19 @@ BfIRValue CeContext::CreateConstant(BfModule* module, uint8* ptr, BfType* bfType
|
|||
charPtr = (char*)(instData + ptrOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64 allocSizeVal = *(int64*)(instData + allocSizeOffset);
|
||||
if ((allocSizeVal & 0x4000000000000000LL) != 0)
|
||||
{
|
||||
int32 ptrVal = *(int32*)(instData + ptrOffset);
|
||||
charPtr = (char*)(ptrVal + memStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
charPtr = (char*)(instData + ptrOffset);
|
||||
}
|
||||
}
|
||||
|
||||
CE_CREATECONST_CHECKPTR(charPtr, lenVal);
|
||||
String str(charPtr, lenVal);
|
||||
|
@ -4085,7 +4142,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
if (ceFunction->mInitializeState < CeFunction::InitializeState_Initialized)
|
||||
mCeMachine->PrepareFunction(ceFunction, NULL);
|
||||
|
||||
auto stackPtr = &mMemory[0] + BF_CE_STACK_SIZE;
|
||||
auto stackPtr = &mMemory[0] + mStackSize;
|
||||
auto* memStart = &mMemory[0];
|
||||
|
||||
BfTypeInstance* thisType = methodInstance->GetOwner();
|
||||
|
@ -4107,6 +4164,23 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
allocThisSize += appendSizeConstant->mInt32;
|
||||
}
|
||||
|
||||
if (allocThisSize >= mStackSize / 4)
|
||||
{
|
||||
// Resize stack a reasonable size
|
||||
mStackSize = BF_ALIGN(allocThisSize, 0x100000) + BF_CE_DEFAULT_STACK_SIZE;
|
||||
int64 memSize = mStackSize + BF_CE_DEFAULT_HEAP_SIZE;
|
||||
if (memSize > BF_CE_MAX_MEMORY)
|
||||
{
|
||||
Fail("Return value too large (>2GB)");
|
||||
return BfTypedValue();
|
||||
}
|
||||
|
||||
if (memSize > mMemory.mSize)
|
||||
mMemory.Resize(memSize);
|
||||
stackPtr = &mMemory[0] + mStackSize;
|
||||
memStart = &mMemory[0];
|
||||
}
|
||||
|
||||
stackPtr -= allocThisSize;
|
||||
auto allocThisPtr = stackPtr;
|
||||
memset(allocThisPtr, 0, allocThisSize);
|
||||
|
@ -4123,6 +4197,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
{
|
||||
stackPtr -= ceModule->mSystem->mPtrSize;
|
||||
memset(stackPtr, 0, ceModule->mSystem->mPtrSize);
|
||||
*(addr_ce*)(stackPtr) = (addr_ce)(allocThisInstAddr + thisType->mInstSize);
|
||||
allocAppendIdxAddr = stackPtr - memStart;
|
||||
}
|
||||
|
||||
|
@ -4256,7 +4331,14 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
}
|
||||
|
||||
BfType* usedReturnType = returnType;
|
||||
BfIRValue constVal = CreateConstant(module, retPtr, returnType, &usedReturnType);
|
||||
BfIRValue constVal;
|
||||
if (returnType->IsObject())
|
||||
{
|
||||
addr_ce retAddr = retPtr - memStart;
|
||||
constVal = CreateConstant(module, (uint8*)&retAddr, returnType, &usedReturnType);
|
||||
}
|
||||
else
|
||||
constVal = CreateConstant(module, retPtr, returnType, &usedReturnType);
|
||||
if (constVal)
|
||||
returnValue = BfTypedValue(constVal, usedReturnType);
|
||||
else
|
||||
|
@ -4289,9 +4371,10 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
}
|
||||
|
||||
#define CE_CHECKALLOC(SIZE) \
|
||||
if ((SIZE < 0) || (uintptr)memSize + (uintptr)SIZE > BF_CE_MAX_MEMORY) \
|
||||
if ((SIZE < 0) || (SIZE >= 0x80000000LL) || ((uintptr)memSize + (uintptr)SIZE > BF_CE_MAX_MEMORY)) \
|
||||
{ \
|
||||
_Fail("Maximum memory size exceeded"); \
|
||||
_Fail("Maximum memory size exceeded (2GB)"); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
// This check will fail for addresses < 64K (null pointer), or out-of-bounds
|
||||
|
@ -4302,12 +4385,65 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
return false; \
|
||||
}
|
||||
#define CE_CHECKADDR(ADDR, SIZE) \
|
||||
if (((ADDR) - 0x10000) + (SIZE) > (memSize - 0x10000)) \
|
||||
if (((ADDR) < 0x10000) || ((ADDR) + (SIZE) > memSize)) \
|
||||
{ \
|
||||
_Fail("Access violation"); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CE_CHECKADDR_STR(STRNAME, ADDR) \
|
||||
{ \
|
||||
addr_ce checkAddr = ADDR; \
|
||||
while (true) \
|
||||
{ \
|
||||
if ((uintptr)checkAddr >= (uintptr)memSize) \
|
||||
{ \
|
||||
break; \
|
||||
} \
|
||||
if (memStart[checkAddr] == 0) \
|
||||
{ \
|
||||
CE_CHECKADDR(ADDR, checkAddr - ADDR + 1); \
|
||||
STRNAME = String::MakeRef((char*)memStart + ADDR, checkAddr - ADDR + 1); \
|
||||
break; \
|
||||
} \
|
||||
checkAddr++; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define CE_GET_INTERNAL(VAR, ID, KIND) \
|
||||
if (!mInternalDataMap.TryGetValue((int)ID, &VAR)) \
|
||||
{ \
|
||||
_Fail("Invalid internal resource id"); \
|
||||
return false; \
|
||||
} \
|
||||
if (VAR->mKind != KIND) \
|
||||
{ \
|
||||
_Fail("Invalid internal resource kind"); \
|
||||
return false; \
|
||||
} \
|
||||
if (VAR->mReleased) \
|
||||
{ \
|
||||
_Fail("Resource already released"); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CE_REMOVE_INTERNAL(VAR, ID, KIND) \
|
||||
if (!mInternalDataMap.Remove((int)ID, &VAR)) \
|
||||
{ \
|
||||
_Fail("Invalid internal resource id"); \
|
||||
return false; \
|
||||
} \
|
||||
if (VAR->mKind != KIND) \
|
||||
{ \
|
||||
_Fail("Invalid internal resource kind"); \
|
||||
return false; \
|
||||
} \
|
||||
if (VAR->mReleased) \
|
||||
{ \
|
||||
_Fail("Resource already released"); \
|
||||
return false; \
|
||||
}
|
||||
|
||||
#define CE_GETINST(T) *((T*)(instPtr += sizeof(T)) - 1)
|
||||
#define CE_GETFRAME(T) *(T*)(framePtr + *((int32*)(instPtr += sizeof(int32)) - 1))
|
||||
#define CEOP_BIN(OP, T) \
|
||||
|
@ -4422,7 +4558,7 @@ BfTypedValue CeContext::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
instPtr = &ceFunction->mCode[0]; \
|
||||
CE_CHECKSTACK();
|
||||
|
||||
static void CeSetAddrVal(void* ptr, addr_ce val, int32 ptrSize)
|
||||
static void CeSetAddrVal(void* ptr, int64 val, int32 ptrSize)
|
||||
{
|
||||
if (ptrSize == 4)
|
||||
*(int32*)(ptr) = (int32)val;
|
||||
|
@ -4490,7 +4626,11 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_Malloc)
|
||||
{
|
||||
int32 size = *(int32*)((uint8*)stackPtr + 4);
|
||||
int64 size;
|
||||
if (ptrSize == 4)
|
||||
size = *(int32*)((uint8*)stackPtr + 4);
|
||||
else
|
||||
size = *(int64*)((uint8*)stackPtr + 8);
|
||||
CE_CHECKALLOC(size);
|
||||
uint8* ptr = CeMalloc(size);
|
||||
CeSetAddrVal(stackPtr + 0, ptr - memStart, ptrSize);
|
||||
|
@ -4532,6 +4672,19 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
charPtr = (char*)(strInst + ptrOffset);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int64 allocSizeVal = *(int64*)(strInst + allocSizeOffset);
|
||||
if ((allocSizeVal & 0x4000000000000000LL) != 0)
|
||||
{
|
||||
int32 ptrVal = *(int32*)(strInst + ptrOffset);
|
||||
charPtr = (char*)(ptrVal + memStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
charPtr = (char*)(strInst + ptrOffset);
|
||||
}
|
||||
}
|
||||
|
||||
int32 ptrVal = *(int32*)(strInst + ptrOffset);
|
||||
|
||||
|
@ -4559,13 +4712,21 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite_Int)
|
||||
{
|
||||
int32 intVal = *(int32*)((uint8*)stackPtr + 0);
|
||||
OutputDebugStrF("Debug Val: %d\n", intVal);
|
||||
if (ceModule->mSystem->mPtrSize == 4)
|
||||
{
|
||||
int32 intVal = *(int32*)((uint8*)stackPtr + 0);
|
||||
OutputDebugStrF("Debug Val: %d %X\n", intVal, intVal);
|
||||
}
|
||||
else
|
||||
{
|
||||
int64 intVal = *(int64*)((uint8*)stackPtr + 0);
|
||||
OutputDebugStrF("Debug Val: %lld %llX\n", intVal, intVal);
|
||||
}
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType)
|
||||
{
|
||||
addr_ce objAddr = *(addr_ce*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
|
||||
CE_CHECKADDR(addr_ce, 4);
|
||||
CE_CHECKADDR(objAddr, 4);
|
||||
int32 typeId = *(int32*)(objAddr + memStart);
|
||||
|
||||
auto reflectType = GetReflectType(typeId);
|
||||
|
@ -4911,7 +5072,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
addr_ce strAddr = *(addr_ce*)((uint8*)stackPtr + 8);
|
||||
addr_ce endAddr = *(addr_ce*)((uint8*)stackPtr + 8 + ptrSize);
|
||||
|
||||
addr_ce checkAddr = strAddr;
|
||||
addr_ce checkAddr = strAddr;
|
||||
while (true)
|
||||
{
|
||||
if ((uintptr)checkAddr >= (uintptr)memSize)
|
||||
|
@ -4921,10 +5082,11 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
}
|
||||
if (memStart[checkAddr] == 0)
|
||||
break;
|
||||
checkAddr++;
|
||||
}
|
||||
CE_CHECKADDR(strAddr, checkAddr - strAddr + 1);
|
||||
|
||||
char* strPtr = (char*)(memStart + strAddr);
|
||||
char* strPtr = (char*)(memStart + strAddr);
|
||||
char** endPtr = NULL;
|
||||
if (endAddr != NULL)
|
||||
endPtr = (char**)(memStart + endAddr);
|
||||
|
@ -4959,7 +5121,292 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
memcpy(memStart + strAddr, str, count + 1);
|
||||
result = count;
|
||||
}
|
||||
else
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Close)
|
||||
{
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
BfpFile_Close(internalData->mFile, (BfpFileResult*)(memStart + outResultAddr));
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Create)
|
||||
{
|
||||
void* resultPtr = ((uint8*)stackPtr + 0);
|
||||
addr_ce nameAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
int createKind = *(int*)((uint8*)stackPtr + ptrSize + ptrSize);
|
||||
int createFlags = *(int*)((uint8*)stackPtr + ptrSize + ptrSize + 4);
|
||||
int createFileAttrs = *(int*)((uint8*)stackPtr + ptrSize + ptrSize + 4 + 4);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + 4 + 4 + 4);
|
||||
|
||||
String path;
|
||||
CE_CHECKADDR_STR(path, nameAddr);
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
BfProject* activeProject = NULL;
|
||||
auto activeTypeDef = mCurModule->GetActiveTypeDef();
|
||||
if (activeTypeDef != NULL)
|
||||
activeProject = activeTypeDef->mProject;
|
||||
if (activeProject != NULL)
|
||||
path = GetAbsPath(path, activeProject->mDirectory);
|
||||
|
||||
auto bfpFile = BfpFile_Create(path.c_str(), (BfpFileCreateKind)createKind, (BfpFileCreateFlags)createFlags, (BfpFileAttributes)createFileAttrs, (BfpFileResult*)(memStart + outResultAddr));
|
||||
if (bfpFile != NULL)
|
||||
{
|
||||
if ((createKind == BfpFileCreateKind_OpenExisting) || (createKind == BfpFileCreateKind_OpenAlways))
|
||||
{
|
||||
auto timeStamp = BfpFile_GetTime_LastWrite(path.c_str());
|
||||
if (timeStamp != 0)
|
||||
{
|
||||
CeRebuildKey rebuildKey;
|
||||
rebuildKey.mKind = CeRebuildKey::Kind_File;
|
||||
rebuildKey.mString = path;
|
||||
|
||||
CeRebuildValue rebuildValue;
|
||||
rebuildValue.mInt = timeStamp;
|
||||
|
||||
AddRebuild(rebuildKey, rebuildValue);
|
||||
}
|
||||
}
|
||||
|
||||
CeInternalData* internalData = new CeInternalData();
|
||||
internalData->mKind = CeInternalData::Kind_File;
|
||||
internalData->mFile = bfpFile;
|
||||
mInternalDataMap[++mCurHandleId] = internalData;
|
||||
CeSetAddrVal(resultPtr, mCurHandleId, ptrSize);
|
||||
}
|
||||
else
|
||||
CeSetAddrVal(resultPtr, 0, ptrSize);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Flush)
|
||||
{
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
BfpFile_Flush(internalData->mFile);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_GetFileSize)
|
||||
{
|
||||
int64& result = *(int64*)((uint8*)stackPtr + 0);
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 8);
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
result = BfpFile_GetFileSize(internalData->mFile);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Read)
|
||||
{
|
||||
void* resultPtr = ((uint8*)stackPtr + 0);
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
addr_ce bufferPtr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize);
|
||||
intptr bufferSize = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize);
|
||||
int timeoutMS = *(int32*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize);
|
||||
|
||||
CE_CHECKADDR(bufferPtr, bufferSize);
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
int64 result = BfpFile_Read(internalData->mFile, memStart + bufferPtr, bufferSize, timeoutMS, (BfpFileResult*)(memStart + outResultAddr));
|
||||
CeSetAddrVal(resultPtr, result, ptrSize);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Release)
|
||||
{
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_REMOVE_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
delete internalData;
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Seek)
|
||||
{
|
||||
int64& result = *(int64*)((uint8*)stackPtr + 0);
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 8);
|
||||
int64 offset = *(int64*)((uint8*)stackPtr + 8 + ptrSize);
|
||||
int seekKind = *(int*)((uint8*)stackPtr + 8 + ptrSize + 8);
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
result = BfpFile_Seek(internalData->mFile, offset, (BfpFileSeekKind)seekKind);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Truncate)
|
||||
{
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
BfpFile_Truncate(internalData->mFile, (BfpFileResult*)(memStart + outResultAddr));
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpFile_Write)
|
||||
{
|
||||
void* resultPtr = ((uint8*)stackPtr + 0);
|
||||
addr_ce fileId = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
addr_ce bufferPtr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize);
|
||||
intptr bufferSize = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize);
|
||||
int timeoutMS = *(int32*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize);
|
||||
|
||||
CE_CHECKADDR(bufferPtr, bufferSize);
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)fileId, CeInternalData::Kind_File);
|
||||
int64 result = BfpFile_Write(internalData->mFile, memStart + bufferPtr, bufferSize, timeoutMS, (outResultAddr == 0) ? NULL : (BfpFileResult*)(memStart + outResultAddr));
|
||||
CeSetAddrVal(resultPtr, result, ptrSize);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_Create)
|
||||
{
|
||||
void* resultPtr = ((uint8*)stackPtr + 0);
|
||||
addr_ce targetPathAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
addr_ce argsAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize);
|
||||
addr_ce workingDirAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize);
|
||||
addr_ce envAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize);
|
||||
int flags = *(int*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize + ptrSize + ptrSize + 4);
|
||||
|
||||
String targetPath;
|
||||
CE_CHECKADDR_STR(targetPath, targetPathAddr);
|
||||
String args;
|
||||
if (argsAddr != 0)
|
||||
CE_CHECKADDR_STR(args, argsAddr);
|
||||
String workingDir;
|
||||
if (workingDirAddr != 0)
|
||||
CE_CHECKADDR_STR(workingDir, workingDirAddr);
|
||||
String env;
|
||||
if (envAddr != 0)
|
||||
CE_CHECKADDR_STR(env, envAddr);
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
if ((targetPath.Contains('/')) || (targetPath.Contains('\\')))
|
||||
{
|
||||
BfProject* activeProject = NULL;
|
||||
auto activeTypeDef = mCurModule->GetActiveTypeDef();
|
||||
if (activeTypeDef != NULL)
|
||||
activeProject = activeTypeDef->mProject;
|
||||
if (activeProject != NULL)
|
||||
targetPath = GetAbsPath(targetPath, activeProject->mDirectory);
|
||||
}
|
||||
|
||||
auto bfpSpawn = BfpSpawn_Create(targetPath.c_str(),
|
||||
(argsAddr == 0) ? NULL : args.c_str(),
|
||||
(workingDirAddr == 0) ? NULL : workingDir.c_str(),
|
||||
(envAddr == 0) ? NULL : env.c_str(), (BfpSpawnFlags)flags, (outResultAddr == 0) ? NULL : (BfpSpawnResult*)(memStart + outResultAddr));
|
||||
if (bfpSpawn != NULL)
|
||||
{
|
||||
CeInternalData* internalData = new CeInternalData();
|
||||
internalData->mKind = CeInternalData::Kind_Spawn;
|
||||
internalData->mSpawn = bfpSpawn;
|
||||
mInternalDataMap[++mCurHandleId] = internalData;
|
||||
CeSetAddrVal(resultPtr, mCurHandleId, ptrSize);
|
||||
}
|
||||
else
|
||||
CeSetAddrVal(resultPtr, 0, ptrSize);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_GetStdHandles)
|
||||
{
|
||||
addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
addr_ce outStdInAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
|
||||
addr_ce outStdOutAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize);
|
||||
addr_ce outStdErrAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize);
|
||||
|
||||
CE_CHECKADDR(outStdInAddr, ptrSize);
|
||||
CE_CHECKADDR(outStdOutAddr, ptrSize);
|
||||
CE_CHECKADDR(outStdErrAddr, ptrSize);
|
||||
|
||||
BfpFile* outStdIn = NULL;
|
||||
BfpFile* outStdOut = NULL;
|
||||
BfpFile* outStdErr = NULL;
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn);
|
||||
BfpSpawn_GetStdHandles(internalData->mSpawn,
|
||||
(outStdInAddr != 0) ? &outStdIn : NULL,
|
||||
(outStdOutAddr != 0) ? &outStdOut : NULL,
|
||||
(outStdErrAddr != 0) ? &outStdErr : NULL);
|
||||
|
||||
auto _SetHandle = [&](addr_ce addr, BfpFile* file)
|
||||
{
|
||||
if (addr == 0)
|
||||
return;
|
||||
if (file != NULL)
|
||||
{
|
||||
CeInternalData* internalData = new CeInternalData();
|
||||
internalData->mKind = CeInternalData::Kind_File;
|
||||
internalData->mFile = file;
|
||||
mInternalDataMap[++mCurHandleId] = internalData;
|
||||
CeSetAddrVal(memStart + addr, mCurHandleId, ptrSize);
|
||||
}
|
||||
};
|
||||
|
||||
_SetHandle(outStdInAddr, outStdIn);
|
||||
_SetHandle(outStdOutAddr, outStdOut);
|
||||
_SetHandle(outStdErrAddr, outStdErr);
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_Kill)
|
||||
{
|
||||
addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
int exitCode = *(int*)((uint8*)stackPtr + ptrSize);
|
||||
int killFlags = *(int*)((uint8*)stackPtr + ptrSize + ptrSize);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + ptrSize + ptrSize + ptrSize);
|
||||
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn);
|
||||
BfpSpawn_Kill(internalData->mSpawn, exitCode, (BfpKillFlags)killFlags, (BfpSpawnResult*)(memStart + outResultAddr));
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_Release)
|
||||
{
|
||||
addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 0);
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn);
|
||||
internalData->mReleased = true;
|
||||
}
|
||||
else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSpawn_WaitFor)
|
||||
{
|
||||
bool& result = *(bool*)((uint8*)stackPtr + 0);
|
||||
addr_ce spawnId = *(addr_ce*)((uint8*)stackPtr + 1);
|
||||
int waitMS = *(int*)((uint8*)stackPtr + 1 + ptrSize);
|
||||
addr_ce outExitCodeAddr = *(addr_ce*)((uint8*)stackPtr + 1 + ptrSize + ptrSize);
|
||||
addr_ce outResultAddr = *(addr_ce*)((uint8*)stackPtr + 1 + ptrSize + ptrSize + ptrSize);
|
||||
|
||||
CE_CHECKADDR(outExitCodeAddr, ptrSize);
|
||||
if (outResultAddr != 0)
|
||||
CE_CHECKADDR(outResultAddr, 4);
|
||||
|
||||
CeInternalData* internalData = NULL;
|
||||
CE_GET_INTERNAL(internalData, (int)spawnId, CeInternalData::Kind_Spawn);
|
||||
|
||||
int outExitCode = 0;
|
||||
int timeLeft = waitMS;
|
||||
do
|
||||
{
|
||||
if (*fastFinishPtr)
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int waitTime = 20;
|
||||
if (timeLeft >= 0)
|
||||
{
|
||||
waitTime = BF_MIN(timeLeft, 20);
|
||||
timeLeft -= waitTime;
|
||||
}
|
||||
|
||||
result = BfpSpawn_WaitFor(internalData->mSpawn, waitTime, &outExitCode, (outResultAddr == 0) ? NULL : (BfpSpawnResult*)(memStart + outResultAddr));
|
||||
if (result)
|
||||
break;
|
||||
if (waitTime == 0)
|
||||
break;
|
||||
} while (true);
|
||||
*(int*)(memStart + outExitCodeAddr) = outExitCode;
|
||||
}
|
||||
else
|
||||
{
|
||||
Fail(_GetCurFrame(), StrFormat("Unable to invoke extern method '%s'", ceModule->MethodToString(checkFunction->mMethodInstance).c_str()));
|
||||
return false;
|
||||
|
@ -4989,6 +5436,8 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
int callCount = 0;
|
||||
int instIdx = 0;
|
||||
|
||||
CE_CHECKSTACK();
|
||||
|
||||
while (true)
|
||||
{
|
||||
if (*fastFinishPtr)
|
||||
|
@ -5004,7 +5453,6 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
}
|
||||
|
||||
++instIdx;
|
||||
|
||||
CeOp op = CE_GETINST(CeOp);
|
||||
switch (op)
|
||||
{
|
||||
|
@ -5132,7 +5580,11 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
case CeOp_Malloc:
|
||||
{
|
||||
auto frameOfs = CE_GETINST(int32);
|
||||
int32 size = CE_GETFRAME(int32);
|
||||
int64 size;
|
||||
if (ptrSize == 4)
|
||||
size = CE_GETFRAME(int32);
|
||||
else
|
||||
size = CE_GETFRAME(int64);
|
||||
CE_CHECKALLOC(size);
|
||||
uint8* mem = CeMalloc(size);
|
||||
_FixVariables();
|
||||
|
@ -5580,7 +6032,12 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
|
||||
auto valueType = bfType->ToTypeInstance();
|
||||
if (valueType->mVirtualMethodTable.IsEmpty())
|
||||
ceModule->PopulateType(valueType, BfPopulateType_DataAndMethods);
|
||||
ceModule->PopulateType(valueType, BfPopulateType_Full_Force);
|
||||
if (valueType->mVirtualMethodTable.IsEmpty())
|
||||
{
|
||||
_Fail("Empty virtual table");
|
||||
return false;
|
||||
}
|
||||
auto methodInstance = (BfMethodInstance*)valueType->mVirtualMethodTable[virtualIdx].mImplementingMethod;
|
||||
|
||||
auto callFunction = mCeMachine->GetPreparedFunction(methodInstance);
|
||||
|
@ -5624,6 +6081,13 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
{
|
||||
if (iface.mInterfaceType == ifaceType)
|
||||
{
|
||||
if (valueType->mInterfaceMethodTable.IsEmpty())
|
||||
ceModule->PopulateType(valueType, BfPopulateType_Full_Force);
|
||||
if (valueType->mInterfaceMethodTable.IsEmpty())
|
||||
{
|
||||
_Fail("Empty interface table");
|
||||
return false;
|
||||
}
|
||||
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef;
|
||||
break;
|
||||
}
|
||||
|
@ -6338,6 +6802,8 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
|||
_Fail("Unhandled op");
|
||||
return false;
|
||||
}
|
||||
|
||||
//BF_ASSERT(_CrtCheckMemory() != 0);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -6359,7 +6825,7 @@ CeMachine::CeMachine(BfCompiler* compiler)
|
|||
mCurBuilder = NULL;
|
||||
mPreparingFunction = NULL;
|
||||
|
||||
mCurEmitContext = NULL;
|
||||
mCurEmitContext = NULL;
|
||||
|
||||
mAppendAllocInfo = NULL;
|
||||
mTempParser = NULL;
|
||||
|
@ -6893,6 +7359,34 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
|
|||
{
|
||||
if (methodDef->mName == "BfpSystem_GetTimeStamp")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpSystem_GetTimeStamp;
|
||||
else if (methodDef->mName == "BfpFile_Close")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Close;
|
||||
else if (methodDef->mName == "BfpFile_Create")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Create;
|
||||
else if (methodDef->mName == "BfpFile_Flush")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Flush;
|
||||
else if (methodDef->mName == "BfpFile_GetFileSize")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_GetFileSize;
|
||||
else if (methodDef->mName == "BfpFile_Read")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Read;
|
||||
else if (methodDef->mName == "BfpFile_Release")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Release;
|
||||
else if (methodDef->mName == "BfpFile_Seek")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Seek;
|
||||
else if (methodDef->mName == "BfpFile_Truncate")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Truncate;
|
||||
else if (methodDef->mName == "BfpFile_Write")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpFile_Write;
|
||||
else if (methodDef->mName == "BfpSpawn_Create")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_Create;
|
||||
else if (methodDef->mName == "BfpSpawn_GetStdHandles")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_GetStdHandles;
|
||||
else if (methodDef->mName == "BfpSpawn_Kill")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_Kill;
|
||||
else if (methodDef->mName == "BfpSpawn_Release")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_Release;
|
||||
else if (methodDef->mName == "BfpSpawn_WaitFor")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_BfpSpawn_WaitFor;
|
||||
}
|
||||
else if (owner->IsInstanceOf(mCeModule->mCompiler->mChar32TypeDef))
|
||||
{
|
||||
|
@ -6926,45 +7420,45 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
|
|||
{
|
||||
if (methodDef->mName == "Abs")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Abs;
|
||||
if (methodDef->mName == "Acos")
|
||||
else if (methodDef->mName == "Acos")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Acos;
|
||||
if (methodDef->mName == "Asin")
|
||||
else if (methodDef->mName == "Asin")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Asin;
|
||||
if (methodDef->mName == "Atan")
|
||||
else if (methodDef->mName == "Atan")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Atan;
|
||||
if (methodDef->mName == "Atan2")
|
||||
else if (methodDef->mName == "Atan2")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Atan2;
|
||||
if (methodDef->mName == "Ceiling")
|
||||
else if (methodDef->mName == "Ceiling")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Ceiling;
|
||||
if (methodDef->mName == "Cos")
|
||||
else if (methodDef->mName == "Cos")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Cos;
|
||||
if (methodDef->mName == "Cosh")
|
||||
else if (methodDef->mName == "Cosh")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Cosh;
|
||||
if (methodDef->mName == "Exp")
|
||||
else if (methodDef->mName == "Exp")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Exp;
|
||||
if (methodDef->mName == "Floor")
|
||||
else if (methodDef->mName == "Floor")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Floor;
|
||||
if (methodDef->mName == "Log")
|
||||
else if (methodDef->mName == "Log")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Log;
|
||||
if (methodDef->mName == "Log10")
|
||||
else if (methodDef->mName == "Log10")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Log10;
|
||||
if (methodDef->mName == "Mod")
|
||||
else if (methodDef->mName == "Mod")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Mod;
|
||||
if (methodDef->mName == "Pow")
|
||||
else if (methodDef->mName == "Pow")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Pow;
|
||||
if (methodDef->mName == "Round")
|
||||
else if (methodDef->mName == "Round")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Round;
|
||||
if (methodDef->mName == "Sin")
|
||||
else if (methodDef->mName == "Sin")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Sin;
|
||||
if (methodDef->mName == "Sinh")
|
||||
else if (methodDef->mName == "Sinh")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Sinh;
|
||||
if (methodDef->mName == "Sqrt")
|
||||
else if (methodDef->mName == "Sqrt")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Sqrt;
|
||||
if (methodDef->mName == "Tan")
|
||||
else if (methodDef->mName == "Tan")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Tan;
|
||||
if (methodDef->mName == "Tanh")
|
||||
else if (methodDef->mName == "Tanh")
|
||||
ceFunction->mFunctionKind = CeFunctionKind_Math_Tanh;
|
||||
}
|
||||
}
|
||||
|
||||
ceFunction->mInitializeState = CeFunction::InitializeState_Initialized;
|
||||
return;
|
||||
|
@ -7214,11 +7708,13 @@ CeContext* CeMachine::AllocContext()
|
|||
ceContext->mMemory.Reserve(BF_CE_INITIAL_MEMORY);
|
||||
}
|
||||
|
||||
ceContext->mCurEmitContext = mCurEmitContext;
|
||||
mCurEmitContext = NULL;
|
||||
ceContext->mCurEmitContext = mCurEmitContext;
|
||||
mCurEmitContext = NULL;
|
||||
mExecuteId++;
|
||||
ceContext->mMemory.Resize(BF_CE_STACK_SIZE);
|
||||
ceContext->mStackSize = BF_CE_DEFAULT_STACK_SIZE;
|
||||
ceContext->mMemory.Resize(ceContext->mStackSize);
|
||||
ceContext->mExecuteId = mExecuteId;
|
||||
ceContext->mCurHandleId = 0;
|
||||
return ceContext;
|
||||
}
|
||||
|
||||
|
@ -7234,9 +7730,12 @@ void CeMachine::ReleaseContext(CeContext* ceContext)
|
|||
ceContext->mStaticFieldMap.Clear();
|
||||
ceContext->mHeap->Clear(BF_CE_MAX_CARRYOVER_HEAP);
|
||||
ceContext->mReflectTypeIdOffset = -1;
|
||||
mCurEmitContext = ceContext->mCurEmitContext;
|
||||
ceContext->mCurEmitContext = NULL;
|
||||
mCurEmitContext = ceContext->mCurEmitContext;
|
||||
ceContext->mCurEmitContext = NULL;
|
||||
mContextList.Add(ceContext);
|
||||
for (auto kv : ceContext->mInternalDataMap)
|
||||
delete kv.mValue;
|
||||
ceContext->mInternalDataMap.Clear();
|
||||
}
|
||||
|
||||
BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodInstance* methodInstance, const BfSizedArray<BfIRValue>& args, CeEvalFlags flags, BfType* expectingType)
|
||||
|
@ -7246,3 +7745,5 @@ BfTypedValue CeMachine::Call(BfAstNode* targetSrc, BfModule* module, BfMethodIns
|
|||
ReleaseContext(ceContext);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -264,6 +264,37 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class CeInternalData
|
||||
{
|
||||
public:
|
||||
enum Kind
|
||||
{
|
||||
Kind_None,
|
||||
Kind_File,
|
||||
Kind_FindFileData,
|
||||
Kind_Spawn
|
||||
};
|
||||
|
||||
public:
|
||||
Kind mKind;
|
||||
bool mReleased;
|
||||
|
||||
union
|
||||
{
|
||||
BfpFile* mFile;
|
||||
BfpFindFileData* mFindFileData;
|
||||
BfpSpawn* mSpawn;
|
||||
};
|
||||
|
||||
CeInternalData()
|
||||
{
|
||||
mKind = Kind_None;
|
||||
mReleased = false;
|
||||
}
|
||||
|
||||
~CeInternalData();
|
||||
};
|
||||
|
||||
enum CeFunctionKind
|
||||
{
|
||||
CeFunctionKind_NotSet,
|
||||
|
@ -294,6 +325,21 @@ enum CeFunctionKind
|
|||
CeFunctionKind_EmitMethodExit,
|
||||
CeFunctionKind_EmitMixin,
|
||||
|
||||
CeFunctionKind_BfpFile_Close,
|
||||
CeFunctionKind_BfpFile_Create,
|
||||
CeFunctionKind_BfpFile_Flush,
|
||||
CeFunctionKind_BfpFile_GetFileSize,
|
||||
CeFunctionKind_BfpFile_Read,
|
||||
CeFunctionKind_BfpFile_Release,
|
||||
CeFunctionKind_BfpFile_Seek,
|
||||
CeFunctionKind_BfpFile_Truncate,
|
||||
CeFunctionKind_BfpFile_Write,
|
||||
CeFunctionKind_BfpSpawn_Create,
|
||||
CeFunctionKind_BfpSpawn_GetStdHandles,
|
||||
CeFunctionKind_BfpSpawn_Kill,
|
||||
CeFunctionKind_BfpSpawn_Release,
|
||||
CeFunctionKind_BfpSpawn_WaitFor,
|
||||
|
||||
CeFunctionKind_BfpSystem_GetTimeStamp,
|
||||
CeFunctionKind_Sleep,
|
||||
|
||||
|
@ -328,7 +374,7 @@ enum CeFunctionKind
|
|||
CeFunctionKind_Math_Sinh,
|
||||
CeFunctionKind_Math_Sqrt,
|
||||
CeFunctionKind_Math_Tan,
|
||||
CeFunctionKind_Math_Tanh,
|
||||
CeFunctionKind_Math_Tanh,
|
||||
};
|
||||
|
||||
class CeConstStructFixup
|
||||
|
@ -501,10 +547,11 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
#define BF_CE_STACK_SIZE 4*1024*1024
|
||||
#define BF_CE_INITIAL_MEMORY BF_CE_STACK_SIZE + 128*1024
|
||||
#define BF_CE_MAX_MEMORY 128*1024*1024
|
||||
#define BF_CE_MAX_CARRYOVER_MEMORY BF_CE_STACK_SIZE * 2
|
||||
#define BF_CE_DEFAULT_STACK_SIZE 4*1024*1024
|
||||
#define BF_CE_DEFAULT_HEAP_SIZE 128*1024
|
||||
#define BF_CE_INITIAL_MEMORY BF_CE_DEFAULT_STACK_SIZE + BF_CE_DEFAULT_HEAP_SIZE
|
||||
#define BF_CE_MAX_MEMORY 0x7FFFFFFF
|
||||
#define BF_CE_MAX_CARRYOVER_MEMORY BF_CE_DEFAULT_STACK_SIZE * 2
|
||||
#define BF_CE_MAX_CARRYOVER_HEAP 1024*1024
|
||||
|
||||
enum CeOperandInfoKind
|
||||
|
@ -683,12 +730,40 @@ public:
|
|||
BfIRValue mAppendSizeValue;
|
||||
};
|
||||
|
||||
class CeRebuildKey
|
||||
{
|
||||
public:
|
||||
enum Kind
|
||||
{
|
||||
Kind_None,
|
||||
Kind_File
|
||||
};
|
||||
|
||||
public:
|
||||
Kind mKind;
|
||||
String mString;
|
||||
|
||||
bool operator==(const CeRebuildKey& other) const
|
||||
{
|
||||
return (mKind == other.mKind) && (mString == other.mString);
|
||||
}
|
||||
};
|
||||
|
||||
class CeRebuildValue
|
||||
{
|
||||
public:
|
||||
union
|
||||
{
|
||||
uint64 mInt;
|
||||
};
|
||||
};
|
||||
|
||||
class CeEmitContext
|
||||
{
|
||||
public:
|
||||
BfType* mType;
|
||||
BfType* mType;
|
||||
BfMethodInstance* mMethodInstance;
|
||||
Array<int32> mInterfaces;
|
||||
Array<int32> mInterfaces;
|
||||
String mEmitData;
|
||||
String mExitEmitData;
|
||||
bool mFailed;
|
||||
|
@ -706,6 +781,25 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class BfCeTypeInfo
|
||||
{
|
||||
public:
|
||||
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
|
||||
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
|
||||
Array<int> mPendingInterfaces;
|
||||
Dictionary<CeRebuildKey, CeRebuildValue> mRebuildMap;
|
||||
Val128 mHash;
|
||||
bool mFailed;
|
||||
BfCeTypeInfo* mNext;
|
||||
|
||||
public:
|
||||
BfCeTypeInfo()
|
||||
{
|
||||
mFailed = false;
|
||||
mNext = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
class CeContext
|
||||
{
|
||||
public:
|
||||
|
@ -719,19 +813,21 @@ public:
|
|||
ContiguousHeap* mHeap;
|
||||
Array<CeFrame> mCallStack;
|
||||
Array<uint8> mMemory;
|
||||
int mStackSize;
|
||||
Dictionary<int, addr_ce> mStringMap;
|
||||
Dictionary<int, addr_ce> mReflectMap;
|
||||
Dictionary<Val128, addr_ce> mConstDataMap;
|
||||
HashSet<int> mStaticCtorExecSet;
|
||||
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
|
||||
Dictionary<void*, addr_ce> mMemToCtxMap;
|
||||
Dictionary<int, CeInternalData*> mInternalDataMap;
|
||||
int mCurHandleId;
|
||||
|
||||
BfMethodInstance* mCurMethodInstance;
|
||||
BfType* mCurExpectingType;
|
||||
BfAstNode* mCurTargetSrc;
|
||||
BfModule* mCurModule;
|
||||
CeFrame* mCurFrame;
|
||||
CeEmitContext* mCurEmitContext;
|
||||
CeEmitContext* mCurEmitContext;
|
||||
|
||||
public:
|
||||
CeContext();
|
||||
|
@ -740,6 +836,7 @@ public:
|
|||
BfError* Fail(const StringImpl& error);
|
||||
BfError* Fail(const CeFrame& curFrame, const StringImpl& error);
|
||||
|
||||
void AddRebuild(const CeRebuildKey& key, const CeRebuildValue& value);
|
||||
uint8* CeMalloc(int size);
|
||||
bool CeFree(addr_ce addr);
|
||||
addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
|
||||
|
@ -791,7 +888,7 @@ public:
|
|||
CeAppendAllocInfo* mAppendAllocInfo;
|
||||
|
||||
CeContext* mCurContext;
|
||||
CeEmitContext* mCurEmitContext;
|
||||
CeEmitContext* mCurEmitContext;
|
||||
CeBuilder* mCurBuilder;
|
||||
CeFunction* mPreparingFunction;
|
||||
|
||||
|
@ -838,3 +935,15 @@ public:
|
|||
};
|
||||
|
||||
NS_BF_END
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <>
|
||||
struct hash<Beefy::CeRebuildKey>
|
||||
{
|
||||
size_t operator()(const Beefy::CeRebuildKey& key) const
|
||||
{
|
||||
return BeefHash<Beefy::String>()(key.mString) ^ (size_t)key.mKind;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -8,12 +8,12 @@ typedef LONG KPRIORITY;
|
|||
|
||||
USING_NS_BF_DBG;
|
||||
|
||||
enum SYSTEM_INFORMATION_CLASS
|
||||
enum SYSTEM_INFORMATION_CLASS
|
||||
{
|
||||
SystemProcessInformation = 5
|
||||
}; // SYSTEM_INFORMATION_CLASS
|
||||
|
||||
struct CLIENT_ID
|
||||
struct CLIENT_ID
|
||||
{
|
||||
HANDLE UniqueProcess;
|
||||
HANDLE UniqueThread;
|
||||
|
@ -81,14 +81,14 @@ struct SYSTEM_PROCESS_INFORMATION
|
|||
SYSTEM_THREAD Threads[1];
|
||||
};
|
||||
|
||||
typedef NTSTATUS(NTAPI *NtQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||
typedef NTSTATUS(NTAPI* NtQuerySystemInformation_t)(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG);
|
||||
static NtQuerySystemInformation_t NtQuerySystemInformation = NULL;
|
||||
static HMODULE ntdll = NULL;
|
||||
|
||||
DbgProfiler::DbgProfiler(WinDebugger* debugger) : mShutdownEvent(true)
|
||||
{
|
||||
mDebugger = debugger;
|
||||
mIsRunning = false;
|
||||
mIsRunning = false;
|
||||
mWantsClear = false;
|
||||
|
||||
mSamplesPerSecond = 1000;
|
||||
|
@ -101,6 +101,13 @@ DbgProfiler::DbgProfiler(WinDebugger* debugger) : mShutdownEvent(true)
|
|||
mEndTick = 0;
|
||||
|
||||
mDebugger->AddProfiler(this);
|
||||
|
||||
mIdleSymbolNames.Add("ZwDelayExecution");
|
||||
mIdleSymbolNames.Add("ZwWaitForWorkViaWorkerFactory");
|
||||
mIdleSymbolNames.Add("NtWaitForAlertByThreadId");
|
||||
mIdleSymbolNames.Add("NtWaitForSingleObject");
|
||||
mIdleSymbolNames.Add("NtWaitForMultipleObjects");
|
||||
mIdleSymbolNames.Add("ZwRemoveIoCompletion");
|
||||
}
|
||||
|
||||
DbgProfiler::~DbgProfiler()
|
||||
|
@ -113,14 +120,14 @@ DbgProfiler::~DbgProfiler()
|
|||
}
|
||||
|
||||
static SYSTEM_PROCESS_INFORMATION* CaptureProcessInfo()
|
||||
{
|
||||
{
|
||||
WCHAR path[MAX_PATH];
|
||||
GetSystemDirectory(path, MAX_PATH);
|
||||
wcscat(path, L"\\ntdll.dll");
|
||||
ntdll = GetModuleHandle(path);
|
||||
wcscat(path, L"\\ntdll.dll");
|
||||
ntdll = GetModuleHandle(path);
|
||||
if (ntdll == NULL)
|
||||
return NULL;
|
||||
NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(ntdll, "NtQuerySystemInformation");
|
||||
NtQuerySystemInformation = (NtQuerySystemInformation_t)GetProcAddress(ntdll, "NtQuerySystemInformation");
|
||||
|
||||
uint allocSize = 1024;
|
||||
uint8* data = NULL;
|
||||
|
@ -134,7 +141,7 @@ static SYSTEM_PROCESS_INFORMATION* CaptureProcessInfo()
|
|||
|
||||
if (status != STATUS_INFO_LENGTH_MISMATCH)
|
||||
return (SYSTEM_PROCESS_INFORMATION*)data;
|
||||
|
||||
|
||||
allocSize = wantSize + 4096;
|
||||
delete data;
|
||||
}
|
||||
|
@ -148,8 +155,8 @@ void DbgProfiler::DoClear()
|
|||
delete val.mProcId;
|
||||
}
|
||||
|
||||
ProfileProcId* DbgProfiler::Get(const StringImpl& str)
|
||||
{
|
||||
ProfileProcId* DbgProfiler::Get(const StringImpl& str, bool* outIsNew)
|
||||
{
|
||||
ProfileProdIdEntry checkEntry;
|
||||
checkEntry.mProcId = (ProfileProcId*)&str;
|
||||
|
||||
|
@ -158,11 +165,16 @@ ProfileProcId* DbgProfiler::Get(const StringImpl& str)
|
|||
{
|
||||
auto procId = new ProfileProcId();
|
||||
procId->mProcName = str;
|
||||
entryPtr->mProcId = procId;
|
||||
procId->mIsIdle = false;
|
||||
entryPtr->mProcId = procId;
|
||||
if (outIsNew != NULL)
|
||||
*outIsNew = true;
|
||||
return procId;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (outIsNew != NULL)
|
||||
*outIsNew = false;
|
||||
return entryPtr->mProcId;
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +182,7 @@ ProfileProcId* DbgProfiler::Get(const StringImpl& str)
|
|||
void DbgProfiler::ThreadProc()
|
||||
{
|
||||
//TODO: Do timing smarter, handle delays and slow stack traces and stuff
|
||||
|
||||
|
||||
//timeBeginPeriod(1);
|
||||
|
||||
BF_ASSERT(mTotalVirtualSamples == 0);
|
||||
|
@ -184,7 +196,7 @@ void DbgProfiler::ThreadProc()
|
|||
uint32 accumMS = 0;
|
||||
|
||||
int totalWait = 0;
|
||||
int totalWait2 = 0;
|
||||
int totalWait2 = 0;
|
||||
int iterations = 0;
|
||||
HashSet<int> idleThreadSet;
|
||||
|
||||
|
@ -218,9 +230,11 @@ void DbgProfiler::ThreadProc()
|
|||
iterations++;
|
||||
DWORD startTick0 = timeGetTime();
|
||||
idleThreadSet.Clear();
|
||||
|
||||
|
||||
SYSTEM_PROCESS_INFORMATION* processData = NULL;
|
||||
std::unique_ptr<SYSTEM_PROCESS_INFORMATION> ptrDelete(processData);
|
||||
std::unique_ptr<SYSTEM_PROCESS_INFORMATION> ptrDelete(processData);
|
||||
|
||||
//processData = CaptureProcessInfo();
|
||||
|
||||
auto curProcessData = processData;
|
||||
while (true)
|
||||
|
@ -235,6 +249,7 @@ void DbgProfiler::ThreadProc()
|
|||
auto& threadInfo = curProcessData->Threads[threadIdx];
|
||||
if ((threadInfo.State == StateWait) || (threadInfo.State == StateTerminated))
|
||||
idleThreadSet.Add((int)(intptr)threadInfo.ClientId.UniqueThread);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -242,12 +257,12 @@ void DbgProfiler::ThreadProc()
|
|||
break;
|
||||
curProcessData = (SYSTEM_PROCESS_INFORMATION*)((intptr)curProcessData + curProcessData->NextEntryOffset);
|
||||
}
|
||||
|
||||
|
||||
if (mShutdownEvent.WaitFor(0))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
DWORD tickNow = timeGetTime();
|
||||
accumMS += (int)(tickNow - prevSampleTick);
|
||||
prevSampleTick = tickNow;
|
||||
|
@ -284,21 +299,21 @@ void DbgProfiler::ThreadProc()
|
|||
|
||||
mTotalVirtualSamples += curSampleCount;
|
||||
mTotalActualSamples++;
|
||||
|
||||
|
||||
int threadIdx = 0;
|
||||
while (true)
|
||||
{
|
||||
{
|
||||
int startTick = timeGetTime();
|
||||
|
||||
AutoCrit autoCrit(mDebugger->mDebugManager->mCritSect);
|
||||
|
||||
if (mDebugger->mRunState != RunState_Running)
|
||||
break;
|
||||
AutoCrit autoCrit(mDebugger->mDebugManager->mCritSect);
|
||||
|
||||
if (mDebugger->mRunState != RunState_Running)
|
||||
break;
|
||||
|
||||
if (threadIdx >= mDebugger->mThreadList.size())
|
||||
break;
|
||||
|
||||
auto thread = mDebugger->mThreadList[threadIdx];
|
||||
auto thread = mDebugger->mThreadList[threadIdx];
|
||||
|
||||
if ((mTargetThreadId > 0) && (thread->mThreadId != mTargetThreadId))
|
||||
{
|
||||
|
@ -321,20 +336,22 @@ void DbgProfiler::ThreadProc()
|
|||
profileThreadInfo = *profileThreadInfoPtr;
|
||||
}
|
||||
|
||||
profileThreadInfo->mTotalSamples += curSampleCount;
|
||||
|
||||
bool isThreadIdle = idleThreadSet.Contains(thread->mThreadId);
|
||||
|
||||
profileThreadInfo->mTotalSamples += curSampleCount;
|
||||
if (isThreadIdle)
|
||||
profileThreadInfo->mTotalIdleSamples += curSampleCount;
|
||||
|
||||
mDebugger->mActiveThread = thread;
|
||||
|
||||
::SuspendThread(thread->mHThread);
|
||||
|
||||
::SuspendThread(thread->mHThread);
|
||||
|
||||
CPURegisters registers;
|
||||
mDebugger->PopulateRegisters(®isters);
|
||||
|
||||
int stackSize = 0;
|
||||
for (int stackIdx = 0 ; stackIdx < maxStackTrace; stackIdx++)
|
||||
{
|
||||
for (int stackIdx = 0; stackIdx < maxStackTrace; stackIdx++)
|
||||
{
|
||||
auto pc = registers.GetPC();
|
||||
if (pc <= 0xFFFF)
|
||||
{
|
||||
|
@ -353,7 +370,7 @@ void DbgProfiler::ThreadProc()
|
|||
|
||||
ProfileAddrEntry* insertedProfileEntry = AddToSet(mProfileAddrEntrySet, stackTrace, stackSize);
|
||||
if (insertedProfileEntry->mEntryIdx == -1)
|
||||
{
|
||||
{
|
||||
insertedProfileEntry->mEntryIdx = (int)mProfileAddrEntrySet.size(); // Starts at '1'
|
||||
mPendingProfileEntries.Add(*insertedProfileEntry);
|
||||
}
|
||||
|
@ -365,7 +382,7 @@ void DbgProfiler::ThreadProc()
|
|||
entryIdx = -entryIdx;
|
||||
profileThreadInfo->mProfileAddrEntries.push_back(entryIdx);
|
||||
}
|
||||
|
||||
|
||||
::ResumeThread(thread->mHThread);
|
||||
|
||||
int elapsedTime = timeGetTime() - startTick;
|
||||
|
@ -379,7 +396,7 @@ void DbgProfiler::ThreadProc()
|
|||
}
|
||||
}
|
||||
|
||||
mIsRunning = false;
|
||||
mIsRunning = false;
|
||||
|
||||
mEndTick = BFTickCount();
|
||||
}
|
||||
|
@ -394,7 +411,7 @@ void DbgProfiler::Start()
|
|||
BF_ASSERT(!mIsRunning);
|
||||
|
||||
mNeedsProcessing = true;
|
||||
mIsRunning = true;
|
||||
mIsRunning = true;
|
||||
auto thread = BfpThread_Create(ThreadProcThunk, (void*)this, 128 * 1024, BfpThreadCreateFlag_StackSizeReserve);
|
||||
BfpThread_Release(thread);
|
||||
}
|
||||
|
@ -439,22 +456,25 @@ String DbgProfiler::GetThreadList()
|
|||
for (auto threadId : mThreadIdList)
|
||||
{
|
||||
auto threadInfo = mThreadInfo[threadId];
|
||||
result += StrFormat("%d\t%s\n", threadId, threadInfo->mName.c_str());
|
||||
int cpuUsage = 0;
|
||||
if (threadInfo->mTotalSamples > 0)
|
||||
cpuUsage = 100 - (threadInfo->mTotalIdleSamples * 100 / threadInfo->mTotalSamples);
|
||||
result += StrFormat("%d\t%d\t%s\n", threadId, cpuUsage, threadInfo->mName.c_str());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void DbgProfiler::AddEntries(String& str, Array<ProfileProcEntry*>& procEntries, int rangeStart, int rangeEnd, int stackIdx, ProfileProcId* findProc)
|
||||
{
|
||||
{
|
||||
struct _QueuedEntry
|
||||
{
|
||||
int mRangeIdx;
|
||||
int mRangeEnd;
|
||||
int mStackIdx;
|
||||
int mStackIdx;
|
||||
};
|
||||
Array<_QueuedEntry> workQueue;
|
||||
|
||||
|
||||
auto _AddEntries = [&](int rangeStart, int rangeEnd, int stackIdx, ProfileProcId* findProc)
|
||||
{
|
||||
int selfSampleCount = 0;
|
||||
|
@ -521,7 +541,7 @@ void DbgProfiler::AddEntries(String& str, Array<ProfileProcEntry*>& procEntries,
|
|||
_QueuedEntry entry;
|
||||
entry.mRangeIdx = rangeStart;
|
||||
entry.mRangeEnd = rangeEnd;
|
||||
entry.mStackIdx = stackIdx;
|
||||
entry.mStackIdx = stackIdx;
|
||||
workQueue.Add(entry);
|
||||
};
|
||||
_AddEntries(rangeStart, rangeEnd, stackIdx, findProc);
|
||||
|
@ -529,7 +549,7 @@ void DbgProfiler::AddEntries(String& str, Array<ProfileProcEntry*>& procEntries,
|
|||
while (!workQueue.IsEmpty())
|
||||
{
|
||||
auto& entry = workQueue.back();
|
||||
|
||||
|
||||
bool addedChild = false;
|
||||
while (entry.mRangeIdx < entry.mRangeEnd)
|
||||
{
|
||||
|
@ -539,7 +559,7 @@ void DbgProfiler::AddEntries(String& str, Array<ProfileProcEntry*>& procEntries,
|
|||
entry.mRangeIdx++;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int nextStackIdx = entry.mStackIdx + 1;
|
||||
auto nextFindProc = procEntry->mData[procEntry->mSize - 1 - nextStackIdx];
|
||||
_AddEntries(entry.mRangeIdx, entry.mRangeEnd, nextStackIdx, nextFindProc);
|
||||
|
@ -552,7 +572,7 @@ void DbgProfiler::AddEntries(String& str, Array<ProfileProcEntry*>& procEntries,
|
|||
if (entry.mStackIdx != -1)
|
||||
str += "-\n";
|
||||
workQueue.pop_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -608,7 +628,10 @@ void DbgProfiler::HandlePendingEntries()
|
|||
symbolName += StrFormat("0x%@", addr);
|
||||
}
|
||||
|
||||
procId = Get(symbolName);
|
||||
bool isNew = false;
|
||||
procId = Get(symbolName, &isNew);
|
||||
if (isNew)
|
||||
procId->mIsIdle = mIdleSymbolNames.Contains(symbolName);
|
||||
}
|
||||
|
||||
if (reverse)
|
||||
|
@ -640,11 +663,11 @@ void DbgProfiler::Process()
|
|||
AutoCrit autoCrit(mDebugger->mDebugManager->mCritSect);
|
||||
|
||||
mNeedsProcessing = false;
|
||||
|
||||
|
||||
int time = mTotalActiveSamplingMS;
|
||||
|
||||
BF_ASSERT(mProfileAddrEntries.IsEmpty());
|
||||
|
||||
|
||||
mProfileAddrEntries.Resize(mProfileAddrEntrySet.size() + 1);
|
||||
for (auto& val : mProfileAddrEntrySet)
|
||||
mProfileAddrEntries[val.mEntryIdx] = &val;
|
||||
|
@ -654,16 +677,35 @@ void DbgProfiler::Process()
|
|||
for (auto& val : mProfileProcEntrySet)
|
||||
mProfileProcEntries[val.mEntryIdx] = &val;
|
||||
|
||||
for (auto threadKV : mThreadInfo)
|
||||
{
|
||||
auto threadInfo = threadKV.mValue;
|
||||
|
||||
for (auto addrEntryIdx : threadInfo->mProfileAddrEntries)
|
||||
{
|
||||
if (addrEntryIdx < 0)
|
||||
{
|
||||
addrEntryIdx = -addrEntryIdx;
|
||||
}
|
||||
|
||||
int procEntryIdx = mProfileAddrToProcMap[addrEntryIdx];
|
||||
auto procEntry = mProfileProcEntries[procEntryIdx];
|
||||
|
||||
auto curProc = procEntry->mData[0];
|
||||
if (curProc->mIsIdle)
|
||||
threadInfo->mTotalIdleSamples++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String DbgProfiler::GetCallTree(int threadId, bool reverse)
|
||||
{
|
||||
{
|
||||
if (mNeedsProcessing)
|
||||
Process();
|
||||
|
||||
AutoCrit autoCrit(mDebugger->mDebugManager->mCritSect);
|
||||
|
||||
BF_ASSERT(!mIsRunning);
|
||||
BF_ASSERT(!mIsRunning);
|
||||
|
||||
Array<ProfileProcEntry*> procEntries;
|
||||
|
||||
|
@ -714,10 +756,10 @@ String DbgProfiler::GetCallTree(int threadId, bool reverse)
|
|||
int idleTicks = totalSampleCount - totalActiveSampleCount;
|
||||
if (idleTicks != 0)
|
||||
str += StrFormat("<Idle>\t%d\t0\n-\n", idleTicks);
|
||||
|
||||
|
||||
AddEntries(str, procEntries, 0, (int)procEntries.size(), -1, NULL);
|
||||
|
||||
str += "-\n";
|
||||
|
||||
str += "-\n";
|
||||
|
||||
//BF_ASSERT(childSampleCount == totalSampleCount);
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ class ProfileProcId
|
|||
{
|
||||
public:
|
||||
String mProcName;
|
||||
bool mIsIdle;
|
||||
};
|
||||
|
||||
class ProfileProdIdEntry
|
||||
|
@ -104,12 +105,14 @@ class ProfileThreadInfo
|
|||
public:
|
||||
Array<int> mProfileAddrEntries;
|
||||
int mTotalSamples;
|
||||
int mTotalIdleSamples;
|
||||
String mName;
|
||||
|
||||
public:
|
||||
ProfileThreadInfo()
|
||||
{
|
||||
mTotalSamples = 0;
|
||||
mTotalIdleSamples = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -143,6 +146,7 @@ public:
|
|||
|
||||
Dictionary<void*, ProfileProcId*> mProcMap; // Keyed on either DwSubprogram or DwSymbol. Multiple pointers can reference the same ProfileProcId (in the case of inlined functions, for example)
|
||||
HashSet<ProfileProdIdEntry> mUniqueProcSet;
|
||||
HashSet<String> mIdleSymbolNames;
|
||||
|
||||
public:
|
||||
void ThreadProc();
|
||||
|
@ -171,7 +175,7 @@ public:
|
|||
void HandlePendingEntries();
|
||||
void Process();
|
||||
void DoClear();
|
||||
ProfileProcId* Get(const StringImpl& str);
|
||||
ProfileProcId* Get(const StringImpl& str, bool* outIsNew = NULL);
|
||||
|
||||
public:
|
||||
DbgProfiler(WinDebugger* debugger);
|
||||
|
|
2
IDEHelper/Tests/Test0.txt
Normal file
2
IDEHelper/Tests/Test0.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
Test
|
||||
0
|
|
@ -183,7 +183,7 @@ namespace Tests
|
|||
mStr.AppendF($"{name} {val}\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
interface ISerializable
|
||||
{
|
||||
void Serialize(SerializationContext ctx);
|
||||
|
@ -229,6 +229,43 @@ namespace Tests
|
|||
GC.Mark!((*ptr));
|
||||
}
|
||||
}
|
||||
|
||||
[CheckEnum]
|
||||
enum EnumA
|
||||
{
|
||||
case A(int64 aa);
|
||||
case B(float bb);
|
||||
}
|
||||
|
||||
[AttributeUsage(.All)]
|
||||
public struct CheckEnumAttribute : Attribute, IComptimeTypeApply
|
||||
{
|
||||
public void ApplyToType(Type type)
|
||||
{
|
||||
int fieldIdx = 0;
|
||||
for (var field in type.GetFields())
|
||||
{
|
||||
switch (fieldIdx)
|
||||
{
|
||||
case 0:
|
||||
Test.Assert(field.Name == "$payload");
|
||||
Test.Assert(field.MemberOffset == 0);
|
||||
Test.Assert(field.FieldType == typeof(int64));
|
||||
case 1:
|
||||
Test.Assert(field.Name == "$discriminator");
|
||||
Test.Assert(field.MemberOffset == 8);
|
||||
Test.Assert(field.FieldType == typeof(int8));
|
||||
}
|
||||
fieldIdx++;
|
||||
}
|
||||
Test.Assert(fieldIdx == 4);
|
||||
}
|
||||
}
|
||||
|
||||
const String cTest0 = Compiler.ReadText("Test0.txt");
|
||||
const String cTest1 = new String('A', 12);
|
||||
const uint8[?] cTest0Binary = Compiler.ReadBinary("Test0.txt");
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
@ -269,6 +306,11 @@ namespace Tests
|
|||
SerializationContext serCtx = scope .();
|
||||
iSer.Serialize(serCtx);
|
||||
Test.Assert(serCtx.mStr == "x 10\ny 2\n");
|
||||
|
||||
Test.Assert(cTest0 == "Test\n0");
|
||||
Test.Assert(cTest1 == "AAAAAAAAAAAA");
|
||||
Test.Assert((Object)cTest1 == (Object)"AAAAAAAAAAAA");
|
||||
Test.Assert((cTest0Binary[0] == (.)'T') && ((cTest0Binary.Count == 6) || (cTest0Binary.Count == 7)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,65 @@ namespace Tests
|
|||
return dlg(val[0]);
|
||||
}
|
||||
|
||||
static void TestWrap<T>(T del, bool b = false) where T : delegate void()
|
||||
{
|
||||
Action ac = scope () => {
|
||||
del();
|
||||
};
|
||||
ac();
|
||||
}
|
||||
|
||||
struct Vector2 : this(float x, float y)
|
||||
{
|
||||
}
|
||||
|
||||
class Invoker
|
||||
{
|
||||
public int mA = 111;
|
||||
|
||||
public void Invoke()
|
||||
{
|
||||
mA += 222;
|
||||
}
|
||||
}
|
||||
|
||||
class TestA
|
||||
{
|
||||
Vector2 mVec = .(11, 22);
|
||||
Event<Action> mEvt ~ _.Dispose();
|
||||
Action mAct;
|
||||
|
||||
public Vector2 Vec
|
||||
{
|
||||
set
|
||||
{
|
||||
DoIt(() =>
|
||||
{
|
||||
Test.Assert(mVec.x == 11);
|
||||
Test.Assert(mVec.y == 22);
|
||||
Test.Assert(value.x == 33);
|
||||
Test.Assert(value.y == 44);
|
||||
});
|
||||
Invoker invoker = scope .();
|
||||
mEvt.Add(new => invoker);
|
||||
DoIt(=> mEvt);
|
||||
Test.Assert(invoker.mA == 333);
|
||||
DoIt(=> invoker);
|
||||
Test.Assert(invoker.mA == 555);
|
||||
mAct = scope => invoker;
|
||||
mAct();
|
||||
Test.Assert(invoker.mA == 777);
|
||||
DoIt(=> mAct);
|
||||
Test.Assert(invoker.mA == 999);
|
||||
}
|
||||
}
|
||||
|
||||
public void DoIt<TDlg>(TDlg dlg) where TDlg : delegate void()
|
||||
{
|
||||
dlg();
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
|
@ -78,6 +137,13 @@ namespace Tests
|
|||
List<float> fList = scope .() { 1.2f, 2.3f };
|
||||
Test.Assert(DoOnListA(fList, (val) => val + 100) == 101.2f);
|
||||
Test.Assert(DoOnListB((val) => val + 200, fList) == 201.2f);
|
||||
|
||||
int a = 222;
|
||||
TestWrap(() => { a += 100; });
|
||||
Test.Assert(a == 322);
|
||||
|
||||
TestA ta = scope .();
|
||||
ta.Vec = .(33, 44);
|
||||
}
|
||||
|
||||
struct MethodRefHolder<T> where T : delegate int(int num)
|
||||
|
|
|
@ -23,6 +23,16 @@ namespace Tests
|
|||
{
|
||||
class Generics
|
||||
{
|
||||
struct StructA : IDisposable
|
||||
{
|
||||
int mA = 123;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class ClassA : IDisposable, LibA.IVal
|
||||
{
|
||||
int LibA.IVal.Val
|
||||
|
@ -172,7 +182,7 @@ namespace Tests
|
|||
delete val;
|
||||
}
|
||||
|
||||
public static void Alloc2<T>() where T : new, delete, IDisposable, struct
|
||||
public static void Alloc2<T>() where T : new, IDisposable, struct
|
||||
{
|
||||
alloctype(T) val = new T();
|
||||
T* val2 = val;
|
||||
|
@ -180,6 +190,14 @@ namespace Tests
|
|||
delete val;
|
||||
}
|
||||
|
||||
public static void Alloc3<T>() where T : new, IDisposable, struct*
|
||||
{
|
||||
T val2 = default;
|
||||
if (val2 != null)
|
||||
val2.Dispose();
|
||||
delete val2;
|
||||
}
|
||||
|
||||
public class ClassE
|
||||
{
|
||||
public static Self Instance = new ClassE() ~ delete _;
|
||||
|
@ -311,6 +329,9 @@ namespace Tests
|
|||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
Alloc2<StructA>();
|
||||
Alloc3<StructA*>();
|
||||
|
||||
MethodD(scope => MethodC);
|
||||
|
||||
List<Entry> list = scope .();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue