mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Merge branch 'master' of https://github.com/beefytech/Beef into FuzzyAutoComplete
This commit is contained in:
parent
c2c7431620
commit
b70745ef1e
48 changed files with 2975 additions and 918 deletions
|
@ -256,7 +256,10 @@ namespace Beefy.widgets
|
||||||
public virtual void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
public virtual void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
||||||
{
|
{
|
||||||
if (mClosed)
|
if (mClosed)
|
||||||
|
{
|
||||||
|
BFApp.sApp.DeferDelete(this);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
mInPopupWindow = true;
|
mInPopupWindow = true;
|
||||||
|
|
||||||
|
|
|
@ -578,6 +578,43 @@ namespace System.Collections
|
||||||
return oldPtr;
|
return oldPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool RemoveEntry(int32 hashCode, int_cosize index)
|
||||||
|
{
|
||||||
|
if (mBuckets != null)
|
||||||
|
{
|
||||||
|
int bucket = hashCode % (int_cosize)mAllocSize;
|
||||||
|
int lastIndex = -1;
|
||||||
|
|
||||||
|
for (int_cosize i = mBuckets[bucket]; i >= 0; lastIndex = i, i = mEntries[i].mNext)
|
||||||
|
{
|
||||||
|
if (i == index)
|
||||||
|
{
|
||||||
|
if (lastIndex < 0)
|
||||||
|
{
|
||||||
|
mBuckets[bucket] = mEntries[index].mNext;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mEntries[lastIndex].mNext = mEntries[index].mNext;
|
||||||
|
}
|
||||||
|
mEntries[index].mHashCode = -1;
|
||||||
|
mEntries[index].mNext = mFreeList;
|
||||||
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
|
mEntries[index].mKey = default;
|
||||||
|
mEntries[index].mValue = default;
|
||||||
|
#endif
|
||||||
|
mFreeList = index;
|
||||||
|
mFreeCount++;
|
||||||
|
#if VERSION_DICTIONARY
|
||||||
|
mVersion++;
|
||||||
|
#endif
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public bool Remove(TKey key)
|
public bool Remove(TKey key)
|
||||||
{
|
{
|
||||||
if (mBuckets != null)
|
if (mBuckets != null)
|
||||||
|
@ -901,7 +938,7 @@ namespace System.Collections
|
||||||
public void Remove() mut
|
public void Remove() mut
|
||||||
{
|
{
|
||||||
int_cosize curIdx = mIndex - 1;
|
int_cosize curIdx = mIndex - 1;
|
||||||
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
|
mDictionary.RemoveEntry(mDictionary.mEntries[curIdx].mHashCode, curIdx);
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
mVersion = mDictionary.mVersion;
|
mVersion = mDictionary.mVersion;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1052,7 +1089,7 @@ namespace System.Collections
|
||||||
public void Remove() mut
|
public void Remove() mut
|
||||||
{
|
{
|
||||||
int_cosize curIdx = mIndex - 1;
|
int_cosize curIdx = mIndex - 1;
|
||||||
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
|
mDictionary.RemoveEntry(mDictionary.mEntries[curIdx].mHashCode, curIdx);
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
mVersion = mDictionary.mVersion;
|
mVersion = mDictionary.mVersion;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1158,7 +1195,7 @@ namespace System.Collections
|
||||||
public void Remove() mut
|
public void Remove() mut
|
||||||
{
|
{
|
||||||
int_cosize curIdx = mIndex - 1;
|
int_cosize curIdx = mIndex - 1;
|
||||||
mDictionary.Remove(mDictionary.mEntries[curIdx].mKey);
|
mDictionary.RemoveEntry(mDictionary.mEntries[curIdx].mHashCode, curIdx);
|
||||||
#if VERSION_DICTIONARY
|
#if VERSION_DICTIONARY
|
||||||
mVersion = mDictionary.mVersion;
|
mVersion = mDictionary.mVersion;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,8 +1,189 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace System
|
namespace System
|
||||||
{
|
{
|
||||||
static class Compiler
|
static class Compiler
|
||||||
{
|
{
|
||||||
|
public abstract class Generator
|
||||||
|
{
|
||||||
|
public enum Flags
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
AllowRegenerate = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public String mCmdInfo = new String() ~ delete _;
|
||||||
|
public Dictionary<StringView, StringView> mParams = new .() ~ delete _;
|
||||||
|
public abstract String Name { get; }
|
||||||
|
|
||||||
|
public StringView ProjectName => mParams["ProjectName"];
|
||||||
|
public StringView ProjectDir => mParams["ProjectDir"];
|
||||||
|
public StringView FolderDir => mParams["FolderDir"];
|
||||||
|
public StringView Namespace => mParams["Namespace"];
|
||||||
|
public StringView DefaultNamespace => mParams["DefaultNamespace"];
|
||||||
|
public StringView WorkspaceName => mParams["WorkspaceName"];
|
||||||
|
public StringView WorkspaceDir => mParams["WorkspaceDir"];
|
||||||
|
public StringView DateTime => mParams["DateTime"];
|
||||||
|
public bool IsRegenerating => mParams.GetValueOrDefault("Regenerating") == "True";
|
||||||
|
|
||||||
|
public void Fail(StringView error)
|
||||||
|
{
|
||||||
|
mCmdInfo.AppendF("error\t");
|
||||||
|
error.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddEdit(StringView dataName, StringView label, StringView defaultValue)
|
||||||
|
{
|
||||||
|
mCmdInfo.AppendF($"addEdit\t");
|
||||||
|
dataName.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\t");
|
||||||
|
label.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\t");
|
||||||
|
defaultValue.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCombo(StringView dataName, StringView label, StringView defaultValue, Span<StringView> values)
|
||||||
|
{
|
||||||
|
mCmdInfo.AppendF($"addCombo\t");
|
||||||
|
dataName.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\t");
|
||||||
|
label.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\t");
|
||||||
|
defaultValue.QuoteString(mCmdInfo);
|
||||||
|
for (var value in values)
|
||||||
|
{
|
||||||
|
mCmdInfo.Append("\t");
|
||||||
|
value.QuoteString(mCmdInfo);
|
||||||
|
}
|
||||||
|
mCmdInfo.Append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCheckbox(StringView dataName, StringView label, bool defaultValue)
|
||||||
|
{
|
||||||
|
mCmdInfo.AppendF($"addCheckbox\t");
|
||||||
|
dataName.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.Append("\t");
|
||||||
|
label.QuoteString(mCmdInfo);
|
||||||
|
mCmdInfo.AppendF($"\t{defaultValue}\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool GetString(StringView key, String outVal)
|
||||||
|
{
|
||||||
|
if (mParams.TryGetAlt(key, var matchKey, var value))
|
||||||
|
{
|
||||||
|
outVal.Append(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void InitUI()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Generate(String outFileName, String outText, ref Flags generateFlags)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static String GetName<T>() where T : Generator
|
||||||
|
{
|
||||||
|
T val = scope T();
|
||||||
|
String str = val.Name;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HandleArgs(String args)
|
||||||
|
{
|
||||||
|
for (var line in args.Split('\n', .RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
int tabPos = line.IndexOf('\t');
|
||||||
|
var key = line.Substring(0, tabPos);
|
||||||
|
var value = line.Substring(tabPos + 1);
|
||||||
|
if (mParams.TryAdd(key, var keyPtr, var valuePtr))
|
||||||
|
{
|
||||||
|
*keyPtr = key;
|
||||||
|
*valuePtr = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static String InitUI<T>(String args) where T : Generator
|
||||||
|
{
|
||||||
|
T val = scope T();
|
||||||
|
val.HandleArgs(args);
|
||||||
|
val.InitUI();
|
||||||
|
return val.mCmdInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static String Generate<T>(String args) where T : Generator
|
||||||
|
{
|
||||||
|
T val = scope T();
|
||||||
|
val.HandleArgs(args);
|
||||||
|
String fileName = scope .();
|
||||||
|
String outText = scope .();
|
||||||
|
Flags flags = .None;
|
||||||
|
val.Generate(fileName, outText, ref flags);
|
||||||
|
val.mCmdInfo.Append("fileName\t");
|
||||||
|
fileName.QuoteString(val.mCmdInfo);
|
||||||
|
val.mCmdInfo.Append("\n");
|
||||||
|
val.mCmdInfo.Append("data\n");
|
||||||
|
|
||||||
|
if (flags.HasFlag(.AllowRegenerate))
|
||||||
|
{
|
||||||
|
bool writeArg = false;
|
||||||
|
for (var line in args.Split('\n', .RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
int tabPos = line.IndexOf('\t');
|
||||||
|
var key = line.Substring(0, tabPos);
|
||||||
|
var value = line.Substring(tabPos + 1);
|
||||||
|
|
||||||
|
if (key == "Generator")
|
||||||
|
writeArg = true;
|
||||||
|
if (writeArg)
|
||||||
|
{
|
||||||
|
val.mCmdInfo.AppendF($"// {key}={value}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var hash = MD5.Hash(.((.)outText.Ptr, outText.Length));
|
||||||
|
val.mCmdInfo.AppendF($"// GenHash={hash}\n\n");
|
||||||
|
}
|
||||||
|
val.mCmdInfo.Append(outText);
|
||||||
|
return val.mCmdInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class NewClassGenerator : Generator
|
||||||
|
{
|
||||||
|
public override String Name => "New Class";
|
||||||
|
|
||||||
|
public override void InitUI()
|
||||||
|
{
|
||||||
|
AddEdit("name", "Class Name", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Generate(String outFileName, String outText, ref Flags generateFlags)
|
||||||
|
{
|
||||||
|
var name = mParams["name"];
|
||||||
|
if (name.EndsWith(".bf", .OrdinalIgnoreCase))
|
||||||
|
name.RemoveFromEnd(3);
|
||||||
|
outFileName.Append(name);
|
||||||
|
outText.AppendF(
|
||||||
|
$"""
|
||||||
|
namespace {Namespace}
|
||||||
|
{{
|
||||||
|
class {name}
|
||||||
|
{{
|
||||||
|
}}
|
||||||
|
}}
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public struct MethodBuilder
|
public struct MethodBuilder
|
||||||
{
|
{
|
||||||
void* mNative;
|
void* mNative;
|
||||||
|
@ -43,7 +224,7 @@ namespace System
|
||||||
public static extern String CallerProject;
|
public static extern String CallerProject;
|
||||||
|
|
||||||
[LinkName("#CallerExpression")]
|
[LinkName("#CallerExpression")]
|
||||||
public static extern String[0x0FFFFFFF] CallerExpression;
|
public static extern String[0x00FFFFFF] CallerExpression;
|
||||||
|
|
||||||
[LinkName("#ProjectName")]
|
[LinkName("#ProjectName")]
|
||||||
public static extern String ProjectName;
|
public static extern String ProjectName;
|
||||||
|
@ -76,6 +257,7 @@ namespace System
|
||||||
static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str);
|
static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str);
|
||||||
static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
|
static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags);
|
||||||
static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
|
static extern void Comptime_EmitTypeBody(int32 typeId, StringView text);
|
||||||
|
static extern void Comptime_EmitAddInterface(int32 typeId, int32 ifaceTypeId);
|
||||||
static extern void Comptime_EmitMethodEntry(int64 methodHandle, StringView text);
|
static extern void Comptime_EmitMethodEntry(int64 methodHandle, StringView text);
|
||||||
static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text);
|
static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text);
|
||||||
static extern void Comptime_EmitMixin(StringView text);
|
static extern void Comptime_EmitMixin(StringView text);
|
||||||
|
@ -94,6 +276,12 @@ namespace System
|
||||||
Comptime_EmitTypeBody((.)owner.TypeId, text);
|
Comptime_EmitTypeBody((.)owner.TypeId, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Comptime(OnlyFromComptime=true)]
|
||||||
|
public static void EmitAddInterface(Type owner, Type iface)
|
||||||
|
{
|
||||||
|
Comptime_EmitAddInterface((.)owner.TypeId, (.)iface.TypeId);
|
||||||
|
}
|
||||||
|
|
||||||
[Comptime(OnlyFromComptime=true)]
|
[Comptime(OnlyFromComptime=true)]
|
||||||
public static void EmitMethodEntry(ComptimeMethodInfo methodHandle, StringView text)
|
public static void EmitMethodEntry(ComptimeMethodInfo methodHandle, StringView text)
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,8 +21,7 @@ namespace System
|
||||||
public const double NegativeInfinity = (double)(- 1.0 / (double)(0.0));
|
public const double NegativeInfinity = (double)(- 1.0 / (double)(0.0));
|
||||||
public const double PositiveInfinity = (double)1.0 / (double)(0.0);
|
public const double PositiveInfinity = (double)1.0 / (double)(0.0);
|
||||||
public const double NaN = (double)0.0 / (double)0.0;
|
public const double NaN = (double)0.0 / (double)0.0;
|
||||||
|
public const double NegativeZero = -0.0;
|
||||||
static double NegativeZero = BitConverter.Convert<int64, double>(0x8000000000000000UL);
|
|
||||||
|
|
||||||
public static int operator<=>(Double a, Double b)
|
public static int operator<=>(Double a, Double b)
|
||||||
{
|
{
|
||||||
|
|
|
@ -163,7 +163,7 @@ namespace System
|
||||||
public static mixin Mark<T>(T val) where T : struct
|
public static mixin Mark<T>(T val) where T : struct
|
||||||
{
|
{
|
||||||
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
#if BF_ENABLE_REALTIME_LEAK_CHECK
|
||||||
val.[Friend]GCMarkMembers();
|
val.[Friend, Unbound]GCMarkMembers();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace System.IO
|
||||||
|
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
mPos = Math.Min(value, Length);
|
mPos = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,20 +43,16 @@ namespace System.IO
|
||||||
|
|
||||||
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
|
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
|
||||||
{
|
{
|
||||||
int64 length = Length;
|
|
||||||
|
|
||||||
int64 newPos;
|
|
||||||
switch (seekKind)
|
switch (seekKind)
|
||||||
{
|
{
|
||||||
case .Absolute:
|
case .Absolute:
|
||||||
mPos = Math.Min(pos, length);
|
mPos = pos;
|
||||||
if (pos > length)
|
|
||||||
return .Err;
|
|
||||||
case .FromEnd:
|
case .FromEnd:
|
||||||
newPos = length - pos;
|
mPos = Length + pos;
|
||||||
case .Relative:
|
case .Relative:
|
||||||
mPos = Math.Min(mPos + pos, length);
|
mPos = mPos + pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +172,12 @@ namespace System.IO
|
||||||
|
|
||||||
public override Result<void> Close()
|
public override Result<void> Close()
|
||||||
{
|
{
|
||||||
return Flush();
|
let ret = Flush();
|
||||||
|
|
||||||
|
mPos = 0;
|
||||||
|
mBufferPos = -Int32.MinValue;
|
||||||
|
mBufferEnd = -Int32.MinValue;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
580
BeefLibs/corlib/src/IO/FileDialog.bf
Normal file
580
BeefLibs/corlib/src/IO/FileDialog.bf
Normal file
|
@ -0,0 +1,580 @@
|
||||||
|
// This file contains portions of code released by Microsoft under the MIT license as part
|
||||||
|
// of an open-sourcing initiative in 2014 of the C# core libraries.
|
||||||
|
// The original source was submitted to https://github.com/Microsoft/referencesource
|
||||||
|
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
namespace System.IO
|
||||||
|
{
|
||||||
|
enum DialogResult
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
OK = 1,
|
||||||
|
Cancel = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class CommonDialog
|
||||||
|
{
|
||||||
|
public Windows.HWnd mHWnd;
|
||||||
|
public Windows.HWnd mDefaultControlHwnd;
|
||||||
|
public int mDefWndProc;
|
||||||
|
|
||||||
|
private const int32 CDM_SETDEFAULTFOCUS = Windows.WM_USER + 0x51;
|
||||||
|
|
||||||
|
public static Dictionary<int, CommonDialog> sHookMap = new Dictionary<int, CommonDialog>() ~
|
||||||
|
{
|
||||||
|
Debug.Assert(sHookMap.Count == 0);
|
||||||
|
delete _;
|
||||||
|
};
|
||||||
|
public static Monitor sMonitor = new Monitor() ~ delete _;
|
||||||
|
|
||||||
|
public Result<DialogResult> ShowDialog(INativeWindow owner = null)
|
||||||
|
{
|
||||||
|
Windows.HWnd hwndOwner = 0;
|
||||||
|
if (owner != null)
|
||||||
|
hwndOwner = (.)owner.Handle;
|
||||||
|
//Native.WndProc wndProc = scope => OwnerWndProc;
|
||||||
|
|
||||||
|
//mDefWndProc = Native.SetWindowLong(mHWnd, Native.GWL_WNDPROC, (intptr)wndProc.GetFuncPtr().Value);
|
||||||
|
|
||||||
|
var result = RunDialog(hwndOwner);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int OwnerWndProc(Windows.HWnd hWnd, int32 msg, int wParam, int lParam)
|
||||||
|
{
|
||||||
|
return Windows.CallWindowProcW(mDefWndProc, hWnd, msg, wParam, lParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual int HookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
||||||
|
{
|
||||||
|
if (msg == Windows.WM_INITDIALOG)
|
||||||
|
{
|
||||||
|
//TODO: MoveToScreenCenter(hWnd);
|
||||||
|
// Under some circumstances, the dialog
|
||||||
|
// does not initially focus on any control. We fix that by explicitly
|
||||||
|
// setting focus ourselves. See ASURT 39435.
|
||||||
|
//
|
||||||
|
mDefaultControlHwnd = (Windows.HWnd)wParam;
|
||||||
|
if (mDefaultControlHwnd != 0)
|
||||||
|
Windows.SetFocus(mDefaultControlHwnd);
|
||||||
|
}
|
||||||
|
else if (msg == Windows.WM_SETFOCUS)
|
||||||
|
{
|
||||||
|
Windows.PostMessageW(hWnd, CDM_SETDEFAULTFOCUS, 0, 0);
|
||||||
|
}
|
||||||
|
else if (msg == CDM_SETDEFAULTFOCUS)
|
||||||
|
{
|
||||||
|
// If the dialog box gets focus, bounce it to the default control.
|
||||||
|
// so we post a message back to ourselves to wait for the focus change then push it to the default
|
||||||
|
// control. See ASURT 84016.
|
||||||
|
//
|
||||||
|
if (mDefaultControlHwnd != 0)
|
||||||
|
Windows.SetFocus(mDefaultControlHwnd);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract Result<DialogResult> RunDialog(Windows.HWnd hWndOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class FileDialog : CommonDialog
|
||||||
|
{
|
||||||
|
protected abstract Result<DialogResult> RunFileDialog(ref Windows.OpenFileName ofn);
|
||||||
|
|
||||||
|
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
||||||
|
{
|
||||||
|
if (TryRunDialogVista(hWndOwner) case .Ok(let result))
|
||||||
|
return .Ok(result);
|
||||||
|
|
||||||
|
return RunDialogOld(hWndOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int32 FILEBUFSIZE = 8192;
|
||||||
|
protected const int32 OPTION_ADDEXTENSION = (int32)0x80000000;
|
||||||
|
|
||||||
|
protected int32 mOptions;
|
||||||
|
private String mTitle ~ delete _;
|
||||||
|
private String mInitialDir ~ delete _;
|
||||||
|
private String mDefaultExt ~ delete _;
|
||||||
|
protected String[] mFileNames ~ DeleteContainerAndItems!(_);
|
||||||
|
private bool mSecurityCheckFileNames;
|
||||||
|
private String mFilter ~ delete _;
|
||||||
|
private String mFilterBuffer = new String() ~ delete _;
|
||||||
|
private int32 mFilterIndex;
|
||||||
|
private bool mSupportMultiDottedExtensions;
|
||||||
|
private bool mIgnoreSecondFileOkNotification; // Used for VS Whidbey 95342
|
||||||
|
private int32 mOKNotificationCount; // Same
|
||||||
|
//private String char8Buffer = new String(FILEBUFSIZE) ~ delete _;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Reset()
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(mTitle);
|
||||||
|
DeleteAndNullify!(mInitialDir);
|
||||||
|
DeleteAndNullify!(mDefaultExt);
|
||||||
|
DeleteContainerAndItems!(mFileNames);
|
||||||
|
mFileNames = null;
|
||||||
|
DeleteAndNullify!(mFilter);
|
||||||
|
mFilterIndex = 1;
|
||||||
|
mSupportMultiDottedExtensions = false;
|
||||||
|
mOptions = Windows.OFN_HIDEREADONLY | Windows.OFN_PATHMUSTEXIST |
|
||||||
|
OPTION_ADDEXTENSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected int32 Options
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mOptions & (
|
||||||
|
Windows.OFN_READONLY |
|
||||||
|
Windows.OFN_HIDEREADONLY |
|
||||||
|
Windows.OFN_NOCHANGEDIR |
|
||||||
|
Windows.OFN_SHOWHELP |
|
||||||
|
Windows.OFN_NOVALIDATE |
|
||||||
|
Windows.OFN_ALLOWMULTISELECT |
|
||||||
|
Windows.OFN_PATHMUSTEXIST |
|
||||||
|
Windows.OFN_FILEMUSTEXIST |
|
||||||
|
Windows.OFN_NODEREFERENCELINKS |
|
||||||
|
Windows.OFN_OVERWRITEPROMPT);
|
||||||
|
//return mOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView Title
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
String.NewOrSet!(mTitle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mTitle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView InitialDirectory
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
String.NewOrSet!(mInitialDir, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mInitialDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] FileNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mFileNames;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView FileName
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (mFileNames == null)
|
||||||
|
{
|
||||||
|
mFileNames = new String[](new String(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool AddExtension
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(OPTION_ADDEXTENSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(OPTION_ADDEXTENSION, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual bool CheckFileExists
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(Windows.OFN_FILEMUSTEXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_FILEMUSTEXIST, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DereferenceLinks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !GetOption(Windows.OFN_NODEREFERENCELINKS);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_NODEREFERENCELINKS, !value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckPathExists
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(Windows.OFN_PATHMUSTEXIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_PATHMUSTEXIST, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Multiselect
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetOption(Windows.OFN_ALLOWMULTISELECT);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_ALLOWMULTISELECT, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool ValidateNames
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return !GetOption(Windows.OFN_NOVALIDATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetOption(Windows.OFN_NOVALIDATE, !value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringView DefaultExt
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return mDefaultExt == null ? "" : mDefaultExt;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
delete mDefaultExt;
|
||||||
|
mDefaultExt = null;
|
||||||
|
|
||||||
|
//if (!String.IsNullOrEmpty(value))
|
||||||
|
if (value.Length > 0)
|
||||||
|
{
|
||||||
|
mDefaultExt = new String(value);
|
||||||
|
if (mDefaultExt.StartsWith("."))
|
||||||
|
mDefaultExt.Remove(0, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetFilter(String outFilter)
|
||||||
|
{
|
||||||
|
if (mFilter != null)
|
||||||
|
outFilter.Append(mFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<void> SetFilter(StringView value)
|
||||||
|
{
|
||||||
|
String useValue = scope String(value);
|
||||||
|
if (useValue != null && useValue.Length > 0)
|
||||||
|
{
|
||||||
|
var formats = String.StackSplit!(useValue, '|');
|
||||||
|
if (formats == null || formats.Count % 2 != 0)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
///
|
||||||
|
/*String[] formats = value.Split('|');
|
||||||
|
if (formats == null || formats.Length % 2 != 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentException(SR.GetString(SR.FileDialogInvalidFilter));
|
||||||
|
}*/
|
||||||
|
String.NewOrSet!(mFilter, useValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
useValue = null;
|
||||||
|
DeleteAndNullify!(mFilter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected bool GetOption(int32 option)
|
||||||
|
{
|
||||||
|
return (mOptions & option) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void SetOption(int32 option, bool value)
|
||||||
|
{
|
||||||
|
if (value)
|
||||||
|
{
|
||||||
|
mOptions |= option;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mOptions &= ~option;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Result<void> MakeFilterString(String s, bool dereferenceLinks, String filterBuffer)
|
||||||
|
{
|
||||||
|
String useStr = s;
|
||||||
|
if (useStr == null || useStr.Length == 0)
|
||||||
|
{
|
||||||
|
// Workaround for Whidbey bug #5165
|
||||||
|
// Apply the workaround only when DereferenceLinks is true and OS is at least WinXP.
|
||||||
|
if (dereferenceLinks && System.Environment.OSVersion.Version.Major >= 5)
|
||||||
|
{
|
||||||
|
useStr = " |*.*";
|
||||||
|
}
|
||||||
|
else if (useStr == null)
|
||||||
|
{
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterBuffer.Set(s);
|
||||||
|
for (int32 i = 0; i < filterBuffer.Length; i++)
|
||||||
|
if (filterBuffer[i] == '|')
|
||||||
|
filterBuffer[i] = (char8)0;
|
||||||
|
filterBuffer.Append((char8)0);
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Result<DialogResult> RunDialogOld(Windows.HWnd hWndOwner)
|
||||||
|
{
|
||||||
|
//RunDialogTest(hWndOwner);
|
||||||
|
|
||||||
|
Windows.WndProc hookProcPtr = => StaticHookProc;
|
||||||
|
Windows.OpenFileName ofn = Windows.OpenFileName();
|
||||||
|
|
||||||
|
char16[FILEBUFSIZE] char16Buffer = .(0, ?);
|
||||||
|
|
||||||
|
if (mFileNames != null && !mFileNames.IsEmpty)
|
||||||
|
{
|
||||||
|
//int len = UTF16.GetEncodedLen(fileNames[0]);
|
||||||
|
//char16Buffer = scope:: char16[len + 1]*;
|
||||||
|
UTF16.Encode(mFileNames[0], (char16*)&char16Buffer, FILEBUFSIZE);
|
||||||
|
}
|
||||||
|
// Degrade to the older style dialog if we're not on Win2K.
|
||||||
|
// We do this by setting the struct size to a different value
|
||||||
|
//
|
||||||
|
|
||||||
|
if (Environment.OSVersion.Platform != System.PlatformID.Win32NT ||
|
||||||
|
Environment.OSVersion.Version.Major < 5) {
|
||||||
|
ofn.mStructSize = 0x4C;
|
||||||
|
}
|
||||||
|
ofn.mHwndOwner = hWndOwner;
|
||||||
|
ofn.mHInstance = (Windows.HInstance)Windows.GetModuleHandleW(null);
|
||||||
|
|
||||||
|
if (mFilter != null)
|
||||||
|
{
|
||||||
|
Try!(MakeFilterString(mFilter, this.DereferenceLinks, mFilterBuffer));
|
||||||
|
ofn.mFilter = mFilterBuffer.ToScopedNativeWChar!::();
|
||||||
|
}
|
||||||
|
ofn.nFilterIndex = mFilterIndex;
|
||||||
|
ofn.mFile = (char16*)&char16Buffer;
|
||||||
|
ofn.nMaxFile = FILEBUFSIZE;
|
||||||
|
if (mInitialDir != null)
|
||||||
|
ofn.mInitialDir = mInitialDir.ToScopedNativeWChar!::();
|
||||||
|
if (mTitle != null)
|
||||||
|
ofn.mTitle = mTitle.ToScopedNativeWChar!::();
|
||||||
|
ofn.mFlags = Options | (Windows.OFN_EXPLORER | Windows.OFN_ENABLEHOOK | Windows.OFN_ENABLESIZING);
|
||||||
|
ofn.mHook = hookProcPtr;
|
||||||
|
ofn.mCustData = (int)Internal.UnsafeCastToPtr(this);
|
||||||
|
ofn.mFlagsEx = Windows.OFN_USESHELLITEM;
|
||||||
|
if (mDefaultExt != null && AddExtension)
|
||||||
|
ofn.mDefExt = mDefaultExt.ToScopedNativeWChar!::();
|
||||||
|
|
||||||
|
DeleteContainerAndItems!(mFileNames);
|
||||||
|
mFileNames = null;
|
||||||
|
//Security checks happen here
|
||||||
|
return RunFileDialog(ref ofn);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int StaticHookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
||||||
|
{
|
||||||
|
if (msg == Windows.WM_INITDIALOG)
|
||||||
|
{
|
||||||
|
using (sMonitor.Enter())
|
||||||
|
{
|
||||||
|
var ofn = (Windows.OpenFileName*)(void*)lparam;
|
||||||
|
sHookMap[(int)hWnd] = (CommonDialog)Internal.UnsafeCastToObject((void*)ofn.mCustData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonDialog dlg;
|
||||||
|
using (sMonitor.Enter())
|
||||||
|
{
|
||||||
|
sHookMap.TryGetValue((int)hWnd, out dlg);
|
||||||
|
}
|
||||||
|
if (dlg == null)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
dlg.[Friend]HookProc(hWnd, msg, wParam, lparam);
|
||||||
|
if (msg == Windows.WM_DESTROY)
|
||||||
|
{
|
||||||
|
using (sMonitor.Enter())
|
||||||
|
{
|
||||||
|
sHookMap.Remove((int)hWnd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//TODO: Add ProcessFileNames for validation
|
||||||
|
|
||||||
|
protected abstract Result<Windows.COM_IFileDialog*> CreateVistaDialog();
|
||||||
|
|
||||||
|
private Result<DialogResult> TryRunDialogVista(Windows.HWnd hWndOwner)
|
||||||
|
{
|
||||||
|
Windows.COM_IFileDialog* dialog;
|
||||||
|
if (!(CreateVistaDialog() case .Ok(out dialog)))
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
OnBeforeVistaDialog(dialog);
|
||||||
|
dialog.VT.Show(dialog, hWndOwner);
|
||||||
|
|
||||||
|
List<String> files = scope .();
|
||||||
|
ProcessVistaFiles(dialog, files);
|
||||||
|
|
||||||
|
DeleteContainerAndItems!(mFileNames);
|
||||||
|
mFileNames = new String[files.Count];
|
||||||
|
files.CopyTo(mFileNames);
|
||||||
|
|
||||||
|
dialog.VT.Release(dialog);
|
||||||
|
|
||||||
|
return .Ok(files.IsEmpty ? .Cancel : .OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnBeforeVistaDialog(Windows.COM_IFileDialog* dialog)
|
||||||
|
{
|
||||||
|
dialog.VT.SetDefaultExtension(dialog, DefaultExt.ToScopedNativeWChar!());
|
||||||
|
|
||||||
|
if (mFileNames != null && !mFileNames.IsEmpty)
|
||||||
|
dialog.VT.SetFileName(dialog, mFileNames[0].ToScopedNativeWChar!());
|
||||||
|
|
||||||
|
if (!String.IsNullOrEmpty(mInitialDir))
|
||||||
|
{
|
||||||
|
Windows.COM_IShellItem* folderShellItem = null;
|
||||||
|
Windows.SHCreateItemFromParsingName(mInitialDir.ToScopedNativeWChar!(), null, Windows.COM_IShellItem.sIID, (void**)&folderShellItem);
|
||||||
|
if (folderShellItem != null)
|
||||||
|
{
|
||||||
|
dialog.VT.SetDefaultFolder(dialog, folderShellItem);
|
||||||
|
dialog.VT.SetFolder(dialog, folderShellItem);
|
||||||
|
folderShellItem.VT.Release(folderShellItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.VT.SetTitle(dialog, mTitle.ToScopedNativeWChar!());
|
||||||
|
dialog.VT.SetOptions(dialog, GetOptions());
|
||||||
|
SetFileTypes(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Windows.COM_IFileDialog.FOS GetOptions()
|
||||||
|
{
|
||||||
|
const Windows.COM_IFileDialog.FOS BlittableOptions =
|
||||||
|
Windows.COM_IFileDialog.FOS.OVERWRITEPROMPT
|
||||||
|
| Windows.COM_IFileDialog.FOS.NOCHANGEDIR
|
||||||
|
| Windows.COM_IFileDialog.FOS.NOVALIDATE
|
||||||
|
| Windows.COM_IFileDialog.FOS.ALLOWMULTISELECT
|
||||||
|
| Windows.COM_IFileDialog.FOS.PATHMUSTEXIST
|
||||||
|
| Windows.COM_IFileDialog.FOS.FILEMUSTEXIST
|
||||||
|
| Windows.COM_IFileDialog.FOS.CREATEPROMPT
|
||||||
|
| Windows.COM_IFileDialog.FOS.NODEREFERENCELINKS;
|
||||||
|
|
||||||
|
const int32 UnexpectedOptions =
|
||||||
|
(int32)(Windows.OFN_SHOWHELP // If ShowHelp is true, we don't use the Vista Dialog
|
||||||
|
| Windows.OFN_ENABLEHOOK // These shouldn't be set in options (only set in the flags for the legacy dialog)
|
||||||
|
| Windows.OFN_ENABLESIZING // These shouldn't be set in options (only set in the flags for the legacy dialog)
|
||||||
|
| Windows.OFN_EXPLORER); // These shouldn't be set in options (only set in the flags for the legacy dialog)
|
||||||
|
|
||||||
|
Debug.Assert((UnexpectedOptions & mOptions) == 0, "Unexpected FileDialog options");
|
||||||
|
|
||||||
|
Windows.COM_IFileDialog.FOS ret = (Windows.COM_IFileDialog.FOS)mOptions & BlittableOptions;
|
||||||
|
|
||||||
|
// Force no mini mode for the SaveFileDialog
|
||||||
|
ret |= Windows.COM_IFileDialog.FOS.DEFAULTNOMINIMODE;
|
||||||
|
|
||||||
|
// Make sure that the Open dialog allows the user to specify
|
||||||
|
// non-file system locations. This flag will cause the dialog to copy the resource
|
||||||
|
// to a local cache (Temporary Internet Files), and return that path instead. This
|
||||||
|
// also affects the Save dialog by disallowing navigation to these areas.
|
||||||
|
// An example of a non-file system location is a URL (http://), or a file stored on
|
||||||
|
// a digital camera that is not mapped to a drive letter.
|
||||||
|
// This reproduces the behavior of the "classic" Open and Save dialogs.
|
||||||
|
ret |= Windows.COM_IFileDialog.FOS.FORCEFILESYSTEM;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void ProcessVistaFiles(Windows.COM_IFileDialog* dialog, List<String> files);
|
||||||
|
|
||||||
|
private Result<void> SetFileTypes(Windows.COM_IFileDialog* dialog)
|
||||||
|
{
|
||||||
|
List<Windows.COMDLG_FILTERSPEC> filterItems = scope .();
|
||||||
|
|
||||||
|
// Expected input types
|
||||||
|
// "Text files (*.txt)|*.txt|All files (*.*)|*.*"
|
||||||
|
// "Image Files(*.BMP;*.JPG;*.GIF)|*.BMP;*.JPG;*.GIF|All files (*.*)|*.*"
|
||||||
|
if (!String.IsNullOrEmpty(mFilter))
|
||||||
|
{
|
||||||
|
StringView[] tokens = mFilter.Split!('|');
|
||||||
|
if (0 == tokens.Count % 2)
|
||||||
|
{
|
||||||
|
// All even numbered tokens should be labels
|
||||||
|
// Odd numbered tokens are the associated extensions
|
||||||
|
for (int i = 1; i < tokens.Count; i += 2)
|
||||||
|
{
|
||||||
|
Windows.COMDLG_FILTERSPEC ext;
|
||||||
|
ext.pszSpec = tokens[i].ToScopedNativeWChar!::(); // This may be a semicolon delimited list of extensions (that's ok)
|
||||||
|
ext.pszName = tokens[i - 1].ToScopedNativeWChar!::();
|
||||||
|
filterItems.Add(ext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filterItems.IsEmpty)
|
||||||
|
return .Ok;
|
||||||
|
|
||||||
|
Windows.COM_IUnknown.HResult hr = dialog.VT.SetFileTypes(dialog, (uint32)filterItems.Count, filterItems.Ptr);
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
hr = dialog.VT.SetFileTypeIndex(dialog, (uint32)mFilterIndex);
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -296,6 +296,15 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int64 Position
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
// Matches the behavior of Platform.BfpFile_Seek(mBfpFile, value, .Absolute);
|
||||||
|
mPos = Math.Max(value, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -416,16 +425,37 @@ namespace System.IO
|
||||||
mFileAccess = access;
|
mFileAccess = access;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override Result<void> Seek(int64 pos, SeekKind seekKind = .Absolute)
|
||||||
|
{
|
||||||
|
int64 newPos;
|
||||||
|
switch (seekKind)
|
||||||
|
{
|
||||||
|
case .Absolute:
|
||||||
|
newPos = pos;
|
||||||
|
case .FromEnd:
|
||||||
|
newPos = Length + pos;
|
||||||
|
case .Relative:
|
||||||
|
newPos = mPos + pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Matches the behaviour of Platform.BfpFile_Seek(mBfpFile, value, .Absolute);
|
||||||
|
mPos = Math.Max(newPos, 0);
|
||||||
|
if (seekKind == .Absolute && newPos < 0)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
public override Result<void> Close()
|
public override Result<void> Close()
|
||||||
{
|
{
|
||||||
var hadError = Flush() case .Err;
|
let ret = base.Close();
|
||||||
if (mBfpFile != null)
|
if (mBfpFile != null)
|
||||||
Platform.BfpFile_Release(mBfpFile);
|
Platform.BfpFile_Release(mBfpFile);
|
||||||
|
|
||||||
mBfpFile = null;
|
mBfpFile = null;
|
||||||
mFileAccess = default;
|
mFileAccess = default;
|
||||||
if (hadError)
|
mBfpFilePos = 0;
|
||||||
return .Err;
|
return ret;
|
||||||
return .Ok;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UpdateLength()
|
protected override void UpdateLength()
|
||||||
|
|
|
@ -57,7 +57,7 @@ namespace System.IO
|
||||||
ShowNewFolderButton = true;
|
ShowNewFolderButton = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Result<DialogResult> RunDialog_New(Windows.HWnd hWndOwner, FolderBrowserDialog.COM_IFileDialog* fileDialog)
|
protected Result<DialogResult> RunDialog_New(Windows.HWnd hWndOwner, Windows.COM_IFileDialog* fileDialog)
|
||||||
{
|
{
|
||||||
//COM_IFileDialogEvents evts;
|
//COM_IFileDialogEvents evts;
|
||||||
/*COM_IFileDialogEvents.VTable funcs;
|
/*COM_IFileDialogEvents.VTable funcs;
|
||||||
|
@ -106,8 +106,8 @@ namespace System.IO
|
||||||
|
|
||||||
if (!mSelectedPath.IsEmpty)
|
if (!mSelectedPath.IsEmpty)
|
||||||
{
|
{
|
||||||
COM_IShellItem* folderShellItem = null;
|
Windows.COM_IShellItem* folderShellItem = null;
|
||||||
Windows.SHCreateItemFromParsingName(mSelectedPath.ToScopedNativeWChar!(), null, COM_IShellItem.sIID, (void**)&folderShellItem);
|
Windows.SHCreateItemFromParsingName(mSelectedPath.ToScopedNativeWChar!(), null, Windows.COM_IShellItem.sIID, (void**)&folderShellItem);
|
||||||
if (folderShellItem != null)
|
if (folderShellItem != null)
|
||||||
{
|
{
|
||||||
fileDialog.VT.SetDefaultFolder(fileDialog, folderShellItem);
|
fileDialog.VT.SetDefaultFolder(fileDialog, folderShellItem);
|
||||||
|
@ -121,7 +121,7 @@ namespace System.IO
|
||||||
DialogResult result = .Cancel;
|
DialogResult result = .Cancel;
|
||||||
|
|
||||||
mSelectedPath.Clear();
|
mSelectedPath.Clear();
|
||||||
COM_IShellItem* shellItem = null;
|
Windows.COM_IShellItem* shellItem = null;
|
||||||
fileDialog.VT.GetResult(fileDialog, out shellItem);
|
fileDialog.VT.GetResult(fileDialog, out shellItem);
|
||||||
if (shellItem != null)
|
if (shellItem != null)
|
||||||
{
|
{
|
||||||
|
@ -142,10 +142,10 @@ namespace System.IO
|
||||||
|
|
||||||
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
||||||
{
|
{
|
||||||
FolderBrowserDialog.COM_IFileDialog* fileDialog = null;
|
Windows.COM_IFileDialog* fileDialog = null;
|
||||||
Windows.COM_IUnknown.HResult hr;
|
Windows.COM_IUnknown.HResult hr;
|
||||||
//if (mFolderKind == .Open)
|
//if (mFolderKind == .Open)
|
||||||
hr = Windows.COM_IUnknown.CoCreateInstance(ref FolderBrowserDialog.COM_IFileDialog.sCLSID, null, .INPROC_SERVER, ref FolderBrowserDialog.COM_IFileDialog.sIID, (void**)&fileDialog);
|
hr = Windows.COM_IUnknown.CoCreateInstance(ref Windows.COM_IFileDialog.sCLSID, null, .INPROC_SERVER, ref Windows.COM_IFileDialog.sIID, (void**)&fileDialog);
|
||||||
//else
|
//else
|
||||||
//hr = Windows.COM_IUnknown.CoCreateInstance(ref FolderBrowserDialog.COM_FileSaveDialog.sCLSID, null, .INPROC_SERVER, ref FolderBrowserDialog.COM_FileSaveDialog.sIID, (void**)&fileDialog);
|
//hr = Windows.COM_IUnknown.CoCreateInstance(ref FolderBrowserDialog.COM_FileSaveDialog.sCLSID, null, .INPROC_SERVER, ref FolderBrowserDialog.COM_FileSaveDialog.sIID, (void**)&fileDialog);
|
||||||
if (hr == 0)
|
if (hr == 0)
|
||||||
|
@ -219,143 +219,6 @@ namespace System.IO
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FDE_SHAREVIOLATION_RESPONSE;
|
|
||||||
struct FDE_OVERWRITE_RESPONSE;
|
|
||||||
|
|
||||||
struct COM_IFileDialogEvents : Windows.COM_IUnknown
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct COM_IShellItem : Windows.COM_IUnknown
|
|
||||||
{
|
|
||||||
public static Guid sIID = .(0x43826d1e, 0xe718, 0x42ee, 0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe);
|
|
||||||
|
|
||||||
public enum SIGDN : uint32
|
|
||||||
{
|
|
||||||
NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL
|
|
||||||
PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING
|
|
||||||
DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING
|
|
||||||
PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING
|
|
||||||
DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
|
||||||
FILESYSPATH = 0x80058000, // SHGDN_FORPARSING
|
|
||||||
URL = 0x80068000, // SHGDN_FORPARSING
|
|
||||||
PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
|
||||||
PARENTRELATIVE = 0x80080001 // SHGDN_INFOLDER
|
|
||||||
}
|
|
||||||
|
|
||||||
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 new VTable* VT
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (.)mVT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct COMDLG_FILTERSPEC
|
|
||||||
{
|
|
||||||
public char16* pszName;
|
|
||||||
public char16* pszSpec;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum FDAP : uint32
|
|
||||||
{
|
|
||||||
FDAP_BOTTOM = 0x00000000,
|
|
||||||
FDAP_TOP = 0x00000001,
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct COM_IFileDialog : Windows.COM_IUnknown
|
|
||||||
{
|
|
||||||
public static Guid sIID = .(0x42f85136, 0xdb7e, 0x439c, 0x85, 0xf1, 0xe4, 0x07, 0x5d, 0x13, 0x5f, 0xc8);
|
|
||||||
public static Guid sCLSID = .(0xdc1c5a9c, 0xe88a, 0x4dde, 0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7);
|
|
||||||
|
|
||||||
///s
|
|
||||||
public enum FOS : uint32
|
|
||||||
{
|
|
||||||
OVERWRITEPROMPT = 0x00000002,
|
|
||||||
STRICTFILETYPES = 0x00000004,
|
|
||||||
NOCHANGEDIR = 0x00000008,
|
|
||||||
PICKFOLDERS = 0x00000020,
|
|
||||||
FORCEFILESYSTEM = 0x00000040,
|
|
||||||
ALLNONSTORAGEITEMS = 0x00000080,
|
|
||||||
NOVALIDATE = 0x00000100,
|
|
||||||
ALLOWMULTISELECT = 0x00000200,
|
|
||||||
PATHMUSTEXIST = 0x00000800,
|
|
||||||
FILEMUSTEXIST = 0x00001000,
|
|
||||||
CREATEPROMPT = 0x00002000,
|
|
||||||
SHAREAWARE = 0x00004000,
|
|
||||||
NOREADONLYRETURN = 0x00008000,
|
|
||||||
NOTESTFILECREATE = 0x00010000,
|
|
||||||
HIDEMRUPLACES = 0x00020000,
|
|
||||||
HIDEPINNEDPLACES = 0x00040000,
|
|
||||||
NODEREFERENCELINKS = 0x00100000,
|
|
||||||
DONTADDTORECENT = 0x02000000,
|
|
||||||
FORCESHOWHIDDEN = 0x10000000,
|
|
||||||
DEFAULTNOMINIMODE = 0x20000000
|
|
||||||
}
|
|
||||||
|
|
||||||
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 new VTable* VT
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return (.)mVT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public struct COM_FileSaveDialog : COM_IFileDialog
|
|
||||||
{
|
|
||||||
public static new Guid sIID = .(0x84bccd23, 0x5fde, 0x4cdb, 0xae, 0xa4, 0xaf, 0x64, 0xb8, 0x3d, 0x78, 0xab);
|
|
||||||
public static new Guid sCLSID = .(0xC0B4E2F3, 0xBA21, 0x4773, 0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
|
@ -11,460 +11,6 @@ using System.Text;
|
||||||
|
|
||||||
namespace System.IO
|
namespace System.IO
|
||||||
{
|
{
|
||||||
enum DialogResult
|
|
||||||
{
|
|
||||||
None = 0,
|
|
||||||
OK = 1,
|
|
||||||
Cancel = 2
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class CommonDialog
|
|
||||||
{
|
|
||||||
public Windows.HWnd mHWnd;
|
|
||||||
public Windows.HWnd mDefaultControlHwnd;
|
|
||||||
public int mDefWndProc;
|
|
||||||
|
|
||||||
private const int32 CDM_SETDEFAULTFOCUS = Windows.WM_USER + 0x51;
|
|
||||||
|
|
||||||
public static Dictionary<int, CommonDialog> sHookMap = new Dictionary<int, CommonDialog>() ~
|
|
||||||
{
|
|
||||||
Debug.Assert(sHookMap.Count == 0);
|
|
||||||
delete _;
|
|
||||||
};
|
|
||||||
public static Monitor sMonitor = new Monitor() ~ delete _;
|
|
||||||
|
|
||||||
public Result<DialogResult> ShowDialog(INativeWindow owner = null)
|
|
||||||
{
|
|
||||||
Windows.HWnd hwndOwner = 0;
|
|
||||||
if (owner != null)
|
|
||||||
hwndOwner = (.)owner.Handle;
|
|
||||||
//Native.WndProc wndProc = scope => OwnerWndProc;
|
|
||||||
|
|
||||||
//mDefWndProc = Native.SetWindowLong(mHWnd, Native.GWL_WNDPROC, (intptr)wndProc.GetFuncPtr().Value);
|
|
||||||
|
|
||||||
var result = RunDialog(hwndOwner);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual int OwnerWndProc(Windows.HWnd hWnd, int32 msg, int wParam, int lParam)
|
|
||||||
{
|
|
||||||
return Windows.CallWindowProcW(mDefWndProc, hWnd, msg, wParam, lParam);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual int HookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
|
||||||
{
|
|
||||||
if (msg == Windows.WM_INITDIALOG)
|
|
||||||
{
|
|
||||||
//TODO: MoveToScreenCenter(hWnd);
|
|
||||||
// Under some circumstances, the dialog
|
|
||||||
// does not initially focus on any control. We fix that by explicitly
|
|
||||||
// setting focus ourselves. See ASURT 39435.
|
|
||||||
//
|
|
||||||
mDefaultControlHwnd = (Windows.HWnd)wParam;
|
|
||||||
if (mDefaultControlHwnd != 0)
|
|
||||||
Windows.SetFocus(mDefaultControlHwnd);
|
|
||||||
}
|
|
||||||
else if (msg == Windows.WM_SETFOCUS)
|
|
||||||
{
|
|
||||||
Windows.PostMessageW(hWnd, CDM_SETDEFAULTFOCUS, 0, 0);
|
|
||||||
}
|
|
||||||
else if (msg == CDM_SETDEFAULTFOCUS)
|
|
||||||
{
|
|
||||||
// If the dialog box gets focus, bounce it to the default control.
|
|
||||||
// so we post a message back to ourselves to wait for the focus change then push it to the default
|
|
||||||
// control. See ASURT 84016.
|
|
||||||
//
|
|
||||||
if (mDefaultControlHwnd != 0)
|
|
||||||
Windows.SetFocus(mDefaultControlHwnd);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Result<DialogResult> RunDialog(Windows.HWnd hWndOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class FileDialog : CommonDialog
|
|
||||||
{
|
|
||||||
protected abstract Result<DialogResult> RunFileDialog(ref Windows.OpenFileName ofn);
|
|
||||||
|
|
||||||
protected override Result<DialogResult> RunDialog(Windows.HWnd hWndOwner)
|
|
||||||
{
|
|
||||||
return RunDialogOld(hWndOwner);
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int32 FILEBUFSIZE = 8192;
|
|
||||||
protected const int32 OPTION_ADDEXTENSION = (int32)0x80000000;
|
|
||||||
|
|
||||||
protected int32 mOptions;
|
|
||||||
private String mTitle ~ delete _;
|
|
||||||
private String mInitialDir ~ delete _;
|
|
||||||
private String mDefaultExt ~ delete _;
|
|
||||||
protected String[] mFileNames ~ DeleteContainerAndItems!(_);
|
|
||||||
private bool mSecurityCheckFileNames;
|
|
||||||
private String mFilter ~ delete _;
|
|
||||||
private String mFilterBuffer = new String() ~ delete _;
|
|
||||||
private int32 mFilterIndex;
|
|
||||||
private bool mSupportMultiDottedExtensions;
|
|
||||||
private bool mIgnoreSecondFileOkNotification; // Used for VS Whidbey 95342
|
|
||||||
private int32 mOKNotificationCount; // Same
|
|
||||||
//private String char8Buffer = new String(FILEBUFSIZE) ~ delete _;
|
|
||||||
|
|
||||||
public this()
|
|
||||||
{
|
|
||||||
Reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Reset()
|
|
||||||
{
|
|
||||||
DeleteAndNullify!(mTitle);
|
|
||||||
DeleteAndNullify!(mInitialDir);
|
|
||||||
DeleteAndNullify!(mDefaultExt);
|
|
||||||
DeleteContainerAndItems!(mFileNames);
|
|
||||||
mFileNames = null;
|
|
||||||
DeleteAndNullify!(mFilter);
|
|
||||||
mFilterIndex = 1;
|
|
||||||
mSupportMultiDottedExtensions = false;
|
|
||||||
mOptions = Windows.OFN_HIDEREADONLY | Windows.OFN_PATHMUSTEXIST |
|
|
||||||
OPTION_ADDEXTENSION;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected int32 Options
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mOptions & (
|
|
||||||
Windows.OFN_READONLY |
|
|
||||||
Windows.OFN_HIDEREADONLY |
|
|
||||||
Windows.OFN_NOCHANGEDIR |
|
|
||||||
Windows.OFN_SHOWHELP |
|
|
||||||
Windows.OFN_NOVALIDATE |
|
|
||||||
Windows.OFN_ALLOWMULTISELECT |
|
|
||||||
Windows.OFN_PATHMUSTEXIST |
|
|
||||||
Windows.OFN_FILEMUSTEXIST |
|
|
||||||
Windows.OFN_NODEREFERENCELINKS |
|
|
||||||
Windows.OFN_OVERWRITEPROMPT);
|
|
||||||
//return mOptions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView Title
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
String.NewOrSet!(mTitle, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mTitle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView InitialDirectory
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
String.NewOrSet!(mInitialDir, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mInitialDir;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String[] FileNames
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mFileNames;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView FileName
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (mFileNames == null)
|
|
||||||
{
|
|
||||||
mFileNames = new String[](new String(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool AddExtension
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(OPTION_ADDEXTENSION);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(OPTION_ADDEXTENSION, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual bool CheckFileExists
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(Windows.OFN_FILEMUSTEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_FILEMUSTEXIST, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool DereferenceLinks
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !GetOption(Windows.OFN_NODEREFERENCELINKS);
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_NODEREFERENCELINKS, !value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool CheckPathExists
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(Windows.OFN_PATHMUSTEXIST);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_PATHMUSTEXIST, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Multiselect
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return GetOption(Windows.OFN_ALLOWMULTISELECT);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_ALLOWMULTISELECT, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool ValidateNames
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return !GetOption(Windows.OFN_NOVALIDATE);
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
SetOption(Windows.OFN_NOVALIDATE, !value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public StringView DefaultExt
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return mDefaultExt == null ? "" : mDefaultExt;
|
|
||||||
}
|
|
||||||
|
|
||||||
set
|
|
||||||
{
|
|
||||||
delete mDefaultExt;
|
|
||||||
mDefaultExt = null;
|
|
||||||
|
|
||||||
//if (!String.IsNullOrEmpty(value))
|
|
||||||
if (value.Length > 0)
|
|
||||||
{
|
|
||||||
mDefaultExt = new String(value);
|
|
||||||
if (mDefaultExt.StartsWith("."))
|
|
||||||
mDefaultExt.Remove(0, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void GetFilter(String outFilter)
|
|
||||||
{
|
|
||||||
if (mFilter != null)
|
|
||||||
outFilter.Append(mFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Result<void> SetFilter(StringView value)
|
|
||||||
{
|
|
||||||
String useValue = scope String(value);
|
|
||||||
if (useValue != null && useValue.Length > 0)
|
|
||||||
{
|
|
||||||
var formats = String.StackSplit!(useValue, '|');
|
|
||||||
if (formats == null || formats.Count % 2 != 0)
|
|
||||||
{
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
///
|
|
||||||
/*String[] formats = value.Split('|');
|
|
||||||
if (formats == null || formats.Length % 2 != 0)
|
|
||||||
{
|
|
||||||
throw new ArgumentException(SR.GetString(SR.FileDialogInvalidFilter));
|
|
||||||
}*/
|
|
||||||
String.NewOrSet!(mFilter, useValue);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
useValue = null;
|
|
||||||
DeleteAndNullify!(mFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected bool GetOption(int32 option)
|
|
||||||
{
|
|
||||||
return (mOptions & option) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void SetOption(int32 option, bool value)
|
|
||||||
{
|
|
||||||
if (value)
|
|
||||||
{
|
|
||||||
mOptions |= option;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mOptions &= ~option;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Result<void> MakeFilterString(String s, bool dereferenceLinks, String filterBuffer)
|
|
||||||
{
|
|
||||||
String useStr = s;
|
|
||||||
if (useStr == null || useStr.Length == 0)
|
|
||||||
{
|
|
||||||
// Workaround for Whidbey bug #5165
|
|
||||||
// Apply the workaround only when DereferenceLinks is true and OS is at least WinXP.
|
|
||||||
if (dereferenceLinks && System.Environment.OSVersion.Version.Major >= 5)
|
|
||||||
{
|
|
||||||
useStr = " |*.*";
|
|
||||||
}
|
|
||||||
else if (useStr == null)
|
|
||||||
{
|
|
||||||
return .Err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
filterBuffer.Set(s);
|
|
||||||
for (int32 i = 0; i < filterBuffer.Length; i++)
|
|
||||||
if (filterBuffer[i] == '|')
|
|
||||||
filterBuffer[i] = (char8)0;
|
|
||||||
filterBuffer.Append((char8)0);
|
|
||||||
return .Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static mixin Testie()
|
|
||||||
{
|
|
||||||
int a = 123;
|
|
||||||
char16* buf;
|
|
||||||
if (a == 0)
|
|
||||||
{
|
|
||||||
buf = null;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
buf = new char16[123]* ( ? );
|
|
||||||
defer:mixin delete buf;
|
|
||||||
}
|
|
||||||
buf
|
|
||||||
}
|
|
||||||
|
|
||||||
private Result<DialogResult> RunDialogOld(Windows.HWnd hWndOwner)
|
|
||||||
{
|
|
||||||
//RunDialogTest(hWndOwner);
|
|
||||||
|
|
||||||
Windows.WndProc hookProcPtr = => StaticHookProc;
|
|
||||||
Windows.OpenFileName ofn = Windows.OpenFileName();
|
|
||||||
|
|
||||||
char16[FILEBUFSIZE] char16Buffer = .(0, ?);
|
|
||||||
|
|
||||||
if (mFileNames != null)
|
|
||||||
{
|
|
||||||
//int len = UTF16.GetEncodedLen(fileNames[0]);
|
|
||||||
//char16Buffer = scope:: char16[len + 1]*;
|
|
||||||
UTF16.Encode(mFileNames[0], (char16*)&char16Buffer, FILEBUFSIZE);
|
|
||||||
}
|
|
||||||
// Degrade to the older style dialog if we're not on Win2K.
|
|
||||||
// We do this by setting the struct size to a different value
|
|
||||||
//
|
|
||||||
|
|
||||||
if (Environment.OSVersion.Platform != System.PlatformID.Win32NT ||
|
|
||||||
Environment.OSVersion.Version.Major < 5) {
|
|
||||||
ofn.mStructSize = 0x4C;
|
|
||||||
}
|
|
||||||
ofn.mHwndOwner = hWndOwner;
|
|
||||||
ofn.mHInstance = (Windows.HInstance)Windows.GetModuleHandleW(null);
|
|
||||||
|
|
||||||
if (mFilter != null)
|
|
||||||
{
|
|
||||||
Try!(MakeFilterString(mFilter, this.DereferenceLinks, mFilterBuffer));
|
|
||||||
ofn.mFilter = mFilterBuffer.ToScopedNativeWChar!::();
|
|
||||||
}
|
|
||||||
ofn.nFilterIndex = mFilterIndex;
|
|
||||||
ofn.mFile = (char16*)&char16Buffer;
|
|
||||||
ofn.nMaxFile = FILEBUFSIZE;
|
|
||||||
if (mInitialDir != null)
|
|
||||||
ofn.mInitialDir = mInitialDir.ToScopedNativeWChar!::();
|
|
||||||
if (mTitle != null)
|
|
||||||
ofn.mTitle = mTitle.ToScopedNativeWChar!::();
|
|
||||||
ofn.mFlags = Options | (Windows.OFN_EXPLORER | Windows.OFN_ENABLEHOOK | Windows.OFN_ENABLESIZING);
|
|
||||||
ofn.mHook = hookProcPtr;
|
|
||||||
ofn.mCustData = (int)Internal.UnsafeCastToPtr(this);
|
|
||||||
ofn.mFlagsEx = Windows.OFN_USESHELLITEM;
|
|
||||||
if (mDefaultExt != null && AddExtension)
|
|
||||||
ofn.mDefExt = mDefaultExt.ToScopedNativeWChar!::();
|
|
||||||
|
|
||||||
DeleteContainerAndItems!(mFileNames);
|
|
||||||
mFileNames = null;
|
|
||||||
//Security checks happen here
|
|
||||||
return RunFileDialog(ref ofn);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int StaticHookProc(Windows.HWnd hWnd, int32 msg, int wParam, int lparam)
|
|
||||||
{
|
|
||||||
if (msg == Windows.WM_INITDIALOG)
|
|
||||||
{
|
|
||||||
using (sMonitor.Enter())
|
|
||||||
{
|
|
||||||
var ofn = (Windows.OpenFileName*)(void*)lparam;
|
|
||||||
sHookMap[(int)hWnd] = (CommonDialog)Internal.UnsafeCastToObject((void*)ofn.mCustData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
CommonDialog dlg;
|
|
||||||
using (sMonitor.Enter())
|
|
||||||
{
|
|
||||||
sHookMap.TryGetValue((int)hWnd, out dlg);
|
|
||||||
}
|
|
||||||
if (dlg == null)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
dlg.[Friend]HookProc(hWnd, msg, wParam, lparam);
|
|
||||||
if (msg == Windows.WM_DESTROY)
|
|
||||||
{
|
|
||||||
using (sMonitor.Enter())
|
|
||||||
{
|
|
||||||
sHookMap.Remove((int)hWnd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
//TODO: Add ProcessFileNames for validation
|
|
||||||
}
|
|
||||||
|
|
||||||
class OpenFileDialog : FileDialog
|
class OpenFileDialog : FileDialog
|
||||||
{
|
{
|
||||||
public override void Reset()
|
public override void Reset()
|
||||||
|
@ -557,6 +103,73 @@ namespace System.IO
|
||||||
|
|
||||||
return DialogResult.OK;
|
return DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ProcessVistaFiles(Windows.COM_IFileDialog* dialog, List<String> files)
|
||||||
|
{
|
||||||
|
mixin GetFilePathFromShellItem(Windows.COM_IShellItem* shellItem)
|
||||||
|
{
|
||||||
|
String str = null;
|
||||||
|
if (shellItem.VT.GetDisplayName(shellItem, .FILESYSPATH, let cStr) == .OK)
|
||||||
|
{
|
||||||
|
str = new String()..Append(cStr);
|
||||||
|
Windows.COM_IUnknown.CoTaskMemFree(cStr);
|
||||||
|
}
|
||||||
|
str
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows.COM_IFileOpenDialog* openDialog = (.)dialog;
|
||||||
|
if (Multiselect)
|
||||||
|
{
|
||||||
|
Windows.COM_IShellItemArray* results = null;
|
||||||
|
openDialog.VT.GetResults(openDialog, out results);
|
||||||
|
|
||||||
|
if (results != null)
|
||||||
|
{
|
||||||
|
results.VT.GetCount(results, let count);
|
||||||
|
for (uint32 i < count)
|
||||||
|
{
|
||||||
|
Windows.COM_IShellItem* item = null;
|
||||||
|
results.VT.GetItemAt(results, i, out item);
|
||||||
|
if (item != null)
|
||||||
|
{
|
||||||
|
let filePath = GetFilePathFromShellItem!(item);
|
||||||
|
if (filePath != null)
|
||||||
|
files.Add(filePath);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results.VT.Release(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Windows.COM_IShellItem* shellItem = null;
|
||||||
|
openDialog.VT.GetResult(openDialog, out shellItem);
|
||||||
|
|
||||||
|
if (shellItem != null)
|
||||||
|
{
|
||||||
|
let filePath = GetFilePathFromShellItem!(shellItem);
|
||||||
|
if (filePath != null)
|
||||||
|
files.Add(filePath);
|
||||||
|
shellItem.VT.Release(shellItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Result<Windows.COM_IFileDialog*> CreateVistaDialog()
|
||||||
|
{
|
||||||
|
Windows.COM_IFileDialog* fileDialog = null;
|
||||||
|
|
||||||
|
Windows.COM_IUnknown.HResult hr = (Windows.COM_IUnknown.CoCreateInstance(
|
||||||
|
ref Windows.COM_IFileDialog.sCLSID,
|
||||||
|
null,
|
||||||
|
.INPROC_SERVER | .LOCAL_SERVER | .REMOTE_SERVER,
|
||||||
|
ref Windows.COM_IFileOpenDialog.sIID,
|
||||||
|
(void**)&fileDialog));
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return fileDialog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,48 @@ namespace System.IO
|
||||||
|
|
||||||
return DialogResult.OK;
|
return DialogResult.OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void ProcessVistaFiles(Windows.COM_IFileDialog* dialog, System.Collections.List<String> files)
|
||||||
|
{
|
||||||
|
mixin GetFilePathFromShellItem(Windows.COM_IShellItem* shellItem)
|
||||||
|
{
|
||||||
|
String str = null;
|
||||||
|
if (shellItem.VT.GetDisplayName(shellItem, .FILESYSPATH, let cStr) == .OK)
|
||||||
|
{
|
||||||
|
str = new String()..Append(cStr);
|
||||||
|
Windows.COM_IUnknown.CoTaskMemFree(cStr);
|
||||||
|
}
|
||||||
|
str
|
||||||
|
}
|
||||||
|
|
||||||
|
Windows.COM_IFileSaveDialog* saveDialog = (.)dialog;
|
||||||
|
Windows.COM_IShellItem* shellItem = null;
|
||||||
|
saveDialog.VT.GetResult(saveDialog, out shellItem);
|
||||||
|
|
||||||
|
if (shellItem != null)
|
||||||
|
{
|
||||||
|
let filePath = GetFilePathFromShellItem!(shellItem);
|
||||||
|
if (filePath != null)
|
||||||
|
files.Add(filePath);
|
||||||
|
shellItem.VT.Release(shellItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Result<Windows.COM_IFileDialog*> CreateVistaDialog()
|
||||||
|
{
|
||||||
|
Windows.COM_IFileDialog* fileDialog = null;
|
||||||
|
|
||||||
|
Windows.COM_IUnknown.HResult hr = (Windows.COM_IUnknown.CoCreateInstance(
|
||||||
|
ref Windows.COM_IFileSaveDialog.sCLSID,
|
||||||
|
null,
|
||||||
|
.INPROC_SERVER | .LOCAL_SERVER | .REMOTE_SERVER,
|
||||||
|
ref Windows.COM_IFileSaveDialog.sIID,
|
||||||
|
(void**)&fileDialog));
|
||||||
|
if (hr.Failed)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
return fileDialog;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1117,6 +1117,215 @@ namespace System
|
||||||
TRUSTEE_W Trustee;
|
TRUSTEE_W Trustee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct COM_IFileDialogEvents : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
struct FDE_SHAREVIOLATION_RESPONSE;
|
||||||
|
struct FDE_OVERWRITE_RESPONSE;
|
||||||
|
|
||||||
|
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 struct COM_IShellItem : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
public static Guid sIID = .(0x43826d1e, 0xe718, 0x42ee, 0xbc, 0x55, 0xa1, 0xe2, 0x61, 0xc3, 0x7b, 0xfe);
|
||||||
|
|
||||||
|
public enum SIGDN : uint32
|
||||||
|
{
|
||||||
|
NORMALDISPLAY = 0x00000000, // SHGDN_NORMAL
|
||||||
|
PARENTRELATIVEPARSING = 0x80018001, // SHGDN_INFOLDER | SHGDN_FORPARSING
|
||||||
|
DESKTOPABSOLUTEPARSING = 0x80028000, // SHGDN_FORPARSING
|
||||||
|
PARENTRELATIVEEDITING = 0x80031001, // SHGDN_INFOLDER | SHGDN_FOREDITING
|
||||||
|
DESKTOPABSOLUTEEDITING = 0x8004c000, // SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||||
|
FILESYSPATH = 0x80058000, // SHGDN_FORPARSING
|
||||||
|
URL = 0x80068000, // SHGDN_FORPARSING
|
||||||
|
PARENTRELATIVEFORADDRESSBAR = 0x8007c001, // SHGDN_INFOLDER | SHGDN_FORPARSING | SHGDN_FORADDRESSBAR
|
||||||
|
PARENTRELATIVE = 0x80080001 // SHGDN_INFOLDER
|
||||||
|
}
|
||||||
|
|
||||||
|
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 new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IShellItemArray : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
public enum GETPROPERTYSTOREFLAGS : uint
|
||||||
|
{
|
||||||
|
DEFAULT = 0x00000000,
|
||||||
|
HANDLERPROPERTIESONLY = 0x00000001,
|
||||||
|
READWRITE = 0x00000002,
|
||||||
|
TEMPORARY = 0x00000004,
|
||||||
|
FASTPROPERTIESONLY = 0x00000008,
|
||||||
|
OPENSLOWITEM = 0x00000010,
|
||||||
|
DELAYCREATION = 0x00000020,
|
||||||
|
BESTEFFORT = 0x00000040,
|
||||||
|
NO_OPLOCK = 0x00000080,
|
||||||
|
PREFERQUERYPROPERTIES = 0x00000100,
|
||||||
|
EXTRINSICPROPERTIES = 0x00000200,
|
||||||
|
EXTRINSICPROPERTIESONLY = 0x00000400,
|
||||||
|
VOLATILEPROPERTIES = 0x00000800,
|
||||||
|
VOLATILEPROPERTIESONLY = 0x00001000,
|
||||||
|
MASK_VALID = 0x00001FFF
|
||||||
|
}
|
||||||
|
|
||||||
|
[AllowDuplicates]
|
||||||
|
public enum SIATTRIBFLAGS : uint
|
||||||
|
{
|
||||||
|
AND = 0x1,
|
||||||
|
OR = 0x2,
|
||||||
|
APPCOMPAT = 0x3,
|
||||||
|
MASK = 0x3,
|
||||||
|
ALLITEMS = 0x4000
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct PROPERTYKEY;
|
||||||
|
|
||||||
|
public static Guid sIID = .(0xB63EA76D, 0x1F85, 0x456F, 0xA1, 0x9C, 0x48, 0x15, 0x9E, 0xFA, 0x85, 0x8B);
|
||||||
|
|
||||||
|
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 new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COMDLG_FILTERSPEC
|
||||||
|
{
|
||||||
|
public char16* pszName;
|
||||||
|
public char16* pszSpec;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FDAP : uint32
|
||||||
|
{
|
||||||
|
FDAP_BOTTOM = 0x00000000,
|
||||||
|
FDAP_TOP = 0x00000001,
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IFileDialog : Windows.COM_IUnknown
|
||||||
|
{
|
||||||
|
public static Guid sIID = .(0x42f85136, 0xdb7e, 0x439c, 0x85, 0xf1, 0xe4, 0x07, 0x5d, 0x13, 0x5f, 0xc8);
|
||||||
|
public static Guid sCLSID = .(0xdc1c5a9c, 0xe88a, 0x4dde, 0xa5, 0xa1, 0x60, 0xf8, 0x2a, 0x20, 0xae, 0xf7);
|
||||||
|
|
||||||
|
///s
|
||||||
|
public enum FOS : uint32
|
||||||
|
{
|
||||||
|
OVERWRITEPROMPT = 0x00000002,
|
||||||
|
STRICTFILETYPES = 0x00000004,
|
||||||
|
NOCHANGEDIR = 0x00000008,
|
||||||
|
PICKFOLDERS = 0x00000020,
|
||||||
|
FORCEFILESYSTEM = 0x00000040,
|
||||||
|
ALLNONSTORAGEITEMS = 0x00000080,
|
||||||
|
NOVALIDATE = 0x00000100,
|
||||||
|
ALLOWMULTISELECT = 0x00000200,
|
||||||
|
PATHMUSTEXIST = 0x00000800,
|
||||||
|
FILEMUSTEXIST = 0x00001000,
|
||||||
|
CREATEPROMPT = 0x00002000,
|
||||||
|
SHAREAWARE = 0x00004000,
|
||||||
|
NOREADONLYRETURN = 0x00008000,
|
||||||
|
NOTESTFILECREATE = 0x00010000,
|
||||||
|
HIDEMRUPLACES = 0x00020000,
|
||||||
|
HIDEPINNEDPLACES = 0x00040000,
|
||||||
|
NODEREFERENCELINKS = 0x00100000,
|
||||||
|
DONTADDTORECENT = 0x02000000,
|
||||||
|
FORCESHOWHIDDEN = 0x10000000,
|
||||||
|
DEFAULTNOMINIMODE = 0x20000000
|
||||||
|
}
|
||||||
|
|
||||||
|
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 new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IFileSaveDialog : COM_IFileDialog
|
||||||
|
{
|
||||||
|
public static new Guid sIID = .(0x84BCCD23, 0x5FDE, 0x4CDB, 0xAE, 0xA4, 0xAF, 0x64, 0xB8, 0x3D, 0x78, 0xAB);
|
||||||
|
public static new Guid sCLSID = .(0xC0B4E2F3, 0xBA21, 0x4773, 0x8D, 0xBA, 0x33, 0x5E, 0xC9, 0x46, 0xEB, 0x8B);
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct COM_IFileOpenDialog : COM_IFileDialog
|
||||||
|
{
|
||||||
|
public static new Guid sIID = .(0xD57C7288, 0xD4AD, 0x4768, 0xBE, 0x02, 0x9D, 0x96, 0x95, 0x32, 0xD9, 0x60);
|
||||||
|
|
||||||
|
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 new VTable* VT
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (.)mVT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Import("version.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("version.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
public static extern IntBool GetFileVersionInfoW(char16* lptstrFilename, uint32 dwHandle, uint32 dwLen, void* lpData);
|
public static extern IntBool GetFileVersionInfoW(char16* lptstrFilename, uint32 dwHandle, uint32 dwLen, void* lpData);
|
||||||
|
|
||||||
|
|
|
@ -830,8 +830,8 @@ public:
|
||||||
else if (size > this->mSize)
|
else if (size > this->mSize)
|
||||||
{
|
{
|
||||||
Reserve(size);
|
Reserve(size);
|
||||||
while (size > this->mSize)
|
memset(&this->mVals[this->mSize], 0, (size - this->mSize) * sizeof(T));
|
||||||
this->mVals[this->mSize++] = T();
|
this->mSize = (int_cosize)size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,7 @@ namespace IDETest
|
||||||
|
|
||||||
void MethodB()
|
void MethodB()
|
||||||
{
|
{
|
||||||
function void() f = => MethodA<T2>; //FAIL Method 'IDETest.Generics.ClassA<T1, T2>.MethodA<T2>(int a)' does not match function 'function void()'
|
function void() f = => MethodA<T2>; //FAIL Method 'void IDETest.Generics.ClassA<T1, T2>.MethodA<T2>(int a)' does not match function 'function void()'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,11 @@ namespace System
|
||||||
{
|
{
|
||||||
class Compiler
|
class Compiler
|
||||||
{
|
{
|
||||||
|
public class Generator
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public static class Options
|
public static class Options
|
||||||
{
|
{
|
||||||
[LinkName("#AllocStackCount")]
|
[LinkName("#AllocStackCount")]
|
||||||
|
|
|
@ -15,9 +15,10 @@ namespace IDE
|
||||||
public Action mOnThreadDone ~ delete _;
|
public Action mOnThreadDone ~ delete _;
|
||||||
[ThreadStatic]
|
[ThreadStatic]
|
||||||
public static bool mBpSetThreadName;
|
public static bool mBpSetThreadName;
|
||||||
|
public bool mAllowFastFinish;
|
||||||
WaitEvent mWaitEvent = new WaitEvent() ~ delete _;
|
WaitEvent mWaitEvent = new WaitEvent() ~ delete _;
|
||||||
|
|
||||||
public void DoBackground(ThreadStart threadStart, Action onThreadDone = null, int maxWait = 0)
|
public void DoBackground(ThreadStart threadStart, Action onThreadDone = null, int maxWait = 0, bool allowFastFinish = true)
|
||||||
{
|
{
|
||||||
Debug.Assert(Thread.CurrentThread == IDEApp.sApp.mMainThread);
|
Debug.Assert(Thread.CurrentThread == IDEApp.sApp.mMainThread);
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@ namespace IDE
|
||||||
|
|
||||||
BeefPerf.Event("DoBackground:starting", "");
|
BeefPerf.Event("DoBackground:starting", "");
|
||||||
|
|
||||||
|
mAllowFastFinish = allowFastFinish;
|
||||||
mOnThreadDone = onThreadDone;
|
mOnThreadDone = onThreadDone;
|
||||||
mThreadRunning = true;
|
mThreadRunning = true;
|
||||||
mWaitEvent.Reset();
|
mWaitEvent.Reset();
|
||||||
|
@ -47,6 +49,7 @@ namespace IDE
|
||||||
delete threadStart;
|
delete threadStart;
|
||||||
mThread = null;
|
mThread = null;
|
||||||
mThreadRunning = false;
|
mThreadRunning = false;
|
||||||
|
mAllowFastFinish = true;
|
||||||
BeefPerf.Event("DoBackground:threadEnd", "");
|
BeefPerf.Event("DoBackground:threadEnd", "");
|
||||||
|
|
||||||
mWaitEvent.Set();
|
mWaitEvent.Set();
|
||||||
|
@ -132,7 +135,7 @@ namespace IDE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void RequestFastFinish()
|
public virtual void RequestFastFinish(bool force = false)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -190,15 +193,20 @@ namespace IDE
|
||||||
return (mThreadWorker.mThreadRunning || mThreadWorkerHi.mThreadRunning);
|
return (mThreadWorker.mThreadRunning || mThreadWorkerHi.mThreadRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsPerformingBackgroundOperationHi()
|
||||||
|
{
|
||||||
|
return (mThreadWorkerHi.mThreadRunning);
|
||||||
|
}
|
||||||
|
|
||||||
public void DoBackground(ThreadStart threadStart, Action onThreadDone = null, int maxWait = 0)
|
public void DoBackground(ThreadStart threadStart, Action onThreadDone = null, int maxWait = 0)
|
||||||
{
|
{
|
||||||
CancelBackground();
|
CancelBackground();
|
||||||
mThreadWorker.DoBackground(threadStart, onThreadDone, maxWait);
|
mThreadWorker.DoBackground(threadStart, onThreadDone, maxWait);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void DoBackgroundHi(ThreadStart threadStart, Action onThreadDone = null)
|
public void DoBackgroundHi(ThreadStart threadStart, Action onThreadDone = null, bool allowFastFinish = true)
|
||||||
{
|
{
|
||||||
mThreadWorkerHi.DoBackground(threadStart, onThreadDone);
|
mThreadWorkerHi.DoBackground(threadStart, onThreadDone, 0, allowFastFinish);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CheckThreadDone()
|
public void CheckThreadDone()
|
||||||
|
|
|
@ -94,6 +94,15 @@ namespace IDE.Compiler
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern char8* BfCompiler_GetUsedOutputFileNames(void* bfCompiler, void* bfProject, bool flushQueuedHotFiles, out bool hadOutputChanges);
|
static extern char8* BfCompiler_GetUsedOutputFileNames(void* bfCompiler, void* bfProject, bool flushQueuedHotFiles, out bool hadOutputChanges);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern char8* BfCompiler_GetGeneratorTypeDefList(void* bfCompiler);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern char8* BfCompiler_GetGeneratorInitData(void* bfCompiler, char8* typeDefName, char8* args);
|
||||||
|
|
||||||
|
[CallingConvention(.Stdcall), CLink]
|
||||||
|
static extern char8* BfCompiler_GetGeneratorGenData(void* bfCompiler, char8* typeDefName, char8* args);
|
||||||
|
|
||||||
[CallingConvention(.Stdcall), CLink]
|
[CallingConvention(.Stdcall), CLink]
|
||||||
static extern char8* BfCompiler_GetTypeDefList(void* bfCompiler);
|
static extern char8* BfCompiler_GetTypeDefList(void* bfCompiler);
|
||||||
|
|
||||||
|
@ -234,13 +243,13 @@ namespace IDE.Compiler
|
||||||
public void GetAutocompleteInfo(String outAutocompleteInfo)
|
public void GetAutocompleteInfo(String outAutocompleteInfo)
|
||||||
{
|
{
|
||||||
char8* result = BfCompiler_GetAutocompleteInfo(mNativeBfCompiler);
|
char8* result = BfCompiler_GetAutocompleteInfo(mNativeBfCompiler);
|
||||||
scope String(result).MoveTo(outAutocompleteInfo);
|
outAutocompleteInfo.Append(StringView(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void GetSymbolReferences(BfPassInstance passInstance, BfResolvePassData resolvePassData, String outSymbolReferences)
|
public void GetSymbolReferences(BfPassInstance passInstance, BfResolvePassData resolvePassData, String outSymbolReferences)
|
||||||
{
|
{
|
||||||
char8* result = BfCompiler_GetSymbolReferences(mNativeBfCompiler, passInstance.mNativeBfPassInstance, resolvePassData.mNativeResolvePassData);
|
char8* result = BfCompiler_GetSymbolReferences(mNativeBfCompiler, passInstance.mNativeBfPassInstance, resolvePassData.mNativeResolvePassData);
|
||||||
scope String(result).MoveTo(outSymbolReferences);
|
outSymbolReferences.Append(StringView(result));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public void UpdateRenameSymbols(BfPassInstance passInstance, BfResolvePassData resolvePassData)
|
/*public void UpdateRenameSymbols(BfPassInstance passInstance, BfResolvePassData resolvePassData)
|
||||||
|
@ -674,17 +683,21 @@ namespace IDE.Compiler
|
||||||
|
|
||||||
public override void RequestCancelBackground()
|
public override void RequestCancelBackground()
|
||||||
{
|
{
|
||||||
if ([Friend]mThreadWorker.mThreadRunning)
|
if (mThreadWorker.mThreadRunning)
|
||||||
{
|
{
|
||||||
if ((mNativeBfCompiler != null) && (!gApp.mDeterministic))
|
if ((mNativeBfCompiler != null) && (!gApp.mDeterministic))
|
||||||
BfCompiler_Cancel(mNativeBfCompiler);
|
BfCompiler_Cancel(mNativeBfCompiler);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void RequestFastFinish()
|
public override void RequestFastFinish(bool force = false)
|
||||||
{
|
{
|
||||||
if ([Friend]mThreadWorker.mThreadRunning || [Friend]mThreadWorkerHi.mThreadRunning)
|
if (mThreadWorker.mThreadRunning || mThreadWorkerHi.mThreadRunning)
|
||||||
{
|
{
|
||||||
|
if ((!force) &&
|
||||||
|
((!mThreadWorker.mAllowFastFinish) || (!mThreadWorkerHi.mAllowFastFinish)))
|
||||||
|
return;
|
||||||
|
|
||||||
if ((mNativeBfCompiler != null) && (!gApp.mDeterministic))
|
if ((mNativeBfCompiler != null) && (!gApp.mDeterministic))
|
||||||
BfCompiler_RequestFastFinish(mNativeBfCompiler);
|
BfCompiler_RequestFastFinish(mNativeBfCompiler);
|
||||||
}
|
}
|
||||||
|
@ -710,6 +723,21 @@ namespace IDE.Compiler
|
||||||
return BfCompiler_GetCurConstEvalExecuteId(mNativeBfCompiler);
|
return BfCompiler_GetCurConstEvalExecuteId(mNativeBfCompiler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void GetGeneratorTypeDefList(String outStr)
|
||||||
|
{
|
||||||
|
outStr.Append(BfCompiler_GetGeneratorTypeDefList(mNativeBfCompiler));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetGeneratorInitData(String typeDefName, String args, String outStr)
|
||||||
|
{
|
||||||
|
outStr.Append(BfCompiler_GetGeneratorInitData(mNativeBfCompiler, typeDefName, args));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetGeneratorGenData(String typeDefName, String args, String outStr)
|
||||||
|
{
|
||||||
|
outStr.Append(BfCompiler_GetGeneratorGenData(mNativeBfCompiler, typeDefName, args));
|
||||||
|
}
|
||||||
|
|
||||||
public void GetTypeDefList(String outStr)
|
public void GetTypeDefList(String outStr)
|
||||||
{
|
{
|
||||||
outStr.Append(BfCompiler_GetTypeDefList(mNativeBfCompiler));
|
outStr.Append(BfCompiler_GetTypeDefList(mNativeBfCompiler));
|
||||||
|
|
|
@ -37,6 +37,7 @@ namespace IDE
|
||||||
public ProjectFolder mParentFolder;
|
public ProjectFolder mParentFolder;
|
||||||
public String mName = new String() ~ delete _;
|
public String mName = new String() ~ delete _;
|
||||||
public String mComment = new String() ~ delete _;
|
public String mComment = new String() ~ delete _;
|
||||||
|
public bool mDetached;
|
||||||
|
|
||||||
public virtual bool IncludeInMap
|
public virtual bool IncludeInMap
|
||||||
{
|
{
|
||||||
|
@ -105,6 +106,7 @@ namespace IDE
|
||||||
|
|
||||||
public virtual void Detach()
|
public virtual void Detach()
|
||||||
{
|
{
|
||||||
|
mDetached = true;
|
||||||
ReleaseRef();
|
ReleaseRef();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -353,7 +355,7 @@ namespace IDE
|
||||||
return .SimpleSource;
|
return .SimpleSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Dispose()
|
public void ClearEditData()
|
||||||
{
|
{
|
||||||
if (mEditData != null)
|
if (mEditData != null)
|
||||||
{
|
{
|
||||||
|
@ -363,6 +365,11 @@ namespace IDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Dispose()
|
||||||
|
{
|
||||||
|
ClearEditData();
|
||||||
|
}
|
||||||
|
|
||||||
public override void Detach()
|
public override void Detach()
|
||||||
{
|
{
|
||||||
Dispose();
|
Dispose();
|
||||||
|
@ -843,6 +850,13 @@ namespace IDE
|
||||||
|
|
||||||
childFileItem.OnRename(childFileItem.mPath, newChildPath);
|
childFileItem.OnRename(childFileItem.mPath, newChildPath);
|
||||||
|
|
||||||
|
String oldFullName = scope String();
|
||||||
|
mProject.GetProjectFullPath(childFileItem.mPath, oldFullName);
|
||||||
|
String newFullName = scope String();
|
||||||
|
mProject.GetProjectFullPath(newChildPath, newFullName);
|
||||||
|
|
||||||
|
IDEApp.sApp.FileRenamed(childFileItem, oldFullName, newFullName);
|
||||||
|
|
||||||
childFileItem.mPath.Set(newChildPath);
|
childFileItem.mPath.Set(newChildPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -598,10 +598,14 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var bfSystem = gApp.mBfResolveSystem;
|
||||||
|
|
||||||
String typeName = scope .();
|
String typeName = scope .();
|
||||||
GetName(item, typeName);
|
GetName(item, typeName);
|
||||||
String info = scope .();
|
String info = scope .();
|
||||||
|
bfSystem.Lock(0);
|
||||||
gApp.mBfResolveCompiler.GetTypeDefInfo(typeName, info);
|
gApp.mBfResolveCompiler.GetTypeDefInfo(typeName, info);
|
||||||
|
bfSystem.Unlock();
|
||||||
|
|
||||||
for (let str in info.Split('\n'))
|
for (let str in info.Split('\n'))
|
||||||
{
|
{
|
||||||
|
|
882
IDE/src/ui/GenerateDialog.bf
Normal file
882
IDE/src/ui/GenerateDialog.bf
Normal file
|
@ -0,0 +1,882 @@
|
||||||
|
using Beefy.theme.dark;
|
||||||
|
using Beefy.widgets;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using Beefy.gfx;
|
||||||
|
using Beefy.events;
|
||||||
|
using IDE.Compiler;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using Beefy.theme;
|
||||||
|
|
||||||
|
namespace IDE.ui
|
||||||
|
{
|
||||||
|
class GenerateListView : DarkListView
|
||||||
|
{
|
||||||
|
public GenerateDialog mNewClassDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenerateKindBar : DarkComboBox
|
||||||
|
{
|
||||||
|
public class Entry
|
||||||
|
{
|
||||||
|
public String mTypeName ~ delete _;
|
||||||
|
public String mName ~ delete _;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Dictionary<String, int32> sMRU = new Dictionary<String, int32>() ~ delete _;
|
||||||
|
public static int32 sCurrentMRUIndex = 1;
|
||||||
|
|
||||||
|
public GenerateDialog mNewClassDialog;
|
||||||
|
public List<Entry> mEntries = new List<Entry>() ~ DeleteContainerAndItems!(_);
|
||||||
|
public List<Entry> mShownEntries = new List<Entry>() ~ delete _;
|
||||||
|
public String mFilterString ~ delete _;
|
||||||
|
public String mCurLocation = new String() ~ delete _;
|
||||||
|
public bool mIgnoreChange = false;
|
||||||
|
|
||||||
|
public this(GenerateDialog dialog)
|
||||||
|
{
|
||||||
|
mNewClassDialog = dialog;
|
||||||
|
mLabelAlign = FontAlign.Left;
|
||||||
|
Label = "";
|
||||||
|
mLabelX = GS!(16);
|
||||||
|
mPopulateMenuAction.Add(new => PopulateNavigationBar);
|
||||||
|
MakeEditable();
|
||||||
|
mEditWidget.mOnContentChanged.Add(new => NavigationBarChanged);
|
||||||
|
mEditWidget.mOnGotFocus.Add(new (widget) => mEditWidget.mEditWidgetContent.SelectAll());
|
||||||
|
mEditWidget.mEditWidgetContent.mWantsUndo = false;
|
||||||
|
mEditWidget.mOnSubmit.Add(new => mNewClassDialog.[Friend]EditSubmitHandler);
|
||||||
|
mFocusDropdown = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static ~this()
|
||||||
|
{
|
||||||
|
for (var key in sMRU.Keys)
|
||||||
|
delete key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetLocation(String location)
|
||||||
|
{
|
||||||
|
if (mCurMenuWidget == null)
|
||||||
|
{
|
||||||
|
mIgnoreChange = true;
|
||||||
|
mEditWidget.SetText(location);
|
||||||
|
mEditWidget.mEditWidgetContent.SelectAll();
|
||||||
|
// SetText can attempt to scroll to the right to make the cursor position visible. Just scroll back to the start.
|
||||||
|
mEditWidget.HorzScrollTo(0);
|
||||||
|
//mNewClassDialog.SelectKind();
|
||||||
|
mIgnoreChange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void PopulateNavigationBar(Menu menu)
|
||||||
|
{
|
||||||
|
List<StringView> findStrs = null;
|
||||||
|
if (mFilterString != null)
|
||||||
|
findStrs = scope:: List<StringView>(mFilterString.Split(' '));
|
||||||
|
|
||||||
|
EntryLoop: for (int32 entryIdx = 0; entryIdx < mEntries.Count; entryIdx++)
|
||||||
|
{
|
||||||
|
var entry = mEntries[entryIdx];
|
||||||
|
if (findStrs != null)
|
||||||
|
{
|
||||||
|
for (let findStr in findStrs)
|
||||||
|
{
|
||||||
|
if (entry.mName.IndexOf(findStr, true) == -1)
|
||||||
|
continue EntryLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mShownEntries.Add(entry);
|
||||||
|
var menuItem = menu.AddItem(entry.mName);
|
||||||
|
menuItem.mOnMenuItemSelected.Add(new (evt) =>
|
||||||
|
{
|
||||||
|
mNewClassDialog.mPendingUIFocus = true;
|
||||||
|
ShowEntry(entryIdx, entry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowEntry(int32 entryIdx, Entry entry)
|
||||||
|
{
|
||||||
|
mEditWidget.SetText(entry.mName);
|
||||||
|
mEditWidget.mEditWidgetContent.SelectAll();
|
||||||
|
mCurMenuWidget?.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavigationBarChanged(EditEvent theEvent)
|
||||||
|
{
|
||||||
|
if (mIgnoreChange)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var editWidget = (EditWidget)theEvent.mSender;
|
||||||
|
var searchText = scope String();
|
||||||
|
editWidget.GetText(searchText);
|
||||||
|
searchText.Trim();
|
||||||
|
mFilterString = searchText;
|
||||||
|
ShowDropdown();
|
||||||
|
mFilterString = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mIgnoreShowDropdown;
|
||||||
|
|
||||||
|
public override MenuWidget ShowDropdown()
|
||||||
|
{
|
||||||
|
if (mIgnoreShowDropdown)
|
||||||
|
return null;
|
||||||
|
mIgnoreShowDropdown = true;
|
||||||
|
defer { mIgnoreShowDropdown = false; }
|
||||||
|
|
||||||
|
if (!mEditWidget.mHasFocus)
|
||||||
|
SetFocus();
|
||||||
|
|
||||||
|
if (mFilterString == null)
|
||||||
|
mEditWidget.Content.SelectAll();
|
||||||
|
|
||||||
|
mShownEntries.Clear();
|
||||||
|
base.ShowDropdown();
|
||||||
|
|
||||||
|
int32 bestItem = -1;
|
||||||
|
int32 bestPri = -1;
|
||||||
|
var menuWidget = (DarkMenuWidget)mCurMenuWidget;
|
||||||
|
|
||||||
|
for (int32 itemIdx = 0; itemIdx < menuWidget.mItemWidgets.Count; itemIdx++)
|
||||||
|
{
|
||||||
|
var menuItemWidget = (DarkMenuItem)menuWidget.mItemWidgets[itemIdx];
|
||||||
|
|
||||||
|
int32 pri;
|
||||||
|
sMRU.TryGetValue(menuItemWidget.mMenuItem.mLabel, out pri);
|
||||||
|
if (pri > bestPri)
|
||||||
|
{
|
||||||
|
bestItem = itemIdx;
|
||||||
|
bestPri = pri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestItem != -1)
|
||||||
|
{
|
||||||
|
mCurMenuWidget.mOnSelectionChanged.Add(new => SelectionChanged);
|
||||||
|
mCurMenuWidget.SetSelection(bestItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
return menuWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SelectionChanged(int selIdx)
|
||||||
|
{
|
||||||
|
if (mEditWidget.mEditWidgetContent.HasSelection())
|
||||||
|
{
|
||||||
|
bool prevIgnoreShowDropdown = mIgnoreShowDropdown;
|
||||||
|
mIgnoreShowDropdown = true;
|
||||||
|
mEditWidget.SetText("");
|
||||||
|
mIgnoreShowDropdown = prevIgnoreShowDropdown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void MenuClosed()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GenerateDialog : IDEDialog
|
||||||
|
{
|
||||||
|
public class UIEntry
|
||||||
|
{
|
||||||
|
public String mName ~ delete _;
|
||||||
|
public String mData ~ delete _;
|
||||||
|
public String mLabel ~ delete _;
|
||||||
|
public Widget mWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum ThreadState
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Executing,
|
||||||
|
Done
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool mPendingGenList;
|
||||||
|
public GenerateKindBar mKindBar;
|
||||||
|
public ThreadState mThreadState;
|
||||||
|
public int mThreadWaitCount;
|
||||||
|
public String mNamespace ~ delete _;
|
||||||
|
public String mProjectName ~ delete _;
|
||||||
|
public ProjectItem mProjectItem ~ _.ReleaseRef();
|
||||||
|
public String mFolderPath ~ delete _;
|
||||||
|
public List<UIEntry> mUIEntries = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
public GenerateKindBar.Entry mSelectedEntry;
|
||||||
|
public GenerateKindBar.Entry mPendingSelectedEntry;
|
||||||
|
public String mUIData ~ delete _;
|
||||||
|
public float mUIHeight = 0;
|
||||||
|
public OutputPanel mOutputPanel;
|
||||||
|
public bool mPendingUIFocus;
|
||||||
|
public bool mSubmitting;
|
||||||
|
public bool mSubmitQueued;
|
||||||
|
public bool mRegenerating;
|
||||||
|
|
||||||
|
public this(ProjectItem projectItem, bool allowHashMismatch = false)
|
||||||
|
{
|
||||||
|
var project = projectItem.mProject;
|
||||||
|
mProjectItem = projectItem;
|
||||||
|
mProjectItem.AddRef();
|
||||||
|
|
||||||
|
mNamespace = new .();
|
||||||
|
|
||||||
|
var projectFolder = projectItem as ProjectFolder;
|
||||||
|
var projectSource = projectItem as ProjectSource;
|
||||||
|
if (projectSource != null)
|
||||||
|
{
|
||||||
|
projectFolder = projectSource.mParentFolder;
|
||||||
|
mRegenerating = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
projectFolder.GetRelDir(mNamespace); mNamespace.Replace('/', '.'); mNamespace.Replace('\\', '.'); mNamespace.Replace(" ", "");
|
||||||
|
if (mNamespace.StartsWith("src."))
|
||||||
|
{
|
||||||
|
mNamespace.Remove(0, 4);
|
||||||
|
if (!project.mBeefGlobalOptions.mDefaultNamespace.IsWhiteSpace)
|
||||||
|
{
|
||||||
|
mNamespace.Insert(0, ".");
|
||||||
|
mNamespace.Insert(0, project.mBeefGlobalOptions.mDefaultNamespace);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (projectItem.mParentFolder == null)
|
||||||
|
{
|
||||||
|
mNamespace.Clear();
|
||||||
|
mNamespace.Append(project.mBeefGlobalOptions.mDefaultNamespace);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mNamespace.Clear();
|
||||||
|
|
||||||
|
mFolderPath = projectFolder.GetFullImportPath(.. new .());
|
||||||
|
mProjectName = new String(projectItem.mProject.mProjectName);
|
||||||
|
|
||||||
|
mWindowFlags = .ClientSized | .TopMost | .Caption | .Border | .SysMenu | .Resizable | .PopupPosition;
|
||||||
|
|
||||||
|
if (!mRegenerating)
|
||||||
|
{
|
||||||
|
AddOkCancelButtons(new (evt) =>
|
||||||
|
{
|
||||||
|
Submit();
|
||||||
|
evt.mCloseDialog = false;
|
||||||
|
}, null, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Title = "Generate File";
|
||||||
|
|
||||||
|
mKindBar = new GenerateKindBar(this);
|
||||||
|
AddWidget(mKindBar);
|
||||||
|
mKindBar.mEditWidget.mOnContentChanged.Add(new (theEvent) => { SelectKind(); });
|
||||||
|
|
||||||
|
if (mRegenerating)
|
||||||
|
{
|
||||||
|
mSubmitQueued = true;
|
||||||
|
mKindBar.SetVisible(false);
|
||||||
|
|
||||||
|
SourceViewPanel sourceViewPanel = gApp.ShowProjectItem(projectSource, false);
|
||||||
|
|
||||||
|
String filePath = projectSource.GetFullImportPath(.. scope .());
|
||||||
|
|
||||||
|
String text = scope .();
|
||||||
|
sourceViewPanel.mEditWidget.GetText(text);
|
||||||
|
|
||||||
|
StringView generatorName = default;
|
||||||
|
StringView hash = default;
|
||||||
|
|
||||||
|
int dataIdx = -1;
|
||||||
|
for (var line in text.Split('\n'))
|
||||||
|
{
|
||||||
|
if (!line.StartsWith("// "))
|
||||||
|
{
|
||||||
|
dataIdx = @line.MatchPos + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int eqPos = line.IndexOf('=');
|
||||||
|
if (eqPos == -1)
|
||||||
|
break;
|
||||||
|
StringView key = line.Substring(3, eqPos - 3);
|
||||||
|
StringView value = line.Substring(eqPos + 1);
|
||||||
|
if (key == "Generator")
|
||||||
|
generatorName = value;
|
||||||
|
else if (key == "GenHash")
|
||||||
|
hash = value;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UIEntry uiEntry = new .();
|
||||||
|
uiEntry.mName = new .(key);
|
||||||
|
uiEntry.mData = new .(value);
|
||||||
|
mUIEntries.Add(uiEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((generatorName == default) || (hash == default))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
gApp.Fail(scope $"File '{filePath}' was not generated by a generator that includes regeneration information");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((dataIdx != -1) && (!allowHashMismatch))
|
||||||
|
{
|
||||||
|
var origHash = MD5Hash.Parse(hash).GetValueOrDefault();
|
||||||
|
|
||||||
|
StringView dataStr = text.Substring(dataIdx);
|
||||||
|
var checkHash = MD5.Hash(.((.)dataStr.Ptr, dataStr.Length));
|
||||||
|
|
||||||
|
if (origHash != checkHash)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
Dialog dialog = ThemeFactory.mDefault.CreateDialog("Regenerate?", "This file has been modified since it was generated. Are you sure you want to regenerate?", DarkTheme.sDarkTheme.mIconWarning);
|
||||||
|
dialog.AddButton("Yes", new (evt) =>
|
||||||
|
{
|
||||||
|
gApp.mProjectPanel.Regenerate(true);
|
||||||
|
//dialog.Close();
|
||||||
|
});
|
||||||
|
dialog.AddButton("No", new (evt) =>
|
||||||
|
{
|
||||||
|
//dialog.Close();
|
||||||
|
});
|
||||||
|
dialog.PopupWindow(gApp.GetActiveWindow());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GenerateKindBar.Entry entry = new .();
|
||||||
|
entry.mName = new .(generatorName);
|
||||||
|
entry.mTypeName = new .(generatorName);
|
||||||
|
mKindBar.mEntries.Add(entry);
|
||||||
|
mPendingSelectedEntry = entry;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mPendingGenList = true;
|
||||||
|
|
||||||
|
mKindBar.mMouseVisible = false;
|
||||||
|
mTabWidgets.Add(mKindBar.mEditWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||||||
|
if (mThreadState == .Executing)
|
||||||
|
{
|
||||||
|
bfCompiler.WaitForBackground();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SelectKind()
|
||||||
|
{
|
||||||
|
GenerateKindBar.Entry foundEntry = null;
|
||||||
|
|
||||||
|
String text = mKindBar.mEditWidget.GetText(.. scope .());
|
||||||
|
for (var entry in mKindBar.mEntries)
|
||||||
|
if (entry.mName == text)
|
||||||
|
foundEntry = entry;
|
||||||
|
|
||||||
|
if (foundEntry == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mSelectedEntry == foundEntry)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mPendingSelectedEntry = foundEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ThreadProc()
|
||||||
|
{
|
||||||
|
var bfSystem = gApp.mBfResolveSystem;
|
||||||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||||||
|
|
||||||
|
String outStr = scope String();
|
||||||
|
|
||||||
|
bfSystem.Lock(0);
|
||||||
|
defer bfSystem.Unlock();
|
||||||
|
|
||||||
|
if (mSelectedEntry != null)
|
||||||
|
{
|
||||||
|
String args = scope .();
|
||||||
|
var project = gApp.mWorkspace.FindProject(mProjectName);
|
||||||
|
if (project == null)
|
||||||
|
return;
|
||||||
|
using (gApp.mMonitor.Enter())
|
||||||
|
{
|
||||||
|
if (mRegenerating)
|
||||||
|
args.Append("Regenerating\tTrue\n");
|
||||||
|
|
||||||
|
args.AppendF(
|
||||||
|
$"""
|
||||||
|
ProjectName\t{mProjectName}
|
||||||
|
ProjectDir\t{project.mProjectPath}
|
||||||
|
FolderDir\t{mFolderPath}
|
||||||
|
Namespace\t{mNamespace}
|
||||||
|
DefaultNamespace\t{project.mBeefGlobalOptions.mDefaultNamespace}
|
||||||
|
WorkspaceName\t{gApp.mWorkspace.mName}
|
||||||
|
WorkspaceDir\t{gApp.mWorkspace.mDir}
|
||||||
|
DateTime\t{DateTime.Now}
|
||||||
|
|
||||||
|
""");
|
||||||
|
|
||||||
|
if (mSubmitting)
|
||||||
|
{
|
||||||
|
args.AppendF($"Generator\t{mSelectedEntry.mTypeName}\n");
|
||||||
|
for (var uiEntry in mUIEntries)
|
||||||
|
{
|
||||||
|
String data = scope .();
|
||||||
|
if (uiEntry.mData != null)
|
||||||
|
{
|
||||||
|
data.Append(uiEntry.mData);
|
||||||
|
}
|
||||||
|
else if (var editWidget = uiEntry.mWidget as EditWidget)
|
||||||
|
{
|
||||||
|
editWidget.GetText(data);
|
||||||
|
}
|
||||||
|
else if (var comboBox = uiEntry.mWidget as DarkComboBox)
|
||||||
|
{
|
||||||
|
comboBox.GetLabel(data);
|
||||||
|
}
|
||||||
|
else if (var checkBox = uiEntry.mWidget as CheckBox)
|
||||||
|
{
|
||||||
|
checkBox.Checked.ToString(data);
|
||||||
|
}
|
||||||
|
data.Replace('\n', '\r');
|
||||||
|
args.AppendF($"{uiEntry.mName}\t{data}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mUIData = new String();
|
||||||
|
if (mSubmitting)
|
||||||
|
bfCompiler.GetGeneratorGenData(mSelectedEntry.mTypeName, args, mUIData);
|
||||||
|
else
|
||||||
|
bfCompiler.GetGeneratorInitData(mSelectedEntry.mTypeName, args, mUIData);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfCompiler.GetGeneratorTypeDefList(outStr);
|
||||||
|
|
||||||
|
for (var line in outStr.Split('\n', .RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
if (line.StartsWith("!error"))
|
||||||
|
{
|
||||||
|
ShowError(line.Substring(7));
|
||||||
|
|
||||||
|
RehupMinSize();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var entry = new GenerateKindBar.Entry();
|
||||||
|
var partItr = line.Split('\t');
|
||||||
|
entry.mTypeName = new String(partItr.GetNext().Value);
|
||||||
|
if (partItr.GetNext() case .Ok(let val))
|
||||||
|
entry.mName = new String(val);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
entry.mName = new String(entry.mTypeName);
|
||||||
|
int termPos = entry.mName.LastIndexOf('.');
|
||||||
|
if (termPos != -1)
|
||||||
|
entry.mName.Remove(0, termPos + 1);
|
||||||
|
termPos = entry.mName.LastIndexOf('+');
|
||||||
|
if (termPos != -1)
|
||||||
|
entry.mName.Remove(0, termPos + 1);
|
||||||
|
}
|
||||||
|
mKindBar.mEntries.Add(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CalcSize()
|
||||||
|
{
|
||||||
|
mWidth = GS!(320);
|
||||||
|
mHeight = GS!(96);
|
||||||
|
mMinWidth = mWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void RehupMinSize()
|
||||||
|
{
|
||||||
|
mWidgetWindow.SetMinimumSize(GS!(240), (.)mUIHeight + GS!(24), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShowError(StringView error)
|
||||||
|
{
|
||||||
|
if (mOutputPanel == null)
|
||||||
|
{
|
||||||
|
IDEApp.Beep(.Error);
|
||||||
|
mOutputPanel = new OutputPanel();
|
||||||
|
AddWidget(mOutputPanel);
|
||||||
|
ResizeComponents();
|
||||||
|
}
|
||||||
|
String str = scope .();
|
||||||
|
str.Append(error);
|
||||||
|
str.Replace('\r', '\n');
|
||||||
|
str.Append("\n");
|
||||||
|
mOutputPanel.WriteSmart(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Update()
|
||||||
|
{
|
||||||
|
base.Update();
|
||||||
|
|
||||||
|
if ((!mKindBar.mEditWidget.mHasFocus) && (mWidgetWindow.mHasFocus))
|
||||||
|
{
|
||||||
|
var sel = mPendingSelectedEntry ?? mSelectedEntry;
|
||||||
|
String editText = mKindBar.mEditWidget.GetText(.. scope .());
|
||||||
|
if ((sel != null) && (editText != sel.mName))
|
||||||
|
{
|
||||||
|
mKindBar.mIgnoreChange = true;
|
||||||
|
mKindBar.mEditWidget.SetText(sel.mName);
|
||||||
|
mKindBar.mIgnoreChange = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mThreadState == .Done)
|
||||||
|
{
|
||||||
|
if (mSelectedEntry != null)
|
||||||
|
{
|
||||||
|
List<UIEntry> oldEntries = scope .();
|
||||||
|
Dictionary<String, UIEntry> entryMap = scope .();
|
||||||
|
if (!mSubmitting)
|
||||||
|
{
|
||||||
|
for (var uiEntry in mUIEntries)
|
||||||
|
{
|
||||||
|
if (!entryMap.TryAdd(uiEntry.mName, uiEntry))
|
||||||
|
oldEntries.Add(uiEntry);
|
||||||
|
}
|
||||||
|
mUIEntries.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mUIData != null)
|
||||||
|
{
|
||||||
|
if (mOutputPanel != null)
|
||||||
|
{
|
||||||
|
mOutputPanel.RemoveSelf();
|
||||||
|
DeleteAndNullify!(mOutputPanel);
|
||||||
|
}
|
||||||
|
|
||||||
|
String fileName = default;
|
||||||
|
StringView genText = default;
|
||||||
|
bool hadError = false;
|
||||||
|
|
||||||
|
if (mUIData.IsEmpty)
|
||||||
|
{
|
||||||
|
gApp.Fail("Generator failed to return results");
|
||||||
|
}
|
||||||
|
|
||||||
|
LinesLoop: for (var line in mUIData.Split('\n', .RemoveEmptyEntries))
|
||||||
|
{
|
||||||
|
var partItr = line.Split('\t');
|
||||||
|
var kind = partItr.GetNext().Value;
|
||||||
|
|
||||||
|
switch (kind)
|
||||||
|
{
|
||||||
|
case "!error":
|
||||||
|
ShowError(line.Substring(7));
|
||||||
|
case "addEdit":
|
||||||
|
if (mSubmitting)
|
||||||
|
break;
|
||||||
|
UIEntry uiEntry = new UIEntry();
|
||||||
|
uiEntry.mName = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||||||
|
uiEntry.mLabel = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||||||
|
var defaultValue = partItr.GetNext().Value.UnQuoteString(.. scope .());
|
||||||
|
DarkEditWidget editWidget = new DarkEditWidget();
|
||||||
|
uiEntry.mWidget = editWidget;
|
||||||
|
editWidget.SetText(defaultValue);
|
||||||
|
editWidget.mEditWidgetContent.SelectAll();
|
||||||
|
editWidget.mOnSubmit.Add(new => EditSubmitHandler);
|
||||||
|
AddWidget(editWidget);
|
||||||
|
mUIEntries.Add(uiEntry);
|
||||||
|
mTabWidgets.Add(editWidget);
|
||||||
|
case "addCombo":
|
||||||
|
if (mSubmitting)
|
||||||
|
break;
|
||||||
|
UIEntry uiEntry = new UIEntry();
|
||||||
|
uiEntry.mName = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||||||
|
uiEntry.mLabel = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||||||
|
var defaultValue = partItr.GetNext().Value.UnQuoteString(.. scope .());
|
||||||
|
List<String> choices = new List<String>();
|
||||||
|
DarkComboBox comboBox = new DarkComboBox();
|
||||||
|
while (partItr.GetNext() case .Ok(let val))
|
||||||
|
{
|
||||||
|
choices.Add(val.UnQuoteString(.. new .()));
|
||||||
|
}
|
||||||
|
comboBox.mOnDeleted.Add(new (widget) => { DeleteContainerAndItems!(choices); });
|
||||||
|
comboBox.mPopulateMenuAction.Add(new (menu) =>
|
||||||
|
{
|
||||||
|
for (var choice in choices)
|
||||||
|
{
|
||||||
|
var item = menu.AddItem(choice);
|
||||||
|
item.mOnMenuItemSelected.Add(new (menu) =>
|
||||||
|
{
|
||||||
|
comboBox.Label = menu.mLabel;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
uiEntry.mWidget = comboBox;
|
||||||
|
comboBox.Label = defaultValue;
|
||||||
|
AddWidget(comboBox);
|
||||||
|
mUIEntries.Add(uiEntry);
|
||||||
|
mTabWidgets.Add(comboBox);
|
||||||
|
case "addCheckbox":
|
||||||
|
if (mSubmitting)
|
||||||
|
break;
|
||||||
|
UIEntry uiEntry = new UIEntry();
|
||||||
|
uiEntry.mName = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||||||
|
uiEntry.mLabel = partItr.GetNext().Value.UnQuoteString(.. new .());
|
||||||
|
var defaultValue = partItr.GetNext().Value;
|
||||||
|
DarkCheckBox checkbox = new DarkCheckBox();
|
||||||
|
uiEntry.mWidget = checkbox;
|
||||||
|
checkbox.Label = uiEntry.mLabel;
|
||||||
|
checkbox.Checked = defaultValue == "True";
|
||||||
|
AddWidget(checkbox);
|
||||||
|
mUIEntries.Add(uiEntry);
|
||||||
|
mTabWidgets.Add(checkbox);
|
||||||
|
case "error":
|
||||||
|
hadError = true;
|
||||||
|
gApp.Fail(line.Substring(6).UnQuoteString(.. scope .()));
|
||||||
|
case "fileName":
|
||||||
|
fileName = line.Substring(9).UnQuoteString(.. scope:: .());
|
||||||
|
case "options":
|
||||||
|
case "data":
|
||||||
|
genText = .(mUIData, @line.MatchPos + 1);
|
||||||
|
break LinesLoop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResizeComponents();
|
||||||
|
RehupMinSize();
|
||||||
|
|
||||||
|
if (fileName?.EndsWith(".bf", .OrdinalIgnoreCase) == true)
|
||||||
|
fileName.RemoveFromEnd(3);
|
||||||
|
|
||||||
|
if ((fileName != null) && (!mRegenerating))
|
||||||
|
{
|
||||||
|
for (char8 c in fileName.RawChars)
|
||||||
|
{
|
||||||
|
if (!c.IsLetterOrDigit && c != '_')
|
||||||
|
{
|
||||||
|
gApp.Fail(scope $"Invalid generated file name: {fileName}");
|
||||||
|
hadError = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fileName.IsEmpty)
|
||||||
|
{
|
||||||
|
gApp.Fail("Geneator failed to specify file name");
|
||||||
|
hadError = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!hadError) && (genText != default) && (fileName != null))
|
||||||
|
{
|
||||||
|
if (!mProjectItem.mDetached)
|
||||||
|
{
|
||||||
|
if (mRegenerating)
|
||||||
|
{
|
||||||
|
gApp.mProjectPanel.Regenerate(mProjectItem as ProjectSource, genText);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gApp.mProjectPanel.Generate(mProjectItem as ProjectFolder, fileName, genText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hadError) && (mRegenerating) && (mOutputPanel == null))
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mPendingUIFocus)
|
||||||
|
{
|
||||||
|
mPendingUIFocus = false;
|
||||||
|
if (!mUIEntries.IsEmpty)
|
||||||
|
mUIEntries[0].mWidget.SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
DeleteAndNullify!(mUIData);
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
if (mSubmitting)
|
||||||
|
{
|
||||||
|
if (!mClosed)
|
||||||
|
{
|
||||||
|
mSubmitting = false;
|
||||||
|
mSubmitQueued = false;
|
||||||
|
mDefaultButton?.mDisabled = false;
|
||||||
|
mEscButton?.mDisabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var uiEntry in entryMap.Values)
|
||||||
|
oldEntries.Add(uiEntry);
|
||||||
|
|
||||||
|
for (var uiEntry in oldEntries)
|
||||||
|
{
|
||||||
|
mTabWidgets.Remove(uiEntry.mWidget);
|
||||||
|
uiEntry.mWidget.RemoveSelf();
|
||||||
|
DeleteAndNullify!(uiEntry.mWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearAndDeleteItems(oldEntries);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mKindBar.mMouseVisible = true;
|
||||||
|
mKindBar.SetFocus();
|
||||||
|
mKindBar.SetLocation("New Class");
|
||||||
|
}
|
||||||
|
mThreadState = .None;
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isWorking = false;
|
||||||
|
if (mThreadState == .None)
|
||||||
|
{
|
||||||
|
if ((mPendingGenList) || (mPendingSelectedEntry != null))
|
||||||
|
{
|
||||||
|
isWorking = true;
|
||||||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||||||
|
if (!bfCompiler.IsPerformingBackgroundOperation())
|
||||||
|
{
|
||||||
|
bfCompiler.CheckThreadDone();
|
||||||
|
|
||||||
|
mPendingGenList = false;
|
||||||
|
if (mPendingSelectedEntry != null)
|
||||||
|
{
|
||||||
|
if (mSubmitQueued)
|
||||||
|
mSubmitting = true;
|
||||||
|
mSelectedEntry = mPendingSelectedEntry;
|
||||||
|
mPendingSelectedEntry = null;
|
||||||
|
}
|
||||||
|
mThreadState = .Executing;
|
||||||
|
bfCompiler.DoBackgroundHi(new => ThreadProc, new () =>
|
||||||
|
{
|
||||||
|
mThreadState = .Done;
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gApp.mBfResolveCompiler.CheckThreadDone();
|
||||||
|
|
||||||
|
if ((mThreadState == .Executing) || (isWorking))
|
||||||
|
{
|
||||||
|
mThreadWaitCount++;
|
||||||
|
if (mUpdateCnt % 8 == 0)
|
||||||
|
MarkDirty();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mThreadWaitCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Resize(float x, float y, float width, float height)
|
||||||
|
{
|
||||||
|
base.Resize(x, y, width, height);
|
||||||
|
ResizeComponents();
|
||||||
|
//mClassViewPanel.Resize(0, 0, width, height - GS!(34));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
||||||
|
{
|
||||||
|
base.PopupWindow(parentWindow, offsetX, offsetY);
|
||||||
|
//mKindBar.SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics g)
|
||||||
|
{
|
||||||
|
base.Draw(g);
|
||||||
|
|
||||||
|
void DrawLabel(Widget widget, StringView label)
|
||||||
|
{
|
||||||
|
if (widget == null)
|
||||||
|
return;
|
||||||
|
if (widget is CheckBox)
|
||||||
|
return;
|
||||||
|
g.DrawString(label, widget.mX + GS!(6), widget.mY - GS!(20));
|
||||||
|
}
|
||||||
|
|
||||||
|
DrawLabel(mKindBar, mRegenerating ? "Regenerating ..." : "Generator");
|
||||||
|
for (var uiEntry in mUIEntries)
|
||||||
|
DrawLabel(uiEntry.mWidget, uiEntry.mLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawAll(Graphics g)
|
||||||
|
{
|
||||||
|
base.DrawAll(g);
|
||||||
|
|
||||||
|
if (mThreadWaitCount > 10)
|
||||||
|
{
|
||||||
|
using (g.PushColor(0x60505050))
|
||||||
|
g.FillRect(0, 0, mWidth, mHeight - ((mDefaultButton != null) ? GS!(40) : GS!(0)));
|
||||||
|
IDEUtils.DrawWait(g, mWidth/2, mHeight/2, mUpdateCnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ResizeComponents()
|
||||||
|
{
|
||||||
|
base.ResizeComponents();
|
||||||
|
|
||||||
|
mUIHeight = GS!(32);
|
||||||
|
|
||||||
|
float insetSize = GS!(12);
|
||||||
|
|
||||||
|
mKindBar.Resize(insetSize, mUIHeight, mWidth - insetSize - insetSize, GS!(22));
|
||||||
|
mUIHeight += GS!(52);
|
||||||
|
|
||||||
|
for (var uiEntry in mUIEntries)
|
||||||
|
{
|
||||||
|
if (uiEntry.mWidget == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
float height = GS!(22);
|
||||||
|
if (uiEntry.mWidget is ComboBox)
|
||||||
|
height = GS!(26);
|
||||||
|
|
||||||
|
if (uiEntry.mWidget is CheckBox)
|
||||||
|
{
|
||||||
|
mUIHeight -= GS!(20);
|
||||||
|
height = GS!(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
uiEntry.mWidget.Resize(insetSize, mUIHeight, mWidth - insetSize - insetSize, height);
|
||||||
|
mUIHeight += height + GS!(28);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mOutputPanel != null)
|
||||||
|
{
|
||||||
|
float startY = mKindBar.mVisible ? GS!(60) : GS!(36);
|
||||||
|
mOutputPanel.Resize(insetSize, startY, mWidth - insetSize - insetSize, Math.Max(mHeight - startY - ((mDefaultButton != null) ? GS!(44) : GS!(12)), GS!(32)));
|
||||||
|
mUIHeight = Math.Max(mUIHeight, GS!(160));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Close()
|
||||||
|
{
|
||||||
|
if (mThreadState == .Executing)
|
||||||
|
{
|
||||||
|
var bfCompiler = gApp.mBfResolveCompiler;
|
||||||
|
bfCompiler.RequestFastFinish(true);
|
||||||
|
bfCompiler.WaitForBackground();
|
||||||
|
}
|
||||||
|
base.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Submit()
|
||||||
|
{
|
||||||
|
mDefaultButton.mDisabled = true;
|
||||||
|
mEscButton.mDisabled = true;
|
||||||
|
|
||||||
|
if (mSubmitQueued)
|
||||||
|
return;
|
||||||
|
mSubmitQueued = true;
|
||||||
|
mPendingSelectedEntry = mPendingSelectedEntry ?? mSelectedEntry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -327,7 +327,7 @@ namespace IDE.ui
|
||||||
int lineIdx = (curLine + lineOfs) % lineCount;
|
int lineIdx = (curLine + lineOfs) % lineCount;
|
||||||
|
|
||||||
if (content.GotoRefrenceAtLine(lineIdx))
|
if (content.GotoRefrenceAtLine(lineIdx))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -792,16 +792,96 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void NewClass(ProjectFolder folder)
|
public void GenerateCode(ProjectFolder folder)
|
||||||
{
|
{
|
||||||
DarkDialog dialog = (DarkDialog)ThemeFactory.mDefault.CreateDialog("New Class", "Class Name");
|
/*DarkDialog dialog = (DarkDialog)ThemeFactory.mDefault.CreateDialog("New Class", "Class Name");
|
||||||
dialog.mMinWidth = GS!(300);
|
dialog.mMinWidth = GS!(300);
|
||||||
dialog.mDefaultButton = dialog.AddButton("OK", new (evt) => DoNewClass(folder, evt));
|
dialog.mDefaultButton = dialog.AddButton("OK", new (evt) => DoNewClass(folder, evt));
|
||||||
dialog.mEscButton = dialog.AddButton("Cancel");
|
dialog.mEscButton = dialog.AddButton("Cancel");
|
||||||
dialog.AddEdit("Unnamed");
|
dialog.AddEdit("Unnamed");
|
||||||
dialog.PopupWindow(gApp.GetActiveWindow());
|
dialog.PopupWindow(gApp.GetActiveWindow());*/
|
||||||
|
|
||||||
|
var dialog = new GenerateDialog(folder);
|
||||||
|
dialog.PopupWindow(gApp.GetActiveWindow());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Regenerate(bool allowHashMismatch)
|
||||||
|
{
|
||||||
|
mListView.GetRoot().WithSelectedItems(scope (selectedItem) =>
|
||||||
|
{
|
||||||
|
if (mListViewToProjectMap.GetValue(selectedItem) case .Ok(var sourceProjectItem))
|
||||||
|
{
|
||||||
|
var dialog = new GenerateDialog(sourceProjectItem, allowHashMismatch);
|
||||||
|
dialog.PopupWindow(gApp.GetActiveWindow());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Regenerate(ProjectSource projectSource, StringView fileText)
|
||||||
|
{
|
||||||
|
var sourceViewPanel = gApp.ShowProjectItem(projectSource, false);
|
||||||
|
sourceViewPanel.mEditWidget.SetText(scope .(fileText));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Generate(ProjectFolder folder, StringView fileName, StringView fileText)
|
||||||
|
{
|
||||||
|
let project = folder.mProject;
|
||||||
|
if (project.mNeedsCreate)
|
||||||
|
project.FinishCreate();
|
||||||
|
String relFileName = scope .(fileName);
|
||||||
|
if (!relFileName.Contains('.'))
|
||||||
|
relFileName.Append(".bf");
|
||||||
|
|
||||||
|
String fullFilePath = scope String();
|
||||||
|
String relPath = scope String();
|
||||||
|
folder.GetRelDir(relPath);
|
||||||
|
if (relPath.Length > 0)
|
||||||
|
relPath.Append("/");
|
||||||
|
relPath.Append(relFileName);
|
||||||
|
folder.mProject.GetProjectFullPath(relPath, fullFilePath);
|
||||||
|
String dirName = scope String();
|
||||||
|
Path.GetDirectoryPath(fullFilePath, dirName);
|
||||||
|
Directory.CreateDirectory(dirName).IgnoreError();
|
||||||
|
|
||||||
|
if (File.Exists(fullFilePath))
|
||||||
|
{
|
||||||
|
var error = scope String();
|
||||||
|
error.AppendF("File '{0}' already exists", fullFilePath);
|
||||||
|
IDEApp.sApp.Fail(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (File.WriteAllText(fullFilePath, fileText) case .Err)
|
||||||
|
{
|
||||||
|
var error = scope String();
|
||||||
|
error.AppendF("Failed to create file '{0}'", fullFilePath);
|
||||||
|
gApp.Fail(error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectSource projectSource = new ProjectSource();
|
||||||
|
projectSource.mIncludeKind = (folder.mIncludeKind == .Auto) ? .Auto : .Manual;
|
||||||
|
projectSource.mName.Set(relFileName);
|
||||||
|
projectSource.mPath = new String();
|
||||||
|
folder.mProject.GetProjectRelPath(fullFilePath, projectSource.mPath);
|
||||||
|
projectSource.mProject = folder.mProject;
|
||||||
|
projectSource.mParentFolder = folder;
|
||||||
|
folder.AddChild(projectSource);
|
||||||
|
let projectItem = AddProjectItem(projectSource);
|
||||||
|
if (projectItem != null)
|
||||||
|
{
|
||||||
|
mListView.GetRoot().SelectItemExclusively(projectItem);
|
||||||
|
mListView.EnsureItemVisible(projectItem, false);
|
||||||
|
}
|
||||||
|
Sort();
|
||||||
|
if (folder.mIncludeKind != .Auto)
|
||||||
|
folder.mProject.SetChanged();
|
||||||
|
|
||||||
|
gApp.RecordHistoryLocation(true);
|
||||||
|
gApp.ShowProjectItem(projectSource);
|
||||||
|
gApp.RecordHistoryLocation(true);
|
||||||
|
}
|
||||||
|
|
||||||
void DoNewClass(ProjectFolder folder, DialogEvent evt)
|
void DoNewClass(ProjectFolder folder, DialogEvent evt)
|
||||||
{
|
{
|
||||||
Dialog dlg = (Dialog)evt.mSender;
|
Dialog dlg = (Dialog)evt.mSender;
|
||||||
|
@ -1470,7 +1550,10 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
|
|
||||||
if (doReleaseRef)
|
if (doReleaseRef)
|
||||||
|
{
|
||||||
|
projectItem.mDetached = true;
|
||||||
projectItem.ReleaseRef();
|
projectItem.ReleaseRef();
|
||||||
|
}
|
||||||
//TODO: Defer this, projectItem is needed for a backgrounded QueueProjectSourceRemoved
|
//TODO: Defer this, projectItem is needed for a backgrounded QueueProjectSourceRemoved
|
||||||
//delete projectItem;
|
//delete projectItem;
|
||||||
}
|
}
|
||||||
|
@ -2373,7 +2456,15 @@ namespace IDE.ui
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (let projectFolder = projectItem as ProjectFolder)
|
if (projectItem is ProjectSource)
|
||||||
|
{
|
||||||
|
item = menu.AddItem("Regenerate");
|
||||||
|
item.mOnMenuItemSelected.Add(new (item) =>
|
||||||
|
{
|
||||||
|
Regenerate(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (let projectFolder = projectItem as ProjectFolder)
|
||||||
{
|
{
|
||||||
//if (projectFolder.mIncludeKind == .Manual)
|
//if (projectFolder.mIncludeKind == .Manual)
|
||||||
{
|
{
|
||||||
|
@ -2471,17 +2562,17 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
item = menu.AddItem("New Class...");
|
item = menu.AddItem("Generate File...");
|
||||||
item.mOnMenuItemSelected.Add(new (item) =>
|
item.mOnMenuItemSelected.Add(new (item) =>
|
||||||
{
|
{
|
||||||
var projectFolder = GetSelectedProjectFolder();
|
var projectFolder = GetSelectedProjectFolder();
|
||||||
if (projectFolder != null)
|
if (projectFolder != null)
|
||||||
{
|
{
|
||||||
if (CheckProjectModify(projectFolder.mProject))
|
if (CheckProjectModify(projectFolder.mProject))
|
||||||
NewClass(projectFolder);
|
GenerateCode(projectFolder);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
item = menu.AddItem("Import File...");
|
item = menu.AddItem("Import File...");
|
||||||
item.mOnMenuItemSelected.Add(new (item) => { mImportFileDeferred = true; /* ImportFile();*/ });
|
item.mOnMenuItemSelected.Add(new (item) => { mImportFileDeferred = true; /* ImportFile();*/ });
|
||||||
|
|
||||||
|
|
|
@ -546,6 +546,11 @@ namespace IDE.ui
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
{
|
{
|
||||||
|
if (mProjectSource?.mEditData?.HasTextChanged() == true)
|
||||||
|
{
|
||||||
|
mProjectSource.ClearEditData();
|
||||||
|
}
|
||||||
|
|
||||||
if (mInPostRemoveUpdatePanels)
|
if (mInPostRemoveUpdatePanels)
|
||||||
{
|
{
|
||||||
//Debug.WriteLine("Removing sourceViewPanel from mPostRemoveUpdatePanel {0} in ~this ", this);
|
//Debug.WriteLine("Removing sourceViewPanel from mPostRemoveUpdatePanel {0} in ~this ", this);
|
||||||
|
|
|
@ -1295,7 +1295,7 @@ namespace IDE.ui
|
||||||
addrsCount = mWatchSeriesInfo.mAddrs.Length / entryAddrSize;
|
addrsCount = mWatchSeriesInfo.mAddrs.Length / entryAddrSize;
|
||||||
|
|
||||||
int totalCount = mWatchSeriesInfo.mCount;
|
int totalCount = mWatchSeriesInfo.mCount;
|
||||||
if (totalCount == -1)
|
if ((totalCount == -1) && (mWatchSeriesInfo.mContinuationData != null))
|
||||||
{
|
{
|
||||||
//int wantNewCount = Math.Min(idx + 32, mWatchSeriesInfo.mCount) - addrsCount;
|
//int wantNewCount = Math.Min(idx + 32, mWatchSeriesInfo.mCount) - addrsCount;
|
||||||
bool continuationDone = false;
|
bool continuationDone = false;
|
||||||
|
|
|
@ -555,6 +555,7 @@ void BeCOFFObject::DbgTEndTag()
|
||||||
BF_ASSERT(mTTagStartPos != -1);
|
BF_ASSERT(mTTagStartPos != -1);
|
||||||
DbgTAlign();
|
DbgTAlign();
|
||||||
int tagSize = mDebugTSect.mData.GetPos() - mTTagStartPos;
|
int tagSize = mDebugTSect.mData.GetPos() - mTTagStartPos;
|
||||||
|
BF_ASSERT(tagSize <= 0xFFFF);
|
||||||
*((int16*)&mDebugTSect.mData.mData[mTTagStartPos]) = (int16)(tagSize - 2);
|
*((int16*)&mDebugTSect.mData.mData[mTTagStartPos]) = (int16)(tagSize - 2);
|
||||||
mTTagStartPos = -1;
|
mTTagStartPos = -1;
|
||||||
}
|
}
|
||||||
|
@ -597,11 +598,7 @@ int BeCOFFObject::DbgGetTypeId(BeDbgType* dbgType, bool doDefine)
|
||||||
DbgGetTypeId(structType->mDerivedFrom);
|
DbgGetTypeId(structType->mDerivedFrom);
|
||||||
for (auto member : structType->mMembers)
|
for (auto member : structType->mMembers)
|
||||||
{
|
{
|
||||||
auto type = member->mType;
|
auto type = member->mType;
|
||||||
//TODO:
|
|
||||||
//if (member->mName == "VersionName")
|
|
||||||
//continue;
|
|
||||||
|
|
||||||
DbgGetTypeId(type);
|
DbgGetTypeId(type);
|
||||||
}
|
}
|
||||||
for (auto func : structType->mMethods)
|
for (auto func : structType->mMethods)
|
||||||
|
@ -627,7 +624,7 @@ int BeCOFFObject::DbgGetTypeId(BeDbgType* dbgType, bool doDefine)
|
||||||
auto _CheckFieldOverflow = [&]()
|
auto _CheckFieldOverflow = [&]()
|
||||||
{
|
{
|
||||||
int tagSize = mDebugTSect.mData.GetPos() - mTTagStartPos;
|
int tagSize = mDebugTSect.mData.GetPos() - mTTagStartPos;
|
||||||
if (tagSize >= 2000)
|
if (tagSize >= 0xE000)
|
||||||
{
|
{
|
||||||
int extFieldListTag = mCurTagId++;
|
int extFieldListTag = mCurTagId++;
|
||||||
|
|
||||||
|
@ -1013,8 +1010,7 @@ void BeCOFFObject::DbgGenerateTypeInfo()
|
||||||
void BeCOFFObject::DbgStartSection(int sectionNum)
|
void BeCOFFObject::DbgStartSection(int sectionNum)
|
||||||
{
|
{
|
||||||
auto& outS = mDebugSSect.mData;
|
auto& outS = mDebugSSect.mData;
|
||||||
BF_ASSERT(mSectionStartPos == -1);
|
BF_ASSERT(mSectionStartPos == -1);
|
||||||
|
|
||||||
outS.Write((int32)sectionNum);
|
outS.Write((int32)sectionNum);
|
||||||
outS.Write(0); // Temporary - size
|
outS.Write(0); // Temporary - size
|
||||||
mSectionStartPos = outS.GetPos();
|
mSectionStartPos = outS.GetPos();
|
||||||
|
@ -1023,7 +1019,7 @@ void BeCOFFObject::DbgStartSection(int sectionNum)
|
||||||
void BeCOFFObject::DbgEndSection()
|
void BeCOFFObject::DbgEndSection()
|
||||||
{
|
{
|
||||||
auto& outS = mDebugSSect.mData;
|
auto& outS = mDebugSSect.mData;
|
||||||
int totalLen = outS.GetPos() - mSectionStartPos;
|
int totalLen = outS.GetPos() - mSectionStartPos;
|
||||||
*((int32*)&outS.mData[mSectionStartPos - 4]) = totalLen;
|
*((int32*)&outS.mData[mSectionStartPos - 4]) = totalLen;
|
||||||
mSectionStartPos = -1;
|
mSectionStartPos = -1;
|
||||||
while ((outS.GetPos() & 3) != 0)
|
while ((outS.GetPos() & 3) != 0)
|
||||||
|
@ -1132,7 +1128,7 @@ void BeCOFFObject::DbgSEndTag()
|
||||||
{
|
{
|
||||||
BF_ASSERT(mSTagStartPos != -1);
|
BF_ASSERT(mSTagStartPos != -1);
|
||||||
int tagSize = mDebugSSect.mData.GetPos() - mSTagStartPos;
|
int tagSize = mDebugSSect.mData.GetPos() - mSTagStartPos;
|
||||||
|
BF_ASSERT(tagSize <= 0xFFFF);
|
||||||
*((uint16*)&mDebugSSect.mData.mData[mSTagStartPos]) = (uint16)(tagSize - 2);
|
*((uint16*)&mDebugSSect.mData.mData[mSTagStartPos]) = (uint16)(tagSize - 2);
|
||||||
mSTagStartPos = -1;
|
mSTagStartPos = -1;
|
||||||
}
|
}
|
||||||
|
@ -2146,7 +2142,7 @@ bool BeCOFFObject::Generate(BeModule* module, const StringImpl& fileName)
|
||||||
if (mWriteToLib)
|
if (mWriteToLib)
|
||||||
{
|
{
|
||||||
DynMemStream memStream;
|
DynMemStream memStream;
|
||||||
|
|
||||||
Generate(module);
|
Generate(module);
|
||||||
|
|
||||||
mStream = &memStream;
|
mStream = &memStream;
|
||||||
|
|
|
@ -1647,7 +1647,7 @@ void BfAutoComplete::CheckIdentifier(BfAstNode* identifierNode, bool isInExpress
|
||||||
{
|
{
|
||||||
"abstract", "base", "class", "const",
|
"abstract", "base", "class", "const",
|
||||||
"delegate", "extern", "enum", "explicit", "extension", "function",
|
"delegate", "extern", "enum", "explicit", "extension", "function",
|
||||||
"interface", "in", "internal", "mixin", "namespace", "new",
|
"interface", "in", "implicit", "internal", "mixin", "namespace", "new",
|
||||||
"operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "rettype", "return",
|
"operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "rettype", "return",
|
||||||
"scope", "sealed", "static", "struct", "this", "typealias",
|
"scope", "sealed", "static", "struct", "this", "typealias",
|
||||||
"using", "virtual", "volatile", "T", "where"
|
"using", "virtual", "volatile", "T", "where"
|
||||||
|
|
|
@ -420,6 +420,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
||||||
mInternalTypeDef = NULL;
|
mInternalTypeDef = NULL;
|
||||||
mPlatformTypeDef = NULL;
|
mPlatformTypeDef = NULL;
|
||||||
mCompilerTypeDef = NULL;
|
mCompilerTypeDef = NULL;
|
||||||
|
mCompilerGeneratorTypeDef = NULL;
|
||||||
mDiagnosticsDebugTypeDef = NULL;
|
mDiagnosticsDebugTypeDef = NULL;
|
||||||
mIDisposableTypeDef = NULL;
|
mIDisposableTypeDef = NULL;
|
||||||
mIIntegerTypeDef = NULL;
|
mIIntegerTypeDef = NULL;
|
||||||
|
@ -6765,6 +6766,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
||||||
mInternalTypeDef = _GetRequiredType("System.Internal");
|
mInternalTypeDef = _GetRequiredType("System.Internal");
|
||||||
mPlatformTypeDef = _GetRequiredType("System.Platform");
|
mPlatformTypeDef = _GetRequiredType("System.Platform");
|
||||||
mCompilerTypeDef = _GetRequiredType("System.Compiler");
|
mCompilerTypeDef = _GetRequiredType("System.Compiler");
|
||||||
|
mCompilerGeneratorTypeDef = _GetRequiredType("System.Compiler.Generator");
|
||||||
mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
|
mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
|
||||||
mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
|
mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
|
||||||
mIIntegerTypeDef = _GetRequiredType("System.IInteger");
|
mIIntegerTypeDef = _GetRequiredType("System.IInteger");
|
||||||
|
@ -8107,6 +8109,149 @@ String BfCompiler::GetTypeDefList()
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String BfCompiler::GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args)
|
||||||
|
{
|
||||||
|
if (typeInst == NULL)
|
||||||
|
{
|
||||||
|
auto type = mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_BaseType);
|
||||||
|
if (type != NULL)
|
||||||
|
typeInst = type->ToTypeInstance();
|
||||||
|
if (typeInst == NULL)
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
BfTypeVector typeVector;
|
||||||
|
typeVector.Add(typeInst);
|
||||||
|
|
||||||
|
auto generatorTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompilerGeneratorTypeDef)->ToTypeInstance();
|
||||||
|
auto methodDef = generatorTypeInst->mTypeDef->GetMethodByName(generatorMethodName);
|
||||||
|
auto moduleMethodInstance = mContext->mUnreifiedModule->GetMethodInstance(generatorTypeInst, methodDef, typeVector);
|
||||||
|
|
||||||
|
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mContext->mUnreifiedModule->mCurMethodInstance, moduleMethodInstance.mMethodInstance);
|
||||||
|
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mContext->mUnreifiedModule->mCurTypeInstance, typeInst);
|
||||||
|
|
||||||
|
BfExprEvaluator exprEvaluator(mContext->mUnreifiedModule);
|
||||||
|
exprEvaluator.mBfEvalExprFlags = BfEvalExprFlags_Comptime;
|
||||||
|
|
||||||
|
SizedArray<BfIRValue, 1> irArgs;
|
||||||
|
if (args != NULL)
|
||||||
|
irArgs.Add(mContext->mUnreifiedModule->GetStringObjectValue(*args));
|
||||||
|
auto callResult = exprEvaluator.CreateCall(NULL, moduleMethodInstance.mMethodInstance, moduleMethodInstance.mFunc, false, irArgs, NULL, BfCreateCallFlags_None);
|
||||||
|
|
||||||
|
if (callResult.mValue.IsConst())
|
||||||
|
{
|
||||||
|
auto stringPtr = mContext->mUnreifiedModule->GetStringPoolString(callResult.mValue, mContext->mUnreifiedModule->mBfIRBuilder);
|
||||||
|
if (stringPtr != NULL)
|
||||||
|
return *stringPtr;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfCompiler::HandleGeneratorErrors(StringImpl& result)
|
||||||
|
{
|
||||||
|
if ((mPassInstance->mErrors.IsEmpty()) && (mPassInstance->mOutStream.IsEmpty()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
result.Clear();
|
||||||
|
|
||||||
|
for (auto& msg : mPassInstance->mOutStream)
|
||||||
|
{
|
||||||
|
String error = msg;
|
||||||
|
error.Replace('\n', '\r');
|
||||||
|
result += "!error\t";
|
||||||
|
result += error;
|
||||||
|
result += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String BfCompiler::GetGeneratorTypeDefList()
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
BfProject* curProject = NULL;
|
||||||
|
Dictionary<BfProject*, int> projectIds;
|
||||||
|
|
||||||
|
BfResolvePassData resolvePassData;
|
||||||
|
SetAndRestoreValue<BfResolvePassData*> prevResolvePassData(mResolvePassData, &resolvePassData);
|
||||||
|
BfPassInstance passInstance(mSystem);
|
||||||
|
SetAndRestoreValue<BfPassInstance*> prevPassInstance(mPassInstance, &passInstance);
|
||||||
|
|
||||||
|
for (auto typeDef : mSystem->mTypeDefs)
|
||||||
|
{
|
||||||
|
if (typeDef->mProject->mDisabled)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (typeDef->mIsPartial)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto type = mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_BaseType);
|
||||||
|
if ((type != NULL) && (type->IsTypeInstance()))
|
||||||
|
{
|
||||||
|
auto typeInst = type->ToTypeInstance();
|
||||||
|
if ((typeInst->mBaseType != NULL) && (typeInst->mBaseType->IsInstanceOf(mCompilerGeneratorTypeDef)))
|
||||||
|
{
|
||||||
|
result += typeDef->mProject->mName;
|
||||||
|
result += ":";
|
||||||
|
result += BfTypeUtils::TypeToString(typeDef, BfTypeNameFlag_InternalName);
|
||||||
|
String nameString = GetGeneratorString(typeDef, typeInst, "GetName", NULL);
|
||||||
|
if (!nameString.IsEmpty())
|
||||||
|
result += "\t" + nameString;
|
||||||
|
result += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleGeneratorErrors(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String BfCompiler::GetGeneratorInitData(const StringImpl& typeName, const StringImpl& args)
|
||||||
|
{
|
||||||
|
BfResolvePassData resolvePassData;
|
||||||
|
SetAndRestoreValue<BfResolvePassData*> prevResolvePassData(mResolvePassData, &resolvePassData);
|
||||||
|
BfPassInstance passInstance(mSystem);
|
||||||
|
SetAndRestoreValue<BfPassInstance*> prevPassInstance(mPassInstance, &passInstance);
|
||||||
|
|
||||||
|
Array<BfTypeDef*> typeDefs;
|
||||||
|
GetTypeDefs(typeName, typeDefs);
|
||||||
|
|
||||||
|
String result;
|
||||||
|
for (auto typeDef : typeDefs)
|
||||||
|
{
|
||||||
|
result += GetGeneratorString(typeDef, NULL, "InitUI", &args);
|
||||||
|
if (!result.IsEmpty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleGeneratorErrors(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String BfCompiler::GetGeneratorGenData(const StringImpl& typeName, const StringImpl& args)
|
||||||
|
{
|
||||||
|
BfResolvePassData resolvePassData;
|
||||||
|
SetAndRestoreValue<BfResolvePassData*> prevResolvePassData(mResolvePassData, &resolvePassData);
|
||||||
|
BfPassInstance passInstance(mSystem);
|
||||||
|
SetAndRestoreValue<BfPassInstance*> prevPassInstance(mPassInstance, &passInstance);
|
||||||
|
|
||||||
|
Array<BfTypeDef*> typeDefs;
|
||||||
|
GetTypeDefs(typeName, typeDefs);
|
||||||
|
|
||||||
|
String result;
|
||||||
|
for (auto typeDef : typeDefs)
|
||||||
|
{
|
||||||
|
result += GetGeneratorString(typeDef, NULL, "Generate", &args);
|
||||||
|
if (!result.IsEmpty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
HandleGeneratorErrors(result);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
struct TypeDefMatchHelper
|
struct TypeDefMatchHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -8600,9 +8745,9 @@ String BfCompiler::GetTypeDefMatches(const StringImpl& searchStr)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
void BfCompiler::GetTypeDefs(const StringImpl& inTypeName, Array<BfTypeDef*>& typeDefs)
|
||||||
{
|
{
|
||||||
BfProject* project = NULL;
|
BfProject* project = NULL;
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
int sep = (int)inTypeName.IndexOf(':');
|
int sep = (int)inTypeName.IndexOf(':');
|
||||||
|
@ -8615,7 +8760,7 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
||||||
String typeName;
|
String typeName;
|
||||||
int genericCount = 0;
|
int genericCount = 0;
|
||||||
int pendingGenericCount = 0;
|
int pendingGenericCount = 0;
|
||||||
for ( ; idx < (int)inTypeName.length(); idx++)
|
for (; idx < (int)inTypeName.length(); idx++)
|
||||||
{
|
{
|
||||||
char c = inTypeName[idx];
|
char c = inTypeName[idx];
|
||||||
if (c == '<')
|
if (c == '<')
|
||||||
|
@ -8626,7 +8771,7 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
||||||
genericCount++;
|
genericCount++;
|
||||||
else if (c == '>')
|
else if (c == '>')
|
||||||
{
|
{
|
||||||
pendingGenericCount = genericCount;
|
pendingGenericCount = genericCount;
|
||||||
genericCount = 0;
|
genericCount = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8640,10 +8785,10 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
||||||
typeName += c;
|
typeName += c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isGlobals = false;
|
bool isGlobals = false;
|
||||||
if (typeName == ":static")
|
if (typeName == ":static")
|
||||||
{
|
{
|
||||||
typeName.clear();
|
typeName.clear();
|
||||||
isGlobals = true;
|
isGlobals = true;
|
||||||
}
|
}
|
||||||
|
@ -8657,63 +8802,73 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
||||||
if (typeName[i] == '+')
|
if (typeName[i] == '+')
|
||||||
typeName[i] = '.';
|
typeName[i] = '.';
|
||||||
|
|
||||||
String result;
|
BfAtomComposite nameComposite;
|
||||||
TypeDefMatchHelper matchHelper(result);
|
|
||||||
|
|
||||||
BfAtomComposite nameComposite;
|
|
||||||
if ((typeName.IsEmpty()) || (mSystem->ParseAtomComposite(typeName, nameComposite)))
|
if ((typeName.IsEmpty()) || (mSystem->ParseAtomComposite(typeName, nameComposite)))
|
||||||
{
|
{
|
||||||
auto itr = mSystem->mTypeDefs.TryGet(nameComposite);
|
auto itr = mSystem->mTypeDefs.TryGet(nameComposite);
|
||||||
while (itr)
|
while (itr)
|
||||||
{
|
{
|
||||||
auto typeDef = *itr;
|
auto typeDef = *itr;
|
||||||
if ((!typeDef->mIsPartial) &&
|
if ((!typeDef->mIsPartial) &&
|
||||||
(typeDef->mProject == project) &&
|
(typeDef->mProject == project) &&
|
||||||
(typeDef->mFullName == nameComposite) &&
|
(typeDef->mFullName == nameComposite) &&
|
||||||
(typeDef->IsGlobalsContainer() == isGlobals) &&
|
(typeDef->IsGlobalsContainer() == isGlobals) &&
|
||||||
(typeDef->GetSelfGenericParamCount() == pendingGenericCount))
|
(typeDef->GetSelfGenericParamCount() == pendingGenericCount))
|
||||||
{
|
{
|
||||||
auto refNode = typeDef->GetRefNode();
|
typeDefs.Add(typeDef);
|
||||||
result += "S";
|
|
||||||
matchHelper.AddLocation(refNode);
|
|
||||||
result += "\n";
|
|
||||||
|
|
||||||
for (auto fieldDef : typeDef->mFields)
|
|
||||||
{
|
|
||||||
result += "F";
|
|
||||||
result += fieldDef->mName;
|
|
||||||
matchHelper.AddFieldDef(fieldDef);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto propDef : typeDef->mProperties)
|
|
||||||
{
|
|
||||||
if (propDef->GetRefNode() == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
result += "P";
|
|
||||||
matchHelper.AddPropertyDef(typeDef, propDef);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto methodDef : typeDef->mMethods)
|
|
||||||
{
|
|
||||||
if ((methodDef->mMethodType != BfMethodType_Normal) &&
|
|
||||||
(methodDef->mMethodType != BfMethodType_Mixin) &&
|
|
||||||
(methodDef->mMethodType != BfMethodType_Ctor) &&
|
|
||||||
(methodDef->mMethodType != BfMethodType_Dtor))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (methodDef->mMethodDeclaration == NULL)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
result += "M";
|
|
||||||
matchHelper.AddMethodDef(methodDef);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
itr.MoveToNextHashMatch();
|
itr.MoveToNextHashMatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
||||||
|
{
|
||||||
|
Array<BfTypeDef*> typeDefs;
|
||||||
|
GetTypeDefs(inTypeName, typeDefs);
|
||||||
|
|
||||||
|
String result;
|
||||||
|
TypeDefMatchHelper matchHelper(result);
|
||||||
|
|
||||||
|
for (auto typeDef : typeDefs)
|
||||||
|
{
|
||||||
|
auto refNode = typeDef->GetRefNode();
|
||||||
|
result += "S";
|
||||||
|
matchHelper.AddLocation(refNode);
|
||||||
|
result += "\n";
|
||||||
|
|
||||||
|
for (auto fieldDef : typeDef->mFields)
|
||||||
|
{
|
||||||
|
result += "F";
|
||||||
|
result += fieldDef->mName;
|
||||||
|
matchHelper.AddFieldDef(fieldDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto propDef : typeDef->mProperties)
|
||||||
|
{
|
||||||
|
if (propDef->GetRefNode() == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result += "P";
|
||||||
|
matchHelper.AddPropertyDef(typeDef, propDef);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto methodDef : typeDef->mMethods)
|
||||||
|
{
|
||||||
|
if ((methodDef->mMethodType != BfMethodType_Normal) &&
|
||||||
|
(methodDef->mMethodType != BfMethodType_Mixin) &&
|
||||||
|
(methodDef->mMethodType != BfMethodType_Ctor) &&
|
||||||
|
(methodDef->mMethodType != BfMethodType_Dtor))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (methodDef->mMethodDeclaration == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
result += "M";
|
||||||
|
matchHelper.AddMethodDef(methodDef);
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8990,6 +9145,30 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorTypeDefList(BfCompiler* bfCompiler)
|
||||||
|
{
|
||||||
|
String& outString = *gTLStrReturn.Get();
|
||||||
|
outString.clear();
|
||||||
|
outString = bfCompiler->GetGeneratorTypeDefList();
|
||||||
|
return outString.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorInitData(BfCompiler* bfCompiler, char* typeDefName, char* args)
|
||||||
|
{
|
||||||
|
String& outString = *gTLStrReturn.Get();
|
||||||
|
outString.clear();
|
||||||
|
outString = bfCompiler->GetGeneratorInitData(typeDefName, args);
|
||||||
|
return outString.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorGenData(BfCompiler* bfCompiler, char* typeDefName, char* args)
|
||||||
|
{
|
||||||
|
String& outString = *gTLStrReturn.Get();
|
||||||
|
outString.clear();
|
||||||
|
outString = bfCompiler->GetGeneratorGenData(typeDefName, args);
|
||||||
|
return outString.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefList(BfCompiler* bfCompiler)
|
BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefList(BfCompiler* bfCompiler)
|
||||||
{
|
{
|
||||||
String& outString = *gTLStrReturn.Get();
|
String& outString = *gTLStrReturn.Get();
|
||||||
|
|
|
@ -374,6 +374,7 @@ public:
|
||||||
BfTypeDef* mInternalTypeDef;
|
BfTypeDef* mInternalTypeDef;
|
||||||
BfTypeDef* mPlatformTypeDef;
|
BfTypeDef* mPlatformTypeDef;
|
||||||
BfTypeDef* mCompilerTypeDef;
|
BfTypeDef* mCompilerTypeDef;
|
||||||
|
BfTypeDef* mCompilerGeneratorTypeDef;
|
||||||
BfTypeDef* mDiagnosticsDebugTypeDef;
|
BfTypeDef* mDiagnosticsDebugTypeDef;
|
||||||
BfTypeDef* mIDisposableTypeDef;
|
BfTypeDef* mIDisposableTypeDef;
|
||||||
BfTypeDef* mIIntegerTypeDef;
|
BfTypeDef* mIIntegerTypeDef;
|
||||||
|
@ -511,9 +512,15 @@ public:
|
||||||
void ProcessAutocompleteTempType();
|
void ProcessAutocompleteTempType();
|
||||||
void GetSymbolReferences();
|
void GetSymbolReferences();
|
||||||
void Cancel();
|
void Cancel();
|
||||||
void RequestFastFinish();
|
void RequestFastFinish();
|
||||||
String GetTypeDefList();
|
String GetTypeDefList();
|
||||||
String GetTypeDefMatches(const StringImpl& searchSrc);
|
String GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args);
|
||||||
|
void HandleGeneratorErrors(StringImpl& result);
|
||||||
|
String GetGeneratorTypeDefList();
|
||||||
|
String GetGeneratorInitData(const StringImpl& typeName, const StringImpl& args);
|
||||||
|
String GetGeneratorGenData(const StringImpl& typeName, const StringImpl& args);
|
||||||
|
String GetTypeDefMatches(const StringImpl& searchSrc);
|
||||||
|
void GetTypeDefs(const StringImpl& typeName, Array<BfTypeDef*>& typeDefs);
|
||||||
String GetTypeDefInfo(const StringImpl& typeName);
|
String GetTypeDefInfo(const StringImpl& typeName);
|
||||||
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
|
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
|
||||||
|
|
||||||
|
|
|
@ -892,6 +892,9 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((typeInst->IsBoxed()) && (typeInst->mTypeDef->mEmitParent != NULL))
|
||||||
|
typeInst->mTypeDef = typeInst->mTypeDef->mEmitParent;
|
||||||
|
|
||||||
if (mSystem->mWorkspaceConfigChanged)
|
if (mSystem->mWorkspaceConfigChanged)
|
||||||
{
|
{
|
||||||
typeInst->mTypeOptionsIdx = -2;
|
typeInst->mTypeOptionsIdx = -2;
|
||||||
|
@ -1060,8 +1063,12 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
||||||
if (typeInst->mTypeDef->mEmitParent != NULL)
|
if (typeInst->mTypeDef->mEmitParent != NULL)
|
||||||
{
|
{
|
||||||
auto emitTypeDef = typeInst->mTypeDef;
|
auto emitTypeDef = typeInst->mTypeDef;
|
||||||
typeInst->mTypeDef = emitTypeDef->mEmitParent;
|
typeInst->mTypeDef = emitTypeDef->mEmitParent;
|
||||||
delete emitTypeDef;
|
BfLogSysM("Type %p queueing delete of typeDef %p, resetting typeDef to %p\n", typeInst, emitTypeDef, typeInst->mTypeDef);
|
||||||
|
emitTypeDef->mDefState = BfTypeDef::DefState_Deleted;
|
||||||
|
AutoCrit autoCrit(mSystem->mDataLock);
|
||||||
|
BF_ASSERT(!mSystem->mTypeDefDeleteQueue.Contains(emitTypeDef));
|
||||||
|
mSystem->mTypeDefDeleteQueue.push_back(emitTypeDef);
|
||||||
}
|
}
|
||||||
|
|
||||||
//typeInst->mTypeDef->ClearEmitted();
|
//typeInst->mTypeDef->ClearEmitted();
|
||||||
|
@ -1912,10 +1919,17 @@ void BfContext::UpdateRevisedTypes()
|
||||||
|
|
||||||
if (typeDef->mEmitParent != NULL)
|
if (typeDef->mEmitParent != NULL)
|
||||||
{
|
{
|
||||||
auto emitTypeDef = typeDef;
|
if (typeDef->mDefState == BfTypeDef::DefState_Deleted)
|
||||||
typeDef = typeDef->mEmitParent;
|
{
|
||||||
if (typeDef->mNextRevision != NULL)
|
typeInst->mTypeDef = typeDef->mEmitParent;
|
||||||
emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto emitTypeDef = typeDef;
|
||||||
|
typeDef = typeDef->mEmitParent;
|
||||||
|
if (typeDef->mNextRevision != NULL)
|
||||||
|
emitTypeDef->mDefState = BfTypeDef::DefState_EmittedDirty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeDef->mProject->mDisabled)
|
if (typeDef->mProject->mDisabled)
|
||||||
|
|
|
@ -3578,7 +3578,7 @@ void BfExprEvaluator::GetLiteral(BfAstNode* refNode, const BfVariant& variant)
|
||||||
if ((mExpectingType != NULL) && (mExpectingType->IsIntegral()) && (mExpectingType->IsChar() == IsCharType(variant.mTypeCode)))
|
if ((mExpectingType != NULL) && (mExpectingType->IsIntegral()) && (mExpectingType->IsChar() == IsCharType(variant.mTypeCode)))
|
||||||
{
|
{
|
||||||
auto primType = (BfPrimitiveType*)mExpectingType;
|
auto primType = (BfPrimitiveType*)mExpectingType;
|
||||||
if (mModule->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, variant.mInt64))
|
if (mModule->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, variant.mUInt64))
|
||||||
{
|
{
|
||||||
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, variant.mUInt64), mExpectingType);
|
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, variant.mUInt64), mExpectingType);
|
||||||
break;
|
break;
|
||||||
|
@ -5090,7 +5090,9 @@ void BfExprEvaluator::ResolveArgValues(BfResolvedArgs& resolvedArgs, BfResolveAr
|
||||||
|
|
||||||
BfExprEvaluator exprEvaluator(mModule);
|
BfExprEvaluator exprEvaluator(mModule);
|
||||||
exprEvaluator.mResolveGenericParam = (flags & BfResolveArgsFlag_AllowUnresolvedTypes) == 0;
|
exprEvaluator.mResolveGenericParam = (flags & BfResolveArgsFlag_AllowUnresolvedTypes) == 0;
|
||||||
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr);
|
exprEvaluator.mBfEvalExprFlags = (BfEvalExprFlags)(exprEvaluator.mBfEvalExprFlags | BfEvalExprFlags_AllowRefExpr | BfEvalExprFlags_AllowOutExpr |
|
||||||
|
(mBfEvalExprFlags & (BfEvalExprFlags_Comptime)));
|
||||||
|
|
||||||
bool handled = false;
|
bool handled = false;
|
||||||
bool evaluated = false;
|
bool evaluated = false;
|
||||||
|
|
||||||
|
@ -6373,16 +6375,23 @@ void BfExprEvaluator::FinishDeferredEvals(BfResolvedArgs& argValues)
|
||||||
auto variableDeclaration = BfNodeDynCast<BfVariableDeclaration>((*argValues.mArguments)[argIdx]);
|
auto variableDeclaration = BfNodeDynCast<BfVariableDeclaration>((*argValues.mArguments)[argIdx]);
|
||||||
if ((variableDeclaration != NULL) && (variableDeclaration->mNameNode != NULL))
|
if ((variableDeclaration != NULL) && (variableDeclaration->mNameNode != NULL))
|
||||||
{
|
{
|
||||||
BfLocalVariable* localVar = new BfLocalVariable();
|
if (mModule->mCurMethodState == NULL)
|
||||||
localVar->mName = variableDeclaration->mNameNode->ToString();
|
{
|
||||||
localVar->mResolvedType = mModule->GetPrimitiveType(BfTypeCode_Var);
|
mModule->Fail("Illegal local variable", variableDeclaration);
|
||||||
localVar->mAddr = mModule->mBfIRBuilder->GetFakeVal();
|
}
|
||||||
localVar->mReadFromId = 0;
|
else
|
||||||
localVar->mWrittenToId = 0;
|
{
|
||||||
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
BfLocalVariable* localVar = new BfLocalVariable();
|
||||||
mModule->CheckVariableDef(localVar);
|
localVar->mName = variableDeclaration->mNameNode->ToString();
|
||||||
localVar->Init();
|
localVar->mResolvedType = mModule->GetPrimitiveType(BfTypeCode_Var);
|
||||||
mModule->AddLocalVariableDef(localVar, true);
|
localVar->mAddr = mModule->mBfIRBuilder->GetFakeVal();
|
||||||
|
localVar->mReadFromId = 0;
|
||||||
|
localVar->mWrittenToId = 0;
|
||||||
|
localVar->mAssignedKind = BfLocalVarAssignKind_Unconditional;
|
||||||
|
mModule->CheckVariableDef(localVar);
|
||||||
|
localVar->Init();
|
||||||
|
mModule->AddLocalVariableDef(localVar, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10139,6 +10148,12 @@ void BfExprEvaluator::Visit(BfInitializerExpression* initExpr)
|
||||||
|
|
||||||
for (auto elementExpr : initExpr->mValues)
|
for (auto elementExpr : initExpr->mValues)
|
||||||
{
|
{
|
||||||
|
if ((mBfEvalExprFlags & BfEvalExprFlags_Comptime) != 0)
|
||||||
|
{
|
||||||
|
mModule->Fail("Comptime cannot evaluate initializer expressions", elementExpr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
bool wasValidInitKind = false;
|
bool wasValidInitKind = false;
|
||||||
|
|
||||||
if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(elementExpr))
|
if (auto assignExpr = BfNodeDynCast<BfAssignmentExpression>(elementExpr))
|
||||||
|
@ -11133,8 +11148,7 @@ void BfExprEvaluator::Visit(BfCastExpression* castExpr)
|
||||||
bool BfExprEvaluator::IsExactMethodMatch(BfMethodInstance* methodA, BfMethodInstance* methodB, bool ignoreImplicitParams)
|
bool BfExprEvaluator::IsExactMethodMatch(BfMethodInstance* methodA, BfMethodInstance* methodB, bool ignoreImplicitParams)
|
||||||
{
|
{
|
||||||
if (methodA->mReturnType != methodB->mReturnType)
|
if (methodA->mReturnType != methodB->mReturnType)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int implicitParamCountA = methodA->GetImplicitParamCount();
|
int implicitParamCountA = methodA->GetImplicitParamCount();
|
||||||
if (methodA->HasExplicitThis())
|
if (methodA->HasExplicitThis())
|
||||||
implicitParamCountA++;
|
implicitParamCountA++;
|
||||||
|
@ -11696,7 +11710,11 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!IsExactMethodMatch(methodInstance, bindMethodInstance, true))
|
bool isExactMethodMatch = IsExactMethodMatch(methodInstance, bindMethodInstance, true);
|
||||||
|
if ((mExpectingType != NULL) && (mExpectingType->IsFunction()) && (methodInstance->mMethodDef->mIsMutating != bindMethodInstance->mMethodDef->mIsMutating))
|
||||||
|
isExactMethodMatch = false;
|
||||||
|
|
||||||
|
if (!isExactMethodMatch)
|
||||||
{
|
{
|
||||||
if (bindResult.mCheckedMultipleMethods)
|
if (bindResult.mCheckedMultipleMethods)
|
||||||
{
|
{
|
||||||
|
@ -11704,8 +11722,8 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
mModule->TypeToString(delegateTypeInstance).c_str()), delegateBindExpr->mTarget);
|
mModule->TypeToString(delegateTypeInstance).c_str()), delegateBindExpr->mTarget);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mModule->Fail(StrFormat("Method '%s' does not match %s '%s'", mModule->MethodToString(bindMethodInstance).c_str(), bindTypeName,
|
mModule->Fail(StrFormat("Method '%s' does not match %s '%s'", mModule->MethodToString(bindMethodInstance, (BfMethodNameFlags)(BfMethodNameFlag_ResolveGenericParamNames | BfMethodNameFlag_IncludeReturnType | BfMethodNameFlag_IncludeMut)).c_str(), bindTypeName,
|
||||||
mModule->TypeToString(delegateTypeInstance).c_str()), delegateBindExpr->mTarget);
|
mModule->TypeToString(delegateTypeInstance).c_str()), delegateBindExpr->mTarget);
|
||||||
}
|
}
|
||||||
mResult = BfTypedValue();
|
mResult = BfTypedValue();
|
||||||
|
@ -11725,7 +11743,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasIncompatibleCallingConventions = !mModule->mSystem->IsCompatibleCallingConvention(methodInstance->mCallingConvention, bindMethodInstance->mCallingConvention);
|
bool hasIncompatibleCallingConventions = !mModule->mSystem->IsCompatibleCallingConvention(methodInstance->mCallingConvention, bindMethodInstance->mCallingConvention);
|
||||||
|
|
||||||
auto _GetInvokeMethodName = [&]()
|
auto _GetInvokeMethodName = [&]()
|
||||||
{
|
{
|
||||||
String methodName = "Invoke$";
|
String methodName = "Invoke$";
|
||||||
|
@ -11789,7 +11807,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
if (mExpectingType->IsFunction())
|
if (mExpectingType->IsFunction())
|
||||||
{
|
{
|
||||||
BfIRValue result;
|
BfIRValue result;
|
||||||
if ((hasIncompatibleCallingConventions) && (mModule->HasCompiledOutput()))
|
if ((hasIncompatibleCallingConventions) && (mModule->HasExecutedOutput()))
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
{
|
{
|
||||||
|
@ -11799,11 +11817,14 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
|
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
String methodName = _GetInvokeMethodName();
|
String methodName = _GetInvokeMethodName();
|
||||||
|
|
||||||
SizedArray<BfIRType, 8> irParamTypes;
|
SizedArray<BfIRType, 8> irParamTypes;
|
||||||
BfIRType irReturnType;
|
BfIRType irReturnType;
|
||||||
bindMethodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes);
|
methodInstance->GetIRFunctionInfo(mModule, irReturnType, irParamTypes);
|
||||||
|
|
||||||
|
int thisFuncParamIdx = methodInstance->GetThisIdx();
|
||||||
|
int thisBindParamIdx = methodInstance->GetThisIdx();
|
||||||
|
|
||||||
auto prevActiveFunction = mModule->mBfIRBuilder->GetActiveFunction();
|
auto prevActiveFunction = mModule->mBfIRBuilder->GetActiveFunction();
|
||||||
auto prevInsertBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
auto prevInsertBlock = mModule->mBfIRBuilder->GetInsertBlock();
|
||||||
|
@ -11949,7 +11970,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
|
|
||||||
// Do we need a special delegate type for this?
|
// Do we need a special delegate type for this?
|
||||||
if (((captureThisByValue) || (needsSplat) || (implicitParamCount > 0) /*|| (hasIncompatibleCallingConventions)*/) &&
|
if (((captureThisByValue) || (needsSplat) || (implicitParamCount > 0) /*|| (hasIncompatibleCallingConventions)*/) &&
|
||||||
(mModule->HasCompiledOutput()))
|
(mModule->HasExecutedOutput()))
|
||||||
{
|
{
|
||||||
hasCaptures = true;
|
hasCaptures = true;
|
||||||
auto curProject = mModule->mCurTypeInstance->mTypeDef->mProject;
|
auto curProject = mModule->mCurTypeInstance->mTypeDef->mProject;
|
||||||
|
@ -12030,7 +12051,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
// Do we need specialized calling code for this?
|
// Do we need specialized calling code for this?
|
||||||
BfIRValue funcValue;
|
BfIRValue funcValue;
|
||||||
if (((needsSplat) || (implicitParamCount > 0) || (hasIncompatibleCallingConventions)) &&
|
if (((needsSplat) || (implicitParamCount > 0) || (hasIncompatibleCallingConventions)) &&
|
||||||
(mModule->HasCompiledOutput()))
|
(mModule->HasExecutedOutput()))
|
||||||
{
|
{
|
||||||
int fieldIdx = 0;
|
int fieldIdx = 0;
|
||||||
for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
|
for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
|
||||||
|
@ -12208,7 +12229,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
|
|
||||||
// >> delegate.mTarget = bindResult.mTarget
|
// >> delegate.mTarget = bindResult.mTarget
|
||||||
BfIRValue valPtr;
|
BfIRValue valPtr;
|
||||||
if (mModule->HasCompiledOutput())
|
if (mModule->HasExecutedOutput())
|
||||||
{
|
{
|
||||||
if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
|
if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
|
||||||
valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
||||||
|
@ -12226,7 +12247,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
||||||
|
|
||||||
if (!funcValue)
|
if (!funcValue)
|
||||||
{
|
{
|
||||||
if ((mModule->HasCompiledOutput()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
if ((mModule->HasExecutedOutput()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
||||||
mModule->AssertErrorState();
|
mModule->AssertErrorState();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -13188,7 +13209,7 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
|
||||||
mModule->mIncompleteMethodCount++;
|
mModule->mIncompleteMethodCount++;
|
||||||
SetAndRestoreValue<BfClosureState*> prevClosureState(mModule->mCurMethodState->mClosureState, &closureState);
|
SetAndRestoreValue<BfClosureState*> prevClosureState(mModule->mCurMethodState->mClosureState, &closureState);
|
||||||
|
|
||||||
if (mModule->HasCompiledOutput())
|
if (mModule->HasExecutedOutput())
|
||||||
mModule->SetupIRMethod(methodInstance, methodInstance->mIRFunction, methodInstance->mAlwaysInline);
|
mModule->SetupIRMethod(methodInstance, methodInstance->mIRFunction, methodInstance->mAlwaysInline);
|
||||||
|
|
||||||
// This keeps us from giving errors twice. ProcessMethod can give errors when we capture by value but needed to
|
// This keeps us from giving errors twice. ProcessMethod can give errors when we capture by value but needed to
|
||||||
|
@ -14415,7 +14436,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
||||||
{
|
{
|
||||||
if (!bindResult.mFunc)
|
if (!bindResult.mFunc)
|
||||||
{
|
{
|
||||||
BF_ASSERT((!mModule->HasCompiledOutput()) || (mModule->mBfIRBuilder->mIgnoreWrites));
|
BF_ASSERT((!mModule->HasExecutedOutput()) || (mModule->mBfIRBuilder->mIgnoreWrites));
|
||||||
appendSizeValue = mModule->GetConstValue(0);
|
appendSizeValue = mModule->GetConstValue(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -19717,7 +19738,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (((mModule->HasCompiledOutput()) || (mModule->mIsComptimeModule)) &&
|
else if (((mModule->HasExecutedOutput()) || (mModule->mIsComptimeModule)) &&
|
||||||
(wantsChecks))
|
(wantsChecks))
|
||||||
{
|
{
|
||||||
if (checkedKind == BfCheckedKind_NotSet)
|
if (checkedKind == BfCheckedKind_NotSet)
|
||||||
|
|
|
@ -857,6 +857,27 @@ BfIRValue BfIRConstHolder::CreateConstArrayZero(int count)
|
||||||
return irValue;
|
return irValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BfIRValue BfIRConstHolder::CreateConstBitCast(BfIRValue val, BfIRType type)
|
||||||
|
{
|
||||||
|
auto constVal = GetConstant(val);
|
||||||
|
|
||||||
|
auto bitCast = mTempAlloc.Alloc<BfConstantBitCast>();
|
||||||
|
if ((constVal == NULL) || (constVal->IsNull()))
|
||||||
|
bitCast->mConstType = BfConstType_BitCastNull;
|
||||||
|
else
|
||||||
|
bitCast->mConstType = BfConstType_BitCast;
|
||||||
|
BF_ASSERT(val.mId != -1);
|
||||||
|
bitCast->mTarget = val.mId;
|
||||||
|
bitCast->mToType = type;
|
||||||
|
|
||||||
|
BfIRValue castedVal(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(bitCast));
|
||||||
|
#ifdef CHECK_CONSTHOLDER
|
||||||
|
castedVal.mHolder = this;
|
||||||
|
#endif
|
||||||
|
BF_ASSERT((void*)GetConstant(castedVal) == (void*)bitCast);
|
||||||
|
return castedVal;
|
||||||
|
}
|
||||||
|
|
||||||
BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type)
|
BfIRValue BfIRConstHolder::CreateTypeOf(BfType* type)
|
||||||
{
|
{
|
||||||
BfTypeOf_Const* typeOf = mTempAlloc.Alloc<BfTypeOf_Const>();
|
BfTypeOf_Const* typeOf = mTempAlloc.Alloc<BfTypeOf_Const>();
|
||||||
|
@ -2970,10 +2991,10 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
|
||||||
diFieldTypes.push_back(memberType);
|
diFieldTypes.push_back(memberType);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPayloadEnum = (typeInstance->IsEnum()) && (!typeInstance->IsTypedPrimitive());
|
bool isPayloadEnum = (typeInstance->IsEnum()) && (!typeInstance->IsTypedPrimitive());
|
||||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
for (int fieldIdx = 0; fieldIdx < typeInstance->mFieldInstances.mSize; fieldIdx++)
|
||||||
{
|
{
|
||||||
auto fieldInstance = &fieldInstanceRef;
|
auto fieldInstance = &typeInstance->mFieldInstances[fieldIdx];
|
||||||
if (!fieldInstance->mFieldIncluded)
|
if (!fieldInstance->mFieldIncluded)
|
||||||
continue;
|
continue;
|
||||||
auto fieldDef = fieldInstance->GetFieldDef();
|
auto fieldDef = fieldInstance->GetFieldDef();
|
||||||
|
@ -3091,18 +3112,15 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
|
||||||
{
|
{
|
||||||
staticValue = ConstToMemory(staticValue);
|
staticValue = ConstToMemory(staticValue);
|
||||||
wasMadeAddr = true;
|
wasMadeAddr = true;
|
||||||
}
|
}
|
||||||
else if (resolvedFieldType->IsPointer())
|
else if (constant->mTypeCode == BfTypeCode_StringId)
|
||||||
{
|
{
|
||||||
int stringId = constant->mInt32;
|
int stringId = constant->mInt32;
|
||||||
const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString;
|
const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString;
|
||||||
staticValue = mModule->GetStringCharPtr(str);
|
if (resolvedFieldType->IsPointer())
|
||||||
}
|
staticValue = mModule->GetStringCharPtr(str);
|
||||||
else if (constant->mTypeCode == BfTypeCode_StringId)
|
else
|
||||||
{
|
staticValue = mModule->GetStringObjectValue(str);
|
||||||
int stringId = constant->mInt32;
|
|
||||||
const StringImpl& str = mModule->mContext->mStringObjectIdMap[stringId].mString;
|
|
||||||
staticValue = mModule->GetStringObjectValue(str);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -4417,25 +4435,7 @@ BfIRValue BfIRBuilder::CreateNot(BfIRValue val)
|
||||||
BfIRValue BfIRBuilder::CreateBitCast(BfIRValue val, BfIRType type)
|
BfIRValue BfIRBuilder::CreateBitCast(BfIRValue val, BfIRType type)
|
||||||
{
|
{
|
||||||
if (val.IsConst())
|
if (val.IsConst())
|
||||||
{
|
return CreateConstBitCast(val, type);
|
||||||
auto constVal = GetConstant(val);
|
|
||||||
|
|
||||||
auto bitCast = mTempAlloc.Alloc<BfConstantBitCast>();
|
|
||||||
if (constVal->IsNull())
|
|
||||||
bitCast->mConstType = BfConstType_BitCastNull;
|
|
||||||
else
|
|
||||||
bitCast->mConstType = BfConstType_BitCast;
|
|
||||||
bitCast->mTarget = val.mId;
|
|
||||||
bitCast->mToType = type;
|
|
||||||
|
|
||||||
BfIRValue castedVal(BfIRValueFlags_Const, mTempAlloc.GetChunkedId(bitCast));
|
|
||||||
#ifdef CHECK_CONSTHOLDER
|
|
||||||
castedVal.mHolder = this;
|
|
||||||
#endif
|
|
||||||
BF_ASSERT((void*)GetConstant(castedVal) == (void*)bitCast);
|
|
||||||
return castedVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto retVal = WriteCmd(BfIRCmd_BitCast, val, type);
|
auto retVal = WriteCmd(BfIRCmd_BitCast, val, type);
|
||||||
NEW_CMD_INSERTED_IRVALUE;
|
NEW_CMD_INSERTED_IRVALUE;
|
||||||
return retVal;
|
return retVal;
|
||||||
|
|
|
@ -934,6 +934,7 @@ public:
|
||||||
BfIRValue CreateConstAggCE(BfIRType type, addr_ce ptr);
|
BfIRValue CreateConstAggCE(BfIRType type, addr_ce ptr);
|
||||||
BfIRValue CreateConstArrayZero(BfIRType type, int count);
|
BfIRValue CreateConstArrayZero(BfIRType type, int count);
|
||||||
BfIRValue CreateConstArrayZero(int count);
|
BfIRValue CreateConstArrayZero(int count);
|
||||||
|
BfIRValue CreateConstBitCast(BfIRValue val, BfIRType type);
|
||||||
BfIRValue CreateTypeOf(BfType* type);
|
BfIRValue CreateTypeOf(BfType* type);
|
||||||
BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData);
|
BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData);
|
||||||
BfIRValue GetUndefConstValue(BfIRType type);
|
BfIRValue GetUndefConstValue(BfIRType type);
|
||||||
|
|
|
@ -7889,7 +7889,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
|
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
|
||||||
{
|
{
|
||||||
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mInt64))
|
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mUInt64))
|
||||||
{
|
{
|
||||||
if ((!ignoreErrors) && (PreFail()))
|
if ((!ignoreErrors) && (PreFail()))
|
||||||
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
||||||
|
@ -9617,6 +9617,11 @@ bool BfModule::HasCompiledOutput()
|
||||||
return (!mSystem->mIsResolveOnly) && (mGeneratesCode) && (!mIsComptimeModule);
|
return (!mSystem->mIsResolveOnly) && (mGeneratesCode) && (!mIsComptimeModule);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfModule::HasExecutedOutput()
|
||||||
|
{
|
||||||
|
return ((!mSystem->mIsResolveOnly) && (mGeneratesCode)) || (mIsComptimeModule);
|
||||||
|
}
|
||||||
|
|
||||||
// We will skip the object access check for any occurrences of this value
|
// We will skip the object access check for any occurrences of this value
|
||||||
void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
|
void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
|
||||||
{
|
{
|
||||||
|
@ -10519,7 +10524,7 @@ bool BfModule::HasMixin(BfTypeInstance* typeInstance, const StringImpl& methodNa
|
||||||
}
|
}
|
||||||
|
|
||||||
StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodNameFlags methodNameFlags, BfTypeVector* typeGenericArgs, BfTypeVector* methodGenericArgs)
|
StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodNameFlags methodNameFlags, BfTypeVector* typeGenericArgs, BfTypeVector* methodGenericArgs)
|
||||||
{
|
{
|
||||||
auto methodDef = methodInst->mMethodDef;
|
auto methodDef = methodInst->mMethodDef;
|
||||||
bool allowResolveGenericParamNames = ((methodNameFlags & BfMethodNameFlag_ResolveGenericParamNames) != 0);
|
bool allowResolveGenericParamNames = ((methodNameFlags & BfMethodNameFlag_ResolveGenericParamNames) != 0);
|
||||||
|
|
||||||
|
@ -10764,8 +10769,16 @@ StringT<128> BfModule::MethodToString(BfMethodInstance* methodInst, BfMethodName
|
||||||
|
|
||||||
if (accessorString.length() != 0)
|
if (accessorString.length() != 0)
|
||||||
{
|
{
|
||||||
methodName += " " + accessorString;
|
methodName += " ";
|
||||||
|
methodName += accessorString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((methodNameFlags & BfMethodNameFlag_IncludeMut) != 0)
|
||||||
|
{
|
||||||
|
if ((methodDef->mIsMutating) && (methodInst->GetOwner()->IsValueType()))
|
||||||
|
methodName += " mut";
|
||||||
|
}
|
||||||
|
|
||||||
return methodName;
|
return methodName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10860,8 +10873,17 @@ void BfModule::CurrentAddToConstHolder(BfIRValue& irVal)
|
||||||
auto origConst = irVal;
|
auto origConst = irVal;
|
||||||
if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
|
if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
|
||||||
{
|
{
|
||||||
auto bitcast = (BfConstantBitCast*)constant;
|
auto bitcast = (BfConstantBitCast*)constant;
|
||||||
constant = mBfIRBuilder->GetConstantById(bitcast->mTarget);
|
BfIRValue newVal;
|
||||||
|
if (bitcast->mTarget)
|
||||||
|
{
|
||||||
|
newVal = BfIRValue(BfIRValueFlags_Const, bitcast->mTarget);
|
||||||
|
CurrentAddToConstHolder(newVal);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
newVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstNull();
|
||||||
|
irVal = mCurTypeInstance->GetOrCreateConstHolder()->CreateConstBitCast(newVal, bitcast->mToType);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
irVal = mCurTypeInstance->CreateConst(constant, mBfIRBuilder);
|
irVal = mCurTypeInstance->CreateConst(constant, mBfIRBuilder);
|
||||||
|
@ -10986,7 +11008,7 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
|
||||||
wantType = mContext->mTypes[constant->mIRType.mId];
|
wantType = mContext->mTypes[constant->mIRType.mId];
|
||||||
|
|
||||||
if (wantType == NULL)
|
if (wantType == NULL)
|
||||||
return constHolder->CreateConstNull();
|
return mBfIRBuilder->CreateConstNull();
|
||||||
|
|
||||||
return GetDefaultValue(wantType);
|
return GetDefaultValue(wantType);
|
||||||
}
|
}
|
||||||
|
@ -11034,8 +11056,21 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
|
||||||
return mBfIRBuilder->CreateIntToPtr(ConstantToCurrent(fromTarget, constHolder, NULL), toIRType);
|
return mBfIRBuilder->CreateIntToPtr(ConstantToCurrent(fromTarget, constHolder, NULL), toIRType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((constant->mConstType == BfConstType_BitCast) || (constant->mConstType == BfConstType_BitCastNull))
|
||||||
|
{
|
||||||
|
auto bitcast = (BfConstantBitCast*)constant;
|
||||||
|
auto fromTarget = constHolder->GetConstantById(bitcast->mTarget);
|
||||||
|
BfIRType toIRType = bitcast->mToType;
|
||||||
|
if (toIRType.mKind == BfIRTypeData::TypeKind_TypeId)
|
||||||
|
{
|
||||||
|
auto toType = mContext->mTypes[toIRType.mId];
|
||||||
|
toIRType = mBfIRBuilder->MapType(toType);
|
||||||
|
}
|
||||||
|
return mBfIRBuilder->CreateBitCast(ConstantToCurrent(fromTarget, constHolder, NULL), toIRType);
|
||||||
|
}
|
||||||
|
|
||||||
if (constant->mConstType == BfConstType_Agg)
|
if (constant->mConstType == BfConstType_Agg)
|
||||||
{
|
{
|
||||||
auto constArray = (BfConstantAgg*)constant;
|
auto constArray = (BfConstantAgg*)constant;
|
||||||
|
|
||||||
if ((wantType == NULL) && (constArray->mType.mKind == BfIRTypeData::TypeKind_TypeId))
|
if ((wantType == NULL) && (constArray->mType.mKind == BfIRTypeData::TypeKind_TypeId))
|
||||||
|
@ -14456,7 +14491,7 @@ BfLocalVariable* BfModule::AddLocalVariableDef(BfLocalVariable* localVarDef, boo
|
||||||
if ((localVarDef->mNameNode != NULL) && (mCurMethodInstance != NULL))
|
if ((localVarDef->mNameNode != NULL) && (mCurMethodInstance != NULL))
|
||||||
{
|
{
|
||||||
bool isClosureProcessing = (mCurMethodState->mClosureState != NULL) && (!mCurMethodState->mClosureState->mCapturing);
|
bool isClosureProcessing = (mCurMethodState->mClosureState != NULL) && (!mCurMethodState->mClosureState->mCapturing);
|
||||||
if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (!mIsComptimeModule))
|
if ((!isClosureProcessing) && (mCompiler->mResolvePassData != NULL) && (localVarDef->mNameNode != NULL) && (rootMethodState->mMethodInstance != NULL) && (!mIsComptimeModule))
|
||||||
mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
|
mCompiler->mResolvePassData->HandleLocalReference(localVarDef->mNameNode, rootMethodState->mMethodInstance->GetOwner()->mTypeDef, rootMethodState->mMethodInstance->mMethodDef, localVarDef->mLocalVarId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15273,14 +15308,18 @@ void BfModule::AssertErrorState()
|
||||||
{
|
{
|
||||||
if (mCurTypeInstance->mTypeFailed)
|
if (mCurTypeInstance->mTypeFailed)
|
||||||
return;
|
return;
|
||||||
if (mCurTypeInstance->mTypeDef->mSource->mParsingFailed)
|
if ((mCurTypeInstance->mTypeDef->GetDefinition()->mSource != NULL) && (mCurTypeInstance->mTypeDef->GetDefinition()->mSource->mParsingFailed))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mCurMethodInstance != NULL)
|
if (mCurMethodInstance != NULL)
|
||||||
{
|
{
|
||||||
if ((mCurMethodInstance->mMethodDef->mDeclaringType != NULL) && (mCurMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
|
if ((mCurMethodInstance->mMethodDef->mDeclaringType != NULL) &&
|
||||||
|
(mCurMethodInstance->mMethodDef->mDeclaringType->mSource != NULL) &&
|
||||||
|
(mCurMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
|
||||||
return;
|
return;
|
||||||
if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL) && (mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
|
if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL) &&
|
||||||
|
(mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource != NULL) &&
|
||||||
|
(mCurMethodState->mMixinState->mMixinMethodInstance->mMethodDef->mDeclaringType->mSource->mParsingFailed))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16203,6 +16242,8 @@ void BfModule::EmitDtorBody()
|
||||||
|
|
||||||
BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define)
|
BfIRValue BfModule::CreateDllImportGlobalVar(BfMethodInstance* methodInstance, bool define)
|
||||||
{
|
{
|
||||||
|
BF_ASSERT(methodInstance->mIsReified);
|
||||||
|
|
||||||
auto typeInstance = methodInstance->GetOwner();
|
auto typeInstance = methodInstance->GetOwner();
|
||||||
|
|
||||||
bool foundDllImportAttr = false;
|
bool foundDllImportAttr = false;
|
||||||
|
@ -16467,7 +16508,7 @@ void BfModule::SetupIRMethod(BfMethodInstance* methodInstance, BfIRFunction func
|
||||||
auto elementType = refType->mElementType;
|
auto elementType = refType->mElementType;
|
||||||
PopulateType(elementType, BfPopulateType_Data);
|
PopulateType(elementType, BfPopulateType_Data);
|
||||||
addDeref = elementType->mSize;
|
addDeref = elementType->mSize;
|
||||||
if ((addDeref <= 0) && (!elementType->IsValuelessType()))
|
if ((addDeref <= 0) && (!elementType->IsValuelessType()) && (!elementType->IsOpaque()))
|
||||||
AssertErrorState();
|
AssertErrorState();
|
||||||
}
|
}
|
||||||
if ((resolvedTypeRef->IsComposite()) && (!resolvedTypeRef->IsTypedPrimitive()))
|
if ((resolvedTypeRef->IsComposite()) && (!resolvedTypeRef->IsTypedPrimitive()))
|
||||||
|
@ -17041,7 +17082,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((HasCompiledOutput()) && (matchedMethod != NULL))
|
if ((HasExecutedOutput()) && (matchedMethod != NULL))
|
||||||
{
|
{
|
||||||
SizedArray<BfIRValue, 1> args;
|
SizedArray<BfIRValue, 1> args;
|
||||||
auto ctorBodyMethodInstance = GetMethodInstance(mCurTypeInstance->mBaseType, matchedMethod, BfTypeVector());
|
auto ctorBodyMethodInstance = GetMethodInstance(mCurTypeInstance->mBaseType, matchedMethod, BfTypeVector());
|
||||||
|
@ -18486,7 +18527,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasCompiledOutput())
|
if (HasExecutedOutput())
|
||||||
{
|
{
|
||||||
BF_ASSERT(mIsModuleMutable);
|
BF_ASSERT(mIsModuleMutable);
|
||||||
}
|
}
|
||||||
|
@ -19713,7 +19754,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
skipBody = true;
|
skipBody = true;
|
||||||
skipEndChecks = true;
|
skipEndChecks = true;
|
||||||
|
|
||||||
if ((HasCompiledOutput()) || (mIsComptimeModule))
|
if (HasExecutedOutput())
|
||||||
{
|
{
|
||||||
// Clear out DebugLoc - to mark the ".addr" code as part of prologue
|
// Clear out DebugLoc - to mark the ".addr" code as part of prologue
|
||||||
mBfIRBuilder->ClearDebugLocation();
|
mBfIRBuilder->ClearDebugLocation();
|
||||||
|
@ -19743,12 +19784,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
mBfIRBuilder->CreateRetVoid();
|
mBfIRBuilder->CreateRetVoid();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BF_ASSERT(!innerMethodInstance.mMethodInstance->mMethodDef->mDeclaringType->IsEmitted());
|
|
||||||
auto innerMethodDef = innerMethodInstance.mMethodInstance->mMethodDef;
|
auto innerMethodDef = innerMethodInstance.mMethodInstance->mMethodDef;
|
||||||
if (innerType->mTypeDef->IsEmitted())
|
|
||||||
innerMethodDef = innerType->mTypeDef->mEmitParent->mMethods[innerMethodDef->mIdx];
|
|
||||||
|
|
||||||
BF_ASSERT(innerMethodDef == methodDef);
|
BF_ASSERT(innerMethodDef == methodDef);
|
||||||
|
|
||||||
SizedArray<BfIRValue, 8> innerParams;
|
SizedArray<BfIRValue, 8> innerParams;
|
||||||
|
@ -19977,7 +20014,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
else if ((mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
|
else if ((mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
|
||||||
{
|
{
|
||||||
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
|
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
|
||||||
if ((HasCompiledOutput()) || (mIsComptimeModule))
|
if (HasExecutedOutput())
|
||||||
{
|
{
|
||||||
EmitEnumToStringBody();
|
EmitEnumToStringBody();
|
||||||
}
|
}
|
||||||
|
@ -19990,7 +20027,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
else if ((mCurTypeInstance->IsTuple()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
|
else if ((mCurTypeInstance->IsTuple()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
|
||||||
{
|
{
|
||||||
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
|
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
|
||||||
if ((HasCompiledOutput()) || (mIsComptimeModule))
|
if (HasExecutedOutput())
|
||||||
{
|
{
|
||||||
EmitTupleToStringBody();
|
EmitTupleToStringBody();
|
||||||
}
|
}
|
||||||
|
@ -20032,7 +20069,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
||||||
{
|
{
|
||||||
mBfIRBuilder->CreateRetVoid();
|
mBfIRBuilder->CreateRetVoid();
|
||||||
}
|
}
|
||||||
else if ((HasCompiledOutput()) || (mIsComptimeModule))
|
else if (HasExecutedOutput())
|
||||||
{
|
{
|
||||||
String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration);
|
String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration);
|
||||||
BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName);
|
BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName);
|
||||||
|
@ -22782,18 +22819,6 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
|
||||||
//BF_ASSERT(mCompiler->IsAutocomplete());
|
//BF_ASSERT(mCompiler->IsAutocomplete());
|
||||||
BfLogSysM("DoMethodDeclaration isTemporaryFunc bailout\n");
|
BfLogSysM("DoMethodDeclaration isTemporaryFunc bailout\n");
|
||||||
return; // Bail out early for autocomplete pass
|
return; // Bail out early for autocomplete pass
|
||||||
}
|
|
||||||
|
|
||||||
if ((methodInstance->GetImportCallKind() != BfImportCallKind_None) && (!mBfIRBuilder->mIgnoreWrites) && (!methodInstance->mIRFunction))
|
|
||||||
{
|
|
||||||
BfLogSysM("DllImportGlobalVar DoMethodDeclaration processing %p\n", methodInstance);
|
|
||||||
// If this is in an extension then we did create the global variable already in the original obj
|
|
||||||
bool doDefine = mExtensionCount == 0;
|
|
||||||
BfIRValue dllImportGlobalVar = CreateDllImportGlobalVar(methodInstance, doDefine);
|
|
||||||
func = mBfIRBuilder->GetFakeVal();
|
|
||||||
methodInstance->mIRFunction = func;
|
|
||||||
BF_ASSERT(dllImportGlobalVar);
|
|
||||||
mFuncReferences[mCurMethodInstance] = dllImportGlobalVar;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: We used to have this (this != mContext->mExternalFuncModule) check, but it caused us to keep around
|
//TODO: We used to have this (this != mContext->mExternalFuncModule) check, but it caused us to keep around
|
||||||
|
|
|
@ -1633,6 +1633,7 @@ public:
|
||||||
bool IsTargetingBeefBackend();
|
bool IsTargetingBeefBackend();
|
||||||
bool WantsLifetimes();
|
bool WantsLifetimes();
|
||||||
bool HasCompiledOutput();
|
bool HasCompiledOutput();
|
||||||
|
bool HasExecutedOutput();
|
||||||
void SkipObjectAccessCheck(BfTypedValue typedVal);
|
void SkipObjectAccessCheck(BfTypedValue typedVal);
|
||||||
void EmitObjectAccessCheck(BfTypedValue typedVal);
|
void EmitObjectAccessCheck(BfTypedValue typedVal);
|
||||||
void EmitEnsureInstructionAt();
|
void EmitEnsureInstructionAt();
|
||||||
|
|
|
@ -2076,6 +2076,9 @@ void BfModule::FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInst
|
||||||
|
|
||||||
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode)
|
void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode)
|
||||||
{
|
{
|
||||||
|
for (int ifaceTypeId : ceEmitContext->mInterfaces)
|
||||||
|
typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId);
|
||||||
|
|
||||||
if (ceEmitContext->mEmitData.IsEmpty())
|
if (ceEmitContext->mEmitData.IsEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -2198,7 +2201,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!ceEmitContext->mEmitData.IsEmpty())
|
else if (ceEmitContext->HasEmissions())
|
||||||
{
|
{
|
||||||
if (typeInstance->mCeTypeInfo == NULL)
|
if (typeInstance->mCeTypeInfo == NULL)
|
||||||
typeInstance->mCeTypeInfo = new BfCeTypeInfo();
|
typeInstance->mCeTypeInfo = new BfCeTypeInfo();
|
||||||
|
@ -2210,7 +2213,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry;
|
typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ceEmitContext->mEmitData.IsEmpty())
|
if (ceEmitContext->HasEmissions())
|
||||||
{
|
{
|
||||||
String ctxStr = "comptime ApplyToType of ";
|
String ctxStr = "comptime ApplyToType of ";
|
||||||
ctxStr += TypeToString(attrType);
|
ctxStr += TypeToString(attrType);
|
||||||
|
@ -2747,7 +2750,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize;
|
resolvedTypeRef->mSize = typeInstance->mAlign = mSystem->mPtrSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mCeTypeInfo != NULL));
|
BF_ASSERT((typeInstance->mMethodInstanceGroups.size() == 0) || (typeInstance->mMethodInstanceGroups.size() == typeDef->mMethods.size()) || (typeInstance->mCeTypeInfo != NULL) || (typeInstance->IsBoxed()));
|
||||||
typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size());
|
typeInstance->mMethodInstanceGroups.Resize(typeDef->mMethods.size());
|
||||||
for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++)
|
for (int i = 0; i < (int)typeInstance->mMethodInstanceGroups.size(); i++)
|
||||||
{
|
{
|
||||||
|
@ -2927,6 +2930,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
{
|
{
|
||||||
bool hadType = false;
|
bool hadType = false;
|
||||||
|
|
||||||
|
BfAstNode* deferredErrorNode = NULL;
|
||||||
|
char* deferredError = NULL;
|
||||||
|
|
||||||
for (auto baseTypeRef : typeDef->mBaseTypes)
|
for (auto baseTypeRef : typeDef->mBaseTypes)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);
|
SetAndRestoreValue<BfTypeReference*> prevTypeRef(mContext->mCurTypeState->mCurBaseTypeRef, baseTypeRef);
|
||||||
|
@ -2946,12 +2952,14 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Fail("Underlying enum type already specified", baseTypeRef);
|
deferredError = "Underlying enum type already specified";
|
||||||
|
deferredErrorNode = baseTypeRef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Fail("Invalid underlying enum type", baseTypeRef);
|
deferredError = "Invalid underlying enum type";
|
||||||
|
deferredErrorNode = baseTypeRef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -2961,6 +2969,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (deferredError != NULL)
|
||||||
|
Fail(deferredError, deferredErrorNode, true);
|
||||||
|
|
||||||
if (underlyingType == NULL)
|
if (underlyingType == NULL)
|
||||||
{
|
{
|
||||||
underlyingType = GetPrimitiveType(BfTypeCode_Int64);
|
underlyingType = GetPrimitiveType(BfTypeCode_Int64);
|
||||||
|
@ -3305,6 +3316,27 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
wantPopulateInterfaces = true;
|
wantPopulateInterfaces = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty()))
|
||||||
|
{
|
||||||
|
for (auto ifaceTypeId : typeInstance->mCeTypeInfo->mPendingInterfaces)
|
||||||
|
{
|
||||||
|
auto ifaceType = mContext->mTypes[ifaceTypeId];
|
||||||
|
if ((ifaceType == NULL) || (!ifaceType->IsInterface()))
|
||||||
|
continue;
|
||||||
|
auto ifaceInst = ifaceType->ToTypeInstance();
|
||||||
|
|
||||||
|
if (ifaceSet.Add(ifaceInst))
|
||||||
|
{
|
||||||
|
// Not base type
|
||||||
|
BfInterfaceDecl ifaceDecl;
|
||||||
|
ifaceDecl.mIFaceTypeInst = ifaceInst;
|
||||||
|
ifaceDecl.mTypeRef = NULL;
|
||||||
|
ifaceDecl.mDeclaringType = typeDef->GetDefinition();
|
||||||
|
interfaces.Add(ifaceDecl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (_CheckTypeDone())
|
if (_CheckTypeDone())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -3694,6 +3726,25 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
if (innerType->IsIncomplete())
|
if (innerType->IsIncomplete())
|
||||||
PopulateType(innerType, BfPopulateType_Data);
|
PopulateType(innerType, BfPopulateType_Data);
|
||||||
|
|
||||||
|
auto innerTypeInst = innerType->ToTypeInstance();
|
||||||
|
if (innerTypeInst != NULL)
|
||||||
|
{
|
||||||
|
if (typeInstance->mTypeDef != innerTypeInst->mTypeDef)
|
||||||
|
{
|
||||||
|
// Rebuild with proper typedef (generally from inner type comptime emission)
|
||||||
|
typeInstance->mTypeDef = innerTypeInst->mTypeDef;
|
||||||
|
DoPopulateType(resolvedTypeRef, populateType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (typeInstance->mInterfaces.mSize < innerTypeInst->mInterfaces.mSize)
|
||||||
|
{
|
||||||
|
auto ifaceEntry = innerTypeInst->mInterfaces[typeInstance->mInterfaces.mSize];
|
||||||
|
typeInstance->mInterfaces.Add(ifaceEntry);
|
||||||
|
AddDependency(ifaceEntry.mInterfaceType, typeInstance, BfDependencyMap::DependencyFlag_ImplementsInterface);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto baseType = typeInstance->mBaseType;
|
auto baseType = typeInstance->mBaseType;
|
||||||
dataPos = baseType->mInstSize;
|
dataPos = baseType->mInstSize;
|
||||||
int alignSize = BF_MAX(innerType->mAlign, baseType->mInstAlign);
|
int alignSize = BF_MAX(innerType->mAlign, baseType->mInstAlign);
|
||||||
|
@ -3997,9 +4048,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) && (tryCE))
|
if ((typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) && (tryCE))
|
||||||
{
|
{
|
||||||
BF_ASSERT(!typeInstance->mTypeDef->IsEmitted());
|
BF_ASSERT(!typeInstance->mTypeDef->IsEmitted());
|
||||||
|
|
||||||
|
if (typeInstance->mCeTypeInfo != NULL)
|
||||||
|
typeInstance->mCeTypeInfo->mPendingInterfaces.Clear();
|
||||||
|
|
||||||
typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
|
typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
|
||||||
bool hadNewMembers = false;
|
bool hadNewMembers = false;
|
||||||
DoCEEmit(typeInstance, hadNewMembers);
|
DoCEEmit(typeInstance, hadNewMembers);
|
||||||
|
@ -4054,6 +4108,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty()))
|
||||||
|
hadNewMembers = true;
|
||||||
|
|
||||||
if ((typeInstance->mTypeDef->IsEmitted()) && (typeInstance->mCeTypeInfo == NULL))
|
if ((typeInstance->mTypeDef->IsEmitted()) && (typeInstance->mCeTypeInfo == NULL))
|
||||||
{
|
{
|
||||||
BF_ASSERT(mCompiler->mCanceling);
|
BF_ASSERT(mCompiler->mCanceling);
|
||||||
|
@ -5658,16 +5715,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto matchedMethodDef = matchedMethod->mMethodDef;
|
auto matchedMethodDef = matchedMethod->mMethodDef;
|
||||||
if (matchedMethodDef->mDeclaringType->IsEmitted())
|
|
||||||
{
|
|
||||||
Fail("Boxed interface binding error to emitted method", mCurTypeInstance->mTypeDef->GetRefNode());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (underlyingTypeInstance->mTypeDef->IsEmitted())
|
|
||||||
matchedMethodDef = underlyingTypeInstance->mTypeDef->mEmitParent->mMethods[matchedMethodDef->mIdx];
|
|
||||||
|
|
||||||
if (!matchedMethod->mIsForeignMethodDef)
|
if (!matchedMethod->mIsForeignMethodDef)
|
||||||
{
|
{
|
||||||
BfMethodInstanceGroup* boxedMethodInstanceGroup = &typeInstance->mMethodInstanceGroups[matchedMethod->mMethodDef->mIdx];
|
BfMethodInstanceGroup* boxedMethodInstanceGroup = &typeInstance->mMethodInstanceGroups[matchedMethod->mMethodDef->mIdx];
|
||||||
|
@ -5676,7 +5724,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
||||||
boxedMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
|
boxedMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl;
|
||||||
VerifyOnDemandMethods();
|
VerifyOnDemandMethods();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto methodFlags = matchedMethod->mIsForeignMethodDef ? BfGetMethodInstanceFlag_ForeignMethodDef : BfGetMethodInstanceFlag_None;
|
auto methodFlags = matchedMethod->mIsForeignMethodDef ? BfGetMethodInstanceFlag_ForeignMethodDef : BfGetMethodInstanceFlag_None;
|
||||||
methodFlags = (BfGetMethodInstanceFlags)(methodFlags | BfGetMethodInstanceFlag_MethodInstanceOnly);
|
methodFlags = (BfGetMethodInstanceFlags)(methodFlags | BfGetMethodInstanceFlag_MethodInstanceOnly);
|
||||||
|
@ -11505,29 +11553,37 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
|
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
|
||||||
auto constraintTypeInst = genericParamInst->mTypeConstraint->ToTypeInstance();
|
auto constraintTypeInst = genericParamInst->mTypeConstraint->ToTypeInstance();
|
||||||
if ((constraintTypeInst != NULL) && (constraintTypeInst->IsInstanceOf(mCompiler->mEnumTypeDef)) && (explicitCast))
|
|
||||||
|
if ((constraintTypeInst != NULL) && (constraintTypeInst->IsDelegateOrFunction()))
|
||||||
{
|
{
|
||||||
// Enum->int
|
// Could be a methodref - can't cast to anything else
|
||||||
if ((explicitCast) && (toType->IsInteger()))
|
|
||||||
return typedVal.mValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypedValue fromTypedValue;
|
|
||||||
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
|
||||||
fromTypedValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint, false, BfDefaultValueKind_Undef);
|
|
||||||
else
|
else
|
||||||
fromTypedValue = BfTypedValue(mBfIRBuilder->GetFakeVal(), genericParamInst->mTypeConstraint, genericParamInst->mTypeConstraint->IsValueType());
|
|
||||||
|
|
||||||
auto result = CastToValue(srcNode, fromTypedValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
|
|
||||||
if (result)
|
|
||||||
{
|
{
|
||||||
if ((genericParamInst->mTypeConstraint->IsDelegate()) && (toType->IsDelegate()))
|
if ((constraintTypeInst != NULL) && (constraintTypeInst->IsInstanceOf(mCompiler->mEnumTypeDef)) && (explicitCast))
|
||||||
{
|
{
|
||||||
// Don't allow cast when we are constrained by a delegate type, because BfMethodRefs can match and we require an actual alloc
|
// Enum->int
|
||||||
Fail(StrFormat("Unable to cast '%s' to '%s' because delegate constraints allow valueless direct method references", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
if ((explicitCast) && (toType->IsInteger()))
|
||||||
return BfIRValue();
|
return typedVal.mValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BfTypedValue fromTypedValue;
|
||||||
|
if (typedVal.mKind == BfTypedValueKind_GenericConstValue)
|
||||||
|
fromTypedValue = GetDefaultTypedValue(genericParamInst->mTypeConstraint, false, BfDefaultValueKind_Undef);
|
||||||
|
else
|
||||||
|
fromTypedValue = BfTypedValue(mBfIRBuilder->GetFakeVal(), genericParamInst->mTypeConstraint, genericParamInst->mTypeConstraint->IsValueType());
|
||||||
|
|
||||||
|
auto result = CastToValue(srcNode, fromTypedValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail));
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
if ((genericParamInst->mTypeConstraint->IsDelegate()) && (toType->IsDelegate()))
|
||||||
|
{
|
||||||
|
// Don't allow cast when we are constrained by a delegate type, because BfMethodRefs can match and we require an actual alloc
|
||||||
|
Fail(StrFormat("Unable to cast '%s' to '%s' because delegate constraints allow valueless direct method references", TypeToString(typedVal.mType).c_str(), TypeToString(toType).c_str()), srcNode);
|
||||||
|
return BfIRValue();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11755,7 +11811,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
||||||
|
|
||||||
if (allowCast)
|
if (allowCast)
|
||||||
{
|
{
|
||||||
if (ignoreWrites)
|
if ((ignoreWrites) && (!typedVal.mValue.IsConst()))
|
||||||
return mBfIRBuilder->GetFakeVal();
|
return mBfIRBuilder->GetFakeVal();
|
||||||
return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
|
return mBfIRBuilder->CreateBitCast(typedVal.mValue, mBfIRBuilder->MapType(toType));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2447,10 +2447,9 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
mTokenEnd = mSrcIdx;
|
mTokenEnd = mSrcIdx;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasNeg = false;
|
|
||||||
bool hadOverflow = false;
|
bool hadOverflow = false;
|
||||||
int64 val = 0;
|
uint64 val = 0;
|
||||||
int numberBase = 10;
|
int numberBase = 10;
|
||||||
int expVal = 0;
|
int expVal = 0;
|
||||||
int expSign = 0;
|
int expSign = 0;
|
||||||
|
@ -2460,8 +2459,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
int hexDigits = 0;
|
int hexDigits = 0;
|
||||||
if (c == '-')
|
if (c == '-')
|
||||||
{
|
{
|
||||||
wasNeg = true; //TODO: This never actually gets set any more (eaten as BfToken_Minus above). Move checks that use this to later in pipeline, then remove this
|
BF_FATAL("Parsing error");
|
||||||
c = mSrc[mSrcIdx++];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val = c - '0';
|
val = c - '0';
|
||||||
|
@ -2641,7 +2639,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
// This is actually a integer followed by an Int32 call (like 123.ToString)
|
// This is actually a integer followed by an Int32 call (like 123.ToString)
|
||||||
mSrcIdx -= 2;
|
mSrcIdx -= 2;
|
||||||
mTokenEnd = mSrcIdx;
|
mTokenEnd = mSrcIdx;
|
||||||
mLiteral.mInt64 = val;
|
mLiteral.mUInt64 = val;
|
||||||
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
||||||
mSyntaxToken = BfSyntaxToken_Literal;
|
mSyntaxToken = BfSyntaxToken_Literal;
|
||||||
return;
|
return;
|
||||||
|
@ -2668,27 +2666,24 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
if (endNumber)
|
if (endNumber)
|
||||||
{
|
{
|
||||||
mTokenEnd = mSrcIdx - 1;
|
mTokenEnd = mSrcIdx - 1;
|
||||||
mSrcIdx--;
|
mSrcIdx--;
|
||||||
if (wasNeg)
|
|
||||||
val = -val;
|
|
||||||
|
|
||||||
if ((numberBase == 0x10) &&
|
if ((numberBase == 0x10) &&
|
||||||
((hexDigits >= 16) || ((hadSeps) && (hexDigits > 8)) || ((hadLeadingHexSep) && (hexDigits == 8))))
|
((hexDigits >= 16) || ((hadSeps) && (hexDigits > 8)) || ((hadLeadingHexSep) && (hexDigits == 8))))
|
||||||
{
|
{
|
||||||
if (hexDigits > 16)
|
if (hexDigits > 16)
|
||||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
mLiteral.mInt64 = val;
|
mLiteral.mUInt64 = val;
|
||||||
if ((val < 0) && (!wasNeg))
|
if (val >= 0x8000000000000000)
|
||||||
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
||||||
else
|
else
|
||||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mLiteral.mInt64 = val;
|
mLiteral.mUInt64 = val;
|
||||||
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
||||||
|
|
||||||
|
|
||||||
if ((numberBase == 0x10) && (hexDigits == 7))
|
if ((numberBase == 0x10) && (hexDigits == 7))
|
||||||
mLiteral.mWarnType = BfWarning_BF4201_Only7Hex;
|
mLiteral.mWarnType = BfWarning_BF4201_Only7Hex;
|
||||||
if ((numberBase == 0x10) && (hexDigits == 9))
|
if ((numberBase == 0x10) && (hexDigits == 9))
|
||||||
|
@ -2699,7 +2694,12 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||||
}
|
}
|
||||||
else if ((val < -0x80000000LL) || (val > 0xFFFFFFFFLL))
|
//else if ((val < -0x80000000LL) || (val > 0xFFFFFFFFLL))
|
||||||
|
else if (val >= 0x8000000000000000)
|
||||||
|
{
|
||||||
|
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
||||||
|
}
|
||||||
|
else if (val > 0xFFFFFFFFLL)
|
||||||
{
|
{
|
||||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||||
}
|
}
|
||||||
|
@ -2709,7 +2709,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 prevVal = val;
|
uint64 prevVal = val;
|
||||||
if ((c >= '0') && (c <= '9') && (c < '0' + numberBase))
|
if ((c >= '0') && (c <= '9') && (c < '0' + numberBase))
|
||||||
{
|
{
|
||||||
if (numberBase == 0x10)
|
if (numberBase == 0x10)
|
||||||
|
@ -2731,9 +2731,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
}
|
}
|
||||||
|
|
||||||
else if ((c == 'u') || (c == 'U'))
|
else if ((c == 'u') || (c == 'U'))
|
||||||
{
|
{
|
||||||
if (wasNeg)
|
|
||||||
val = -val;
|
|
||||||
if ((mSrc[mSrcIdx] == 'l') || (mSrc[mSrcIdx] == 'L'))
|
if ((mSrc[mSrcIdx] == 'l') || (mSrc[mSrcIdx] == 'L'))
|
||||||
{
|
{
|
||||||
if (mSrc[mSrcIdx] == 'l')
|
if (mSrc[mSrcIdx] == 'l')
|
||||||
|
@ -2744,7 +2742,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
mLiteral.mUInt64 = (uint64)val;
|
mLiteral.mUInt64 = (uint64)val;
|
||||||
if (hexDigits > 16)
|
if (hexDigits > 16)
|
||||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
else if ((hadOverflow) || (wasNeg))
|
else if (hadOverflow)
|
||||||
mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
mSyntaxToken = BfSyntaxToken_Literal;
|
mSyntaxToken = BfSyntaxToken_Literal;
|
||||||
return;
|
return;
|
||||||
|
@ -2752,7 +2750,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
mTokenEnd = mSrcIdx;
|
mTokenEnd = mSrcIdx;
|
||||||
mLiteral.mTypeCode = BfTypeCode_UIntPtr;
|
mLiteral.mTypeCode = BfTypeCode_UIntPtr;
|
||||||
mLiteral.mUInt32 = (uint32)val;
|
mLiteral.mUInt32 = (uint32)val;
|
||||||
if ((hadOverflow) || (wasNeg) || ((uint64)val != (uint64)mLiteral.mUInt32))
|
if ((hadOverflow) || ((uint64)val != (uint64)mLiteral.mUInt32))
|
||||||
mPassInstance->FailAt("Value doesn't fit into uint32", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Value doesn't fit into uint32", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
mSyntaxToken = BfSyntaxToken_Literal;
|
mSyntaxToken = BfSyntaxToken_Literal;
|
||||||
return;
|
return;
|
||||||
|
@ -2760,9 +2758,7 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
else if ((c == 'l') || (c == 'L'))
|
else if ((c == 'l') || (c == 'L'))
|
||||||
{
|
{
|
||||||
if (c == 'l')
|
if (c == 'l')
|
||||||
TokenFail("Uppercase 'L' required for int64");
|
TokenFail("Uppercase 'L' required for int64");
|
||||||
if (wasNeg)
|
|
||||||
val = -val;
|
|
||||||
if ((mSrc[mSrcIdx] == 'u') || (mSrc[mSrcIdx] == 'U'))
|
if ((mSrc[mSrcIdx] == 'u') || (mSrc[mSrcIdx] == 'U'))
|
||||||
{
|
{
|
||||||
mSrcIdx++;
|
mSrcIdx++;
|
||||||
|
@ -2771,25 +2767,24 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
mLiteral.mUInt64 = (uint64)val;
|
mLiteral.mUInt64 = (uint64)val;
|
||||||
if (hexDigits > 16)
|
if (hexDigits > 16)
|
||||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
else if ((hadOverflow) || (wasNeg))
|
else if (hadOverflow)
|
||||||
mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Value doesn't fit into uint64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
mSyntaxToken = BfSyntaxToken_Literal;
|
mSyntaxToken = BfSyntaxToken_Literal;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mTokenEnd = mSrcIdx;
|
mTokenEnd = mSrcIdx;
|
||||||
mLiteral.mTypeCode = BfTypeCode_Int64;
|
mLiteral.mTypeCode = BfTypeCode_Int64;
|
||||||
mLiteral.mInt64 = (int64)val;
|
mLiteral.mInt64 = (int64)val;
|
||||||
|
if (val == 0x8000000000000000)
|
||||||
bool signMatched = true;
|
mLiteral.mTypeCode = BfTypeCode_UInt64;
|
||||||
if (val != 0)
|
else if (val >= 0x8000000000000000)
|
||||||
signMatched = (val < 0) == wasNeg;
|
hadOverflow = true;
|
||||||
|
|
||||||
if (numberBase == 0x10)
|
if (numberBase == 0x10)
|
||||||
{
|
{
|
||||||
if (hexDigits > 16)
|
if (hexDigits > 16)
|
||||||
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Too many hex digits for int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
}
|
}
|
||||||
else if ((hadOverflow) || (!signMatched))
|
else if (hadOverflow)
|
||||||
mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
mPassInstance->FailAt("Value doesn't fit into int64", mSourceData, mTokenStart, mSrcIdx - mTokenStart);
|
||||||
mSyntaxToken = BfSyntaxToken_Literal;
|
mSyntaxToken = BfSyntaxToken_Literal;
|
||||||
return;
|
return;
|
||||||
|
@ -2813,17 +2808,14 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTokenEnd = mSrcIdx - 1;
|
mTokenEnd = mSrcIdx - 1;
|
||||||
mSrcIdx--;
|
mSrcIdx--;
|
||||||
if (wasNeg)
|
mLiteral.mUInt64 = val;
|
||||||
val = -val;
|
|
||||||
mLiteral.mInt64 = val;
|
|
||||||
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
mLiteral.mTypeCode = BfTypeCode_IntUnknown;
|
||||||
mSyntaxToken = BfSyntaxToken_Literal;
|
mSyntaxToken = BfSyntaxToken_Literal;
|
||||||
TokenFail("Unexpected character while parsing number", 0);
|
TokenFail("Unexpected character while parsing number", 0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if ((val < 0) && (val != -0x8000000000000000))
|
|
||||||
if ((uint64)prevVal > (uint64)val)
|
if ((uint64)prevVal > (uint64)val)
|
||||||
hadOverflow = true;
|
hadOverflow = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -226,6 +226,7 @@ public:
|
||||||
void SetSource(const char* data, int length);
|
void SetSource(const char* data, int length);
|
||||||
void MoveSource(const char* data, int length); // Takes ownership of data ptr
|
void MoveSource(const char* data, int length); // Takes ownership of data ptr
|
||||||
void RefSource(const char* data, int length);
|
void RefSource(const char* data, int length);
|
||||||
|
void MakeNegative(uint64& val, bool& hadOverflow);
|
||||||
void NextToken(int endIdx = -1, bool outerIsInterpolate = false);
|
void NextToken(int endIdx = -1, bool outerIsInterpolate = false);
|
||||||
BfAstNode* CreateNode();
|
BfAstNode* CreateNode();
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,11 @@ int BfPrinter::CalcOrigLineSpacing(BfAstNode* bfAstNode, int* lineStartIdx)
|
||||||
|
|
||||||
void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
void BfPrinter::WriteIgnoredNode(BfAstNode* node)
|
||||||
{
|
{
|
||||||
|
if ((!mOutString.IsEmpty()) && (!isspace((uint8)mOutString[mOutString.mLength - 1])))
|
||||||
|
{
|
||||||
|
Write(" ");
|
||||||
|
}
|
||||||
|
|
||||||
bool wasExpectingNewLine = mExpectingNewLine;
|
bool wasExpectingNewLine = mExpectingNewLine;
|
||||||
|
|
||||||
mTriviaIdx = std::max(mTriviaIdx, node->GetTriviaStart());
|
mTriviaIdx = std::max(mTriviaIdx, node->GetTriviaStart());
|
||||||
|
@ -1759,9 +1764,14 @@ void BfPrinter::Visit(BfLambdaBindExpression* lambdaBindExpr)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ExpectSpace();
|
ExpectSpace();
|
||||||
VisitChild(lambdaBindExpr->mBody);
|
VisitChild(lambdaBindExpr->mBody);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
VisitChild(lambdaBindExpr->mDtor);
|
||||||
|
mNextStateModify.mExpectingSpace = false;
|
||||||
|
mVirtualNewLineIdx = mNextStateModify.mWantNewLineIdx;
|
||||||
|
mCurIndentLevel = mNextStateModify.mWantVirtualIndent;
|
||||||
|
mVirtualIndentLevel = mNextStateModify.mWantVirtualIndent;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfPrinter::Visit(BfObjectCreateExpression* newExpr)
|
void BfPrinter::Visit(BfObjectCreateExpression* newExpr)
|
||||||
|
@ -2643,7 +2653,7 @@ void BfPrinter::Visit(BfIndexerDeclaration* indexerDeclaration)
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfPrinter::Visit(BfFieldDeclaration* fieldDeclaration)
|
void BfPrinter::Visit(BfFieldDeclaration* fieldDeclaration)
|
||||||
{
|
{
|
||||||
bool isEnumDecl = false;
|
bool isEnumDecl = false;
|
||||||
|
|
||||||
if (auto enumEntry = BfNodeDynCast<BfEnumEntryDeclaration>(fieldDeclaration))
|
if (auto enumEntry = BfNodeDynCast<BfEnumEntryDeclaration>(fieldDeclaration))
|
||||||
|
@ -2703,18 +2713,10 @@ void BfPrinter::Visit(BfFieldDeclaration* fieldDeclaration)
|
||||||
QueueVisitChild(fieldDeclaration->mInitializer);
|
QueueVisitChild(fieldDeclaration->mInitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto fieldDtor = fieldDeclaration->mFieldDtor;
|
|
||||||
while (fieldDtor != NULL)
|
|
||||||
{
|
|
||||||
ExpectSpace();
|
|
||||||
QueueVisitChild(fieldDtor->mTildeToken);
|
|
||||||
ExpectSpace();
|
|
||||||
QueueVisitChild(fieldDtor->mBody);
|
|
||||||
fieldDtor = fieldDtor->mNextFieldDtor;
|
|
||||||
}
|
|
||||||
|
|
||||||
mNextStateModify.mExpectingSpace = false;
|
mNextStateModify.mExpectingSpace = false;
|
||||||
FlushVisitChild();
|
FlushVisitChild();
|
||||||
|
VisitChild(fieldDeclaration->mFieldDtor);
|
||||||
|
mNextStateModify.mExpectingSpace = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfPrinter::Visit(BfEnumCaseDeclaration* enumCaseDeclaration)
|
void BfPrinter::Visit(BfEnumCaseDeclaration* enumCaseDeclaration)
|
||||||
|
@ -2763,6 +2765,32 @@ void BfPrinter::Visit(BfTypeAliasDeclaration* typeDeclaration)
|
||||||
VisitChild(typeDeclaration->mEndSemicolon);
|
VisitChild(typeDeclaration->mEndSemicolon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfPrinter::Visit(BfFieldDtorDeclaration* fieldDtorDeclaration)
|
||||||
|
{
|
||||||
|
ExpectSpace();
|
||||||
|
if (fieldDtorDeclaration->mBody != NULL)
|
||||||
|
{
|
||||||
|
if (fieldDtorDeclaration->mBody->IsA<BfBlock>())
|
||||||
|
{
|
||||||
|
ExpectNewLine();
|
||||||
|
ExpectIndent();
|
||||||
|
VisitChild(fieldDtorDeclaration->mTildeToken);
|
||||||
|
VisitChild(fieldDtorDeclaration->mBody);
|
||||||
|
ExpectUnindent();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VisitChild(fieldDtorDeclaration->mTildeToken);
|
||||||
|
ExpectSpace();
|
||||||
|
VisitChild(fieldDtorDeclaration->mBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
VisitChild(fieldDtorDeclaration->mTildeToken);
|
||||||
|
|
||||||
|
VisitChild(fieldDtorDeclaration->mNextFieldDtor);
|
||||||
|
}
|
||||||
|
|
||||||
void BfPrinter::Visit(BfTypeDeclaration* typeDeclaration)
|
void BfPrinter::Visit(BfTypeDeclaration* typeDeclaration)
|
||||||
{
|
{
|
||||||
SetAndRestoreValue<BfTypeDeclaration*> prevTypeDecl(mCurTypeDecl, typeDeclaration);
|
SetAndRestoreValue<BfTypeDeclaration*> prevTypeDecl(mCurTypeDecl, typeDeclaration);
|
||||||
|
|
|
@ -220,6 +220,7 @@ public:
|
||||||
virtual void Visit(BfFieldDeclaration* fieldDeclaration) override;
|
virtual void Visit(BfFieldDeclaration* fieldDeclaration) override;
|
||||||
virtual void Visit(BfEnumCaseDeclaration* enumCaseDeclaration) override;
|
virtual void Visit(BfEnumCaseDeclaration* enumCaseDeclaration) override;
|
||||||
virtual void Visit(BfTypeAliasDeclaration* typeDeclaration) override;
|
virtual void Visit(BfTypeAliasDeclaration* typeDeclaration) override;
|
||||||
|
virtual void Visit(BfFieldDtorDeclaration* fieldDtorDeclaration) override;
|
||||||
virtual void Visit(BfTypeDeclaration* typeDeclaration) override;
|
virtual void Visit(BfTypeDeclaration* typeDeclaration) override;
|
||||||
virtual void Visit(BfUsingDirective* usingDirective) override;
|
virtual void Visit(BfUsingDirective* usingDirective) override;
|
||||||
virtual void Visit(BfUsingModDirective* usingDirective) override;
|
virtual void Visit(BfUsingModDirective* usingDirective) override;
|
||||||
|
|
|
@ -5912,12 +5912,9 @@ BfAstNode* BfReducer::ReadTypeMember(BfTokenNode* tokenNode, bool declStarted, i
|
||||||
ReplaceNode(tokenNode, operatorDecl);
|
ReplaceNode(tokenNode, operatorDecl);
|
||||||
operatorDecl->mOperatorToken = tokenNode;
|
operatorDecl->mOperatorToken = tokenNode;
|
||||||
|
|
||||||
auto nextIdentifier = ExpectIdentifierAfter(operatorDecl, "type");
|
|
||||||
if (nextIdentifier == NULL)
|
|
||||||
return operatorDecl;
|
|
||||||
mVisitorPos.mReadPos--; // Backtrack, that's part of our type
|
|
||||||
|
|
||||||
auto typeRef = CreateTypeRefAfter(operatorDecl);
|
auto typeRef = CreateTypeRefAfter(operatorDecl);
|
||||||
|
if (typeRef == NULL)
|
||||||
|
return operatorDecl;
|
||||||
MEMBER_SET_CHECKED(operatorDecl, mReturnType, typeRef);
|
MEMBER_SET_CHECKED(operatorDecl, mReturnType, typeRef);
|
||||||
operatorDecl->mIsConvOperator = true;
|
operatorDecl->mIsConvOperator = true;
|
||||||
|
|
||||||
|
|
|
@ -1298,15 +1298,6 @@ void BfMethodInstance::GetIRFunctionInfo(BfModule* module, BfIRType& returnType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if ((paramIdx == 0) && (GetParamName(0) == "this") && (checkType->IsPointer()))
|
|
||||||
// {
|
|
||||||
// // We don't actually pass a this pointer for mut methods in valueless structs
|
|
||||||
// auto underlyingType = checkType->GetUnderlyingType();
|
|
||||||
// module->PopulateType(underlyingType, BfPopulateType_Data);
|
|
||||||
// if (underlyingType->IsValuelessType())
|
|
||||||
// continue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (checkType->CanBeValuelessType())
|
if (checkType->CanBeValuelessType())
|
||||||
module->PopulateType(checkType, BfPopulateType_Data);
|
module->PopulateType(checkType, BfPopulateType_Data);
|
||||||
if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef()))
|
if ((checkType->IsValuelessType()) && (!checkType->IsMethodRef()))
|
||||||
|
@ -1563,6 +1554,7 @@ BfTypeInstance::~BfTypeInstance()
|
||||||
if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL))
|
if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL))
|
||||||
{
|
{
|
||||||
mMethodInstanceGroups.Clear();
|
mMethodInstanceGroups.Clear();
|
||||||
|
BfLogSys(mModule->mSystem, "Type %p dtor deleting typeDef %p\n", this, mTypeDef);
|
||||||
delete mTypeDef;
|
delete mTypeDef;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2636,6 +2628,12 @@ void BfTupleType::Finish()
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
BfBoxedType::~BfBoxedType()
|
||||||
|
{
|
||||||
|
if ((mTypeDef != NULL) && (mTypeDef->mEmitParent != NULL))
|
||||||
|
mTypeDef = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
BfType* BfBoxedType::GetModifiedElementType()
|
BfType* BfBoxedType::GetModifiedElementType()
|
||||||
{
|
{
|
||||||
if ((mBoxedFlags & BoxedFlags_StructPtr) != 0)
|
if ((mBoxedFlags & BoxedFlags_StructPtr) != 0)
|
||||||
|
|
|
@ -61,7 +61,8 @@ enum BfMethodNameFlags : uint8
|
||||||
BfMethodNameFlag_ResolveGenericParamNames = 1,
|
BfMethodNameFlag_ResolveGenericParamNames = 1,
|
||||||
BfMethodNameFlag_OmitTypeName = 2,
|
BfMethodNameFlag_OmitTypeName = 2,
|
||||||
BfMethodNameFlag_IncludeReturnType = 4,
|
BfMethodNameFlag_IncludeReturnType = 4,
|
||||||
BfMethodNameFlag_OmitParams = 8
|
BfMethodNameFlag_OmitParams = 8,
|
||||||
|
BfMethodNameFlag_IncludeMut = 0x10
|
||||||
};
|
};
|
||||||
|
|
||||||
enum BfGetMethodInstanceFlags : uint16
|
enum BfGetMethodInstanceFlags : uint16
|
||||||
|
@ -1827,6 +1828,7 @@ class BfCeTypeInfo
|
||||||
public:
|
public:
|
||||||
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
|
Dictionary<int, BfCeTypeEmitEntry> mOnCompileMap;
|
||||||
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
|
Dictionary<int, BfCeTypeEmitEntry> mTypeIFaceMap;
|
||||||
|
Array<int> mPendingInterfaces;
|
||||||
Val128 mHash;
|
Val128 mHash;
|
||||||
bool mFailed;
|
bool mFailed;
|
||||||
BfCeTypeInfo* mNext;
|
BfCeTypeInfo* mNext;
|
||||||
|
@ -2109,6 +2111,7 @@ public:
|
||||||
mBoxedBaseType = NULL;
|
mBoxedBaseType = NULL;
|
||||||
mBoxedFlags = BoxedFlags_None;
|
mBoxedFlags = BoxedFlags_None;
|
||||||
}
|
}
|
||||||
|
~BfBoxedType();
|
||||||
|
|
||||||
virtual bool IsBoxed() override { return true; }
|
virtual bool IsBoxed() override { return true; }
|
||||||
|
|
||||||
|
|
|
@ -793,11 +793,6 @@ BfTypeDef::~BfTypeDef()
|
||||||
{
|
{
|
||||||
BfLogSysM("BfTypeDef::~BfTypeDef %p\n", this);
|
BfLogSysM("BfTypeDef::~BfTypeDef %p\n", this);
|
||||||
|
|
||||||
if ((mHash == -1330357811) && (IsEmitted()))
|
|
||||||
{
|
|
||||||
NOP;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete mNextRevision;
|
delete mNextRevision;
|
||||||
FreeMembers();
|
FreeMembers();
|
||||||
|
|
||||||
|
@ -2282,6 +2277,41 @@ bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, int64 value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, uint64 value)
|
||||||
|
{
|
||||||
|
if (typeCode == BfTypeCode_IntPtr)
|
||||||
|
typeCode = (mPtrSize == 4) ? BfTypeCode_Int32 : BfTypeCode_Int64;
|
||||||
|
if (typeCode == BfTypeCode_UIntPtr)
|
||||||
|
typeCode = (mPtrSize == 4) ? BfTypeCode_UInt32 : BfTypeCode_UInt64;
|
||||||
|
|
||||||
|
if (value >= 0x8000000000000000)
|
||||||
|
return typeCode == BfTypeCode_UInt64;
|
||||||
|
|
||||||
|
switch (typeCode)
|
||||||
|
{
|
||||||
|
case BfTypeCode_Int8:
|
||||||
|
return (value < 0x80);
|
||||||
|
case BfTypeCode_Int16:
|
||||||
|
return (value < 0x8000);
|
||||||
|
case BfTypeCode_Int32:
|
||||||
|
return (value < 0x80000000LL);
|
||||||
|
case BfTypeCode_Int64:
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case BfTypeCode_UInt8:
|
||||||
|
return (value < 0x100);
|
||||||
|
case BfTypeCode_UInt16:
|
||||||
|
return (value < 0x10000);
|
||||||
|
case BfTypeCode_UInt32:
|
||||||
|
return (value < 0x100000000LL);
|
||||||
|
case BfTypeCode_UInt64:
|
||||||
|
return true;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
BfParser* BfSystem::CreateParser(BfProject* bfProject)
|
BfParser* BfSystem::CreateParser(BfProject* bfProject)
|
||||||
{
|
{
|
||||||
AutoCrit crit(mDataLock);
|
AutoCrit crit(mDataLock);
|
||||||
|
@ -3693,10 +3723,14 @@ void BfSystem::RemoveOldData()
|
||||||
{
|
{
|
||||||
AutoCrit autoCrit(mDataLock);
|
AutoCrit autoCrit(mDataLock);
|
||||||
|
|
||||||
for (auto typeDef : mTypeDefDeleteQueue)
|
for (int i = 0; i < (int)mTypeDefDeleteQueue.size(); i++)
|
||||||
|
{
|
||||||
|
auto typeDef = mTypeDefDeleteQueue[i];
|
||||||
|
mTypeDefDeleteQueue[i] = NULL;
|
||||||
|
BfLogSys(this, "RemoveOldData deleting from mTypeDefDeleteQueue %p\n", typeDef);
|
||||||
delete typeDef;
|
delete typeDef;
|
||||||
|
}
|
||||||
mTypeDefDeleteQueue.Clear();
|
mTypeDefDeleteQueue.Clear();
|
||||||
|
|
||||||
|
|
||||||
if (!mProjectDeleteQueue.IsEmpty())
|
if (!mProjectDeleteQueue.IsEmpty())
|
||||||
{
|
{
|
||||||
|
@ -3729,6 +3763,7 @@ void BfSystem::RemoveOldData()
|
||||||
|
|
||||||
void BfSystem::VerifyTypeDef(BfTypeDef* typeDef)
|
void BfSystem::VerifyTypeDef(BfTypeDef* typeDef)
|
||||||
{
|
{
|
||||||
|
#if defined _DEBUG && false
|
||||||
auto _FindTypeDef = [&](BfTypeReference* typeRef)
|
auto _FindTypeDef = [&](BfTypeReference* typeRef)
|
||||||
{
|
{
|
||||||
if (auto directStrTypeRef = BfNodeDynCast<BfDirectStrTypeReference>(typeRef))
|
if (auto directStrTypeRef = BfNodeDynCast<BfDirectStrTypeReference>(typeRef))
|
||||||
|
@ -3762,6 +3797,7 @@ void BfSystem::VerifyTypeDef(BfTypeDef* typeDef)
|
||||||
_FindTypeDef(paramDef->mTypeRef);
|
_FindTypeDef(paramDef->mTypeRef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
BfTypeOptions* BfSystem::GetTypeOptions(int optionsIdx)
|
BfTypeOptions* BfSystem::GetTypeOptions(int optionsIdx)
|
||||||
|
|
|
@ -1610,6 +1610,7 @@ public:
|
||||||
|
|
||||||
void CreateBasicTypes();
|
void CreateBasicTypes();
|
||||||
bool DoesLiteralFit(BfTypeCode typeCode, int64 value);
|
bool DoesLiteralFit(BfTypeCode typeCode, int64 value);
|
||||||
|
bool DoesLiteralFit(BfTypeCode typeCode, uint64 value);
|
||||||
BfParser* CreateParser(BfProject* bfProject);
|
BfParser* CreateParser(BfProject* bfProject);
|
||||||
BfCompiler* CreateCompiler(bool isResolveOnly);
|
BfCompiler* CreateCompiler(bool isResolveOnly);
|
||||||
BfProject* GetProject(const StringImpl& projName);
|
BfProject* GetProject(const StringImpl& projName);
|
||||||
|
|
|
@ -1288,7 +1288,7 @@ void CeBuilder::Build()
|
||||||
auto methodInstance = mCeFunction->mMethodInstance;
|
auto methodInstance = mCeFunction->mMethodInstance;
|
||||||
|
|
||||||
if (methodInstance != NULL)
|
if (methodInstance != NULL)
|
||||||
{
|
{
|
||||||
BfMethodInstance dupMethodInstance;
|
BfMethodInstance dupMethodInstance;
|
||||||
dupMethodInstance.CopyFrom(methodInstance);
|
dupMethodInstance.CopyFrom(methodInstance);
|
||||||
auto methodDef = methodInstance->mMethodDef;
|
auto methodDef = methodInstance->mMethodDef;
|
||||||
|
@ -1638,10 +1638,10 @@ void CeBuilder::Build()
|
||||||
EmitBinaryOp(CeOp_Shl_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
EmitBinaryOp(CeOp_Shl_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||||
break;
|
break;
|
||||||
case BeBinaryOpKind_RightShift:
|
case BeBinaryOpKind_RightShift:
|
||||||
EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||||
break;
|
break;
|
||||||
case BeBinaryOpKind_ARightShift:
|
case BeBinaryOpKind_ARightShift:
|
||||||
EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Fail("Invalid binary op");
|
Fail("Invalid binary op");
|
||||||
|
@ -2476,7 +2476,18 @@ void CeBuilder::Build()
|
||||||
EmitFrameOffset(ceSize);
|
EmitFrameOffset(ceSize);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case BfIRIntrinsic_MemSet:
|
||||||
|
{
|
||||||
|
CeOperand ceDestPtr = GetOperand(castedInst->mArgs[0].mValue);
|
||||||
|
CeOperand ceValue = GetOperand(castedInst->mArgs[1].mValue);
|
||||||
|
CeOperand ceSize = GetOperand(castedInst->mArgs[2].mValue);
|
||||||
|
|
||||||
|
Emit(CeOp_MemSet);
|
||||||
|
EmitFrameOffset(ceDestPtr);
|
||||||
|
EmitFrameOffset(ceValue);
|
||||||
|
EmitFrameOffset(ceSize);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case BfIRIntrinsic_AtomicFence:
|
case BfIRIntrinsic_AtomicFence:
|
||||||
// Nothing to do
|
// Nothing to do
|
||||||
|
@ -4729,6 +4740,17 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitAddInterface)
|
||||||
|
{
|
||||||
|
int32 typeId = *(int32*)((uint8*)stackPtr);
|
||||||
|
int32 ifaceTypeId = *(int32*)((uint8*)stackPtr + sizeof(int32));
|
||||||
|
if ((mCurEmitContext == NULL) || (mCurEmitContext->mType->mTypeId != typeId))
|
||||||
|
{
|
||||||
|
_Fail("Code cannot be emitted for this type in this context");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
mCurEmitContext->mInterfaces.Add(ifaceTypeId);
|
||||||
|
}
|
||||||
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitMethodEntry)
|
else if (checkFunction->mFunctionKind == CeFunctionKind_EmitMethodEntry)
|
||||||
{
|
{
|
||||||
int64 methodHandle = *(int64*)((uint8*)stackPtr);
|
int64 methodHandle = *(int64*)((uint8*)stackPtr);
|
||||||
|
@ -4972,7 +4994,12 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
if (*fastFinishPtr)
|
if (*fastFinishPtr)
|
||||||
{
|
{
|
||||||
if (*cancelingPtr)
|
if (*cancelingPtr)
|
||||||
_Fail("Comptime evaluation canceled");
|
{
|
||||||
|
if ((mCurModule != NULL) && (mCurModule->mCurTypeInstance != NULL))
|
||||||
|
mCurModule->DeferRebuildType(mCurModule->mCurTypeInstance);
|
||||||
|
else
|
||||||
|
_Fail("Comptime evaluation canceled");
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6817,6 +6844,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
|
||||||
{
|
{
|
||||||
ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
|
ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody;
|
||||||
}
|
}
|
||||||
|
if (methodDef->mName == "Comptime_EmitAddInterface")
|
||||||
|
{
|
||||||
|
ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface;
|
||||||
|
}
|
||||||
else if (methodDef->mName == "Comptime_EmitMethodEntry")
|
else if (methodDef->mName == "Comptime_EmitMethodEntry")
|
||||||
{
|
{
|
||||||
ceFunction->mFunctionKind = CeFunctionKind_EmitMethodEntry;
|
ceFunction->mFunctionKind = CeFunctionKind_EmitMethodEntry;
|
||||||
|
|
|
@ -289,6 +289,7 @@ enum CeFunctionKind
|
||||||
CeFunctionKind_Method_GetParamInfo,
|
CeFunctionKind_Method_GetParamInfo,
|
||||||
|
|
||||||
CeFunctionKind_EmitTypeBody,
|
CeFunctionKind_EmitTypeBody,
|
||||||
|
CeFunctionKind_EmitAddInterface,
|
||||||
CeFunctionKind_EmitMethodEntry,
|
CeFunctionKind_EmitMethodEntry,
|
||||||
CeFunctionKind_EmitMethodExit,
|
CeFunctionKind_EmitMethodExit,
|
||||||
CeFunctionKind_EmitMixin,
|
CeFunctionKind_EmitMixin,
|
||||||
|
@ -687,6 +688,7 @@ class CeEmitContext
|
||||||
public:
|
public:
|
||||||
BfType* mType;
|
BfType* mType;
|
||||||
BfMethodInstance* mMethodInstance;
|
BfMethodInstance* mMethodInstance;
|
||||||
|
Array<int32> mInterfaces;
|
||||||
String mEmitData;
|
String mEmitData;
|
||||||
String mExitEmitData;
|
String mExitEmitData;
|
||||||
bool mFailed;
|
bool mFailed;
|
||||||
|
@ -697,6 +699,11 @@ public:
|
||||||
mMethodInstance = NULL;
|
mMethodInstance = NULL;
|
||||||
mFailed = false;
|
mFailed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HasEmissions()
|
||||||
|
{
|
||||||
|
return !mEmitData.IsEmpty() || !mInterfaces.IsEmpty();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CeContext
|
class CeContext
|
||||||
|
|
|
@ -174,7 +174,61 @@ namespace Tests
|
||||||
public float mY;
|
public float mY;
|
||||||
public float mZ;
|
public float mZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SerializationContext
|
||||||
|
{
|
||||||
|
public String mStr = new String() ~ delete _;
|
||||||
|
public void Serialize<T>(String name, T val) where T : struct
|
||||||
|
{
|
||||||
|
mStr.AppendF($"{name} {val}\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ISerializable
|
||||||
|
{
|
||||||
|
void Serialize(SerializationContext ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(.Enum | .Struct | .Class, .NotInherited | .ReflectAttribute | .DisallowAllowMultiple)]
|
||||||
|
struct SerializableAttribute : Attribute, IComptimeTypeApply
|
||||||
|
{
|
||||||
|
[Comptime]
|
||||||
|
public void ApplyToType(Type type)
|
||||||
|
{
|
||||||
|
const String SERIALIZE_NAME = "void ISerializable.Serialize(SerializationContext ctx)\n";
|
||||||
|
|
||||||
|
String serializeBuffer = new .();
|
||||||
|
|
||||||
|
Compiler.Assert(!type.IsUnion);
|
||||||
|
|
||||||
|
for (let field in type.GetFields())
|
||||||
|
{
|
||||||
|
if (!field.IsInstanceField || field.DeclaringType != type)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
serializeBuffer.AppendF($"\n\tctx.Serialize(\"{field.Name}\", {field.Name});");
|
||||||
|
}
|
||||||
|
|
||||||
|
Compiler.EmitTypeBody(type, scope $"{SERIALIZE_NAME}{{{serializeBuffer}\n}}\n");
|
||||||
|
Compiler.EmitAddInterface(type, typeof(ISerializable));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable]
|
||||||
|
struct Foo : this(float x, float y)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ComponentHandler<T>
|
||||||
|
where T : struct
|
||||||
|
{
|
||||||
|
uint8* data;
|
||||||
|
protected override void GCMarkMembers()
|
||||||
|
{
|
||||||
|
T* ptr = (T*)data;
|
||||||
|
GC.Mark!((*ptr));
|
||||||
|
}
|
||||||
|
}
|
||||||
[Test]
|
[Test]
|
||||||
public static void TestBasics()
|
public static void TestBasics()
|
||||||
{
|
{
|
||||||
|
@ -209,6 +263,12 @@ namespace Tests
|
||||||
4 mY
|
4 mY
|
||||||
8 mZ
|
8 mZ
|
||||||
""");
|
""");
|
||||||
|
|
||||||
|
Foo bar = .(10, 2);
|
||||||
|
ISerializable iSer = bar;
|
||||||
|
SerializationContext serCtx = scope .();
|
||||||
|
iSer.Serialize(serCtx);
|
||||||
|
Test.Assert(serCtx.mStr == "x 10\ny 2\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8415,7 +8415,7 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC
|
||||||
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
||||||
if (isReadOnly)
|
if (isReadOnly)
|
||||||
evalStr += ", ne";
|
evalStr += ", ne";
|
||||||
retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64() / dimSize1, 50000) +
|
retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, sizeValue.GetInt64() / dimSize1, 50000) +
|
||||||
"\t[{0}]\t" + evalStr;
|
"\t[{0}]\t" + evalStr;
|
||||||
}
|
}
|
||||||
else if (lowerDimSizes.size() == 2)
|
else if (lowerDimSizes.size() == 2)
|
||||||
|
@ -8431,7 +8431,7 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC
|
||||||
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
||||||
if (isReadOnly)
|
if (isReadOnly)
|
||||||
evalStr += ", ne";
|
evalStr += ", ne";
|
||||||
retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64() / dimSize1 / dimSize2, 50000) +
|
retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, sizeValue.GetInt64() / dimSize1 / dimSize2, 50000) +
|
||||||
"\t[{0}]\t" + evalStr;
|
"\t[{0}]\t" + evalStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8449,7 +8449,7 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC
|
||||||
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
||||||
if (isReadOnly)
|
if (isReadOnly)
|
||||||
evalStr += ", ne";
|
evalStr += ", ne";
|
||||||
retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64() / dimSize1 / dimSize2 / dimSize3, 50000) +
|
retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, sizeValue.GetInt64() / dimSize1 / dimSize2 / dimSize3, 50000) +
|
||||||
"\t[{0}]\t" + evalStr;
|
"\t[{0}]\t" + evalStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8459,7 +8459,7 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC
|
||||||
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
||||||
if (isReadOnly)
|
if (isReadOnly)
|
||||||
evalStr += ", ne";
|
evalStr += ", ne";
|
||||||
retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64(), 50000) +
|
retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, sizeValue.GetInt64(), 50000) +
|
||||||
"\t[{0}]\t" + evalStr;
|
"\t[{0}]\t" + evalStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8476,7 +8476,7 @@ void WinDebugger::HandleCustomExpandedItems(String& retVal, DbgCompileUnit* dbgC
|
||||||
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
evalStr += ", refid=\"" + referenceId + ".[]\"";
|
||||||
if (isReadOnly)
|
if (isReadOnly)
|
||||||
evalStr += ", ne";
|
evalStr += ", ne";
|
||||||
retVal += "\n:repeat" + StrFormat("\t%d\t%d\t%d", 0, (int)sizeValue.GetInt64(), 50000) +
|
retVal += "\n:repeat" + StrFormat("\t%d\t%lld\t%d", 0, sizeValue.GetInt64(), 50000) +
|
||||||
"\t[{0}]\t" + evalStr;
|
"\t[{0}]\t" + evalStr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue