mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 03:28:20 +02:00
Code generator support
This commit is contained in:
parent
195c705a46
commit
73099e4a04
15 changed files with 1472 additions and 83 deletions
|
@ -256,7 +256,10 @@ namespace Beefy.widgets
|
|||
public virtual void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
||||
{
|
||||
if (mClosed)
|
||||
{
|
||||
BFApp.sApp.DeferDelete(this);
|
||||
return;
|
||||
}
|
||||
|
||||
mInPopupWindow = true;
|
||||
|
||||
|
|
|
@ -1,8 +1,188 @@
|
|||
using System.Reflection;
|
||||
using System.Diagnostics;
|
||||
using System.Collections;
|
||||
using System.Security.Cryptography;
|
||||
|
||||
namespace System
|
||||
{
|
||||
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 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
|
||||
{
|
||||
void* mNative;
|
||||
|
@ -43,7 +223,7 @@ namespace System
|
|||
public static extern String CallerProject;
|
||||
|
||||
[LinkName("#CallerExpression")]
|
||||
public static extern String[0x0FFFFFFF] CallerExpression;
|
||||
public static extern String[0x00FFFFFF] CallerExpression;
|
||||
|
||||
[LinkName("#ProjectName")]
|
||||
public static extern String ProjectName;
|
||||
|
|
|
@ -15,9 +15,10 @@ namespace IDE
|
|||
public Action mOnThreadDone ~ delete _;
|
||||
[ThreadStatic]
|
||||
public static bool mBpSetThreadName;
|
||||
public bool mAllowFastFinish;
|
||||
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);
|
||||
|
||||
|
@ -26,6 +27,7 @@ namespace IDE
|
|||
|
||||
BeefPerf.Event("DoBackground:starting", "");
|
||||
|
||||
mAllowFastFinish = allowFastFinish;
|
||||
mOnThreadDone = onThreadDone;
|
||||
mThreadRunning = true;
|
||||
mWaitEvent.Reset();
|
||||
|
@ -47,6 +49,7 @@ namespace IDE
|
|||
delete threadStart;
|
||||
mThread = null;
|
||||
mThreadRunning = false;
|
||||
mAllowFastFinish = true;
|
||||
BeefPerf.Event("DoBackground:threadEnd", "");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
public bool IsPerformingBackgroundOperationHi()
|
||||
{
|
||||
return (mThreadWorkerHi.mThreadRunning);
|
||||
}
|
||||
|
||||
public void DoBackground(ThreadStart threadStart, Action onThreadDone = null, int maxWait = 0)
|
||||
{
|
||||
CancelBackground();
|
||||
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()
|
||||
|
|
|
@ -94,6 +94,15 @@ namespace IDE.Compiler
|
|||
[CallingConvention(.Stdcall), CLink]
|
||||
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]
|
||||
static extern char8* BfCompiler_GetTypeDefList(void* bfCompiler);
|
||||
|
||||
|
@ -674,17 +683,21 @@ namespace IDE.Compiler
|
|||
|
||||
public override void RequestCancelBackground()
|
||||
{
|
||||
if ([Friend]mThreadWorker.mThreadRunning)
|
||||
if (mThreadWorker.mThreadRunning)
|
||||
{
|
||||
if ((mNativeBfCompiler != null) && (!gApp.mDeterministic))
|
||||
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))
|
||||
BfCompiler_RequestFastFinish(mNativeBfCompiler);
|
||||
}
|
||||
|
@ -710,6 +723,21 @@ namespace IDE.Compiler
|
|||
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)
|
||||
{
|
||||
outStr.Append(BfCompiler_GetTypeDefList(mNativeBfCompiler));
|
||||
|
|
|
@ -37,6 +37,7 @@ namespace IDE
|
|||
public ProjectFolder mParentFolder;
|
||||
public String mName = new String() ~ delete _;
|
||||
public String mComment = new String() ~ delete _;
|
||||
public bool mDetached;
|
||||
|
||||
public virtual bool IncludeInMap
|
||||
{
|
||||
|
@ -105,6 +106,7 @@ namespace IDE
|
|||
|
||||
public virtual void Detach()
|
||||
{
|
||||
mDetached = true;
|
||||
ReleaseRef();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -598,10 +598,14 @@ namespace IDE.ui
|
|||
}
|
||||
}
|
||||
|
||||
var bfSystem = gApp.mBfResolveSystem;
|
||||
|
||||
String typeName = scope .();
|
||||
GetName(item, typeName);
|
||||
String info = scope .();
|
||||
bfSystem.Lock(0);
|
||||
gApp.mBfResolveCompiler.GetTypeDefInfo(typeName, info);
|
||||
bfSystem.Unlock();
|
||||
|
||||
for (let str in info.Split('\n'))
|
||||
{
|
||||
|
|
869
IDE/src/ui/GenerateDialog.bf
Normal file
869
IDE/src/ui/GenerateDialog.bf
Normal file
|
@ -0,0 +1,869 @@
|
|||
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;
|
||||
|
||||
AddOkCancelButtons(new (evt) => { CreateClass(); }, null, 0, 1);
|
||||
|
||||
Title = "Generate";
|
||||
|
||||
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 include 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())
|
||||
{
|
||||
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));
|
||||
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 CreateClass()
|
||||
{
|
||||
//mClassViewPanel.[Friend]mSearchEdit.mOnSubmit(null);
|
||||
}
|
||||
|
||||
void ShowError(StringView error)
|
||||
{
|
||||
if (mOutputPanel == null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 (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 ..." : "Using 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 - GS!(40));
|
||||
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 - GS!(44), GS!(32)));
|
||||
mUIHeight = Math.Max(mUIHeight, GS!(160));
|
||||
}
|
||||
}
|
||||
|
||||
public override void Close()
|
||||
{
|
||||
if (mThreadState == .Executing)
|
||||
{
|
||||
var bfCompiler = gApp.mBfResolveCompiler;
|
||||
bfCompiler.RequestFastFinish();
|
||||
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;
|
||||
|
||||
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.mDefaultButton = dialog.AddButton("OK", new (evt) => DoNewClass(folder, evt));
|
||||
dialog.mEscButton = dialog.AddButton("Cancel");
|
||||
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)
|
||||
{
|
||||
Dialog dlg = (Dialog)evt.mSender;
|
||||
|
@ -1470,7 +1550,10 @@ namespace IDE.ui
|
|||
}
|
||||
|
||||
if (doReleaseRef)
|
||||
{
|
||||
projectItem.mDetached = true;
|
||||
projectItem.ReleaseRef();
|
||||
}
|
||||
//TODO: Defer this, projectItem is needed for a backgrounded QueueProjectSourceRemoved
|
||||
//delete projectItem;
|
||||
}
|
||||
|
@ -2471,17 +2554,26 @@ namespace IDE.ui
|
|||
}
|
||||
});
|
||||
|
||||
item = menu.AddItem("New Class...");
|
||||
item = menu.AddItem("Generate...");
|
||||
item.mOnMenuItemSelected.Add(new (item) =>
|
||||
{
|
||||
var projectFolder = GetSelectedProjectFolder();
|
||||
if (projectFolder != null)
|
||||
{
|
||||
if (CheckProjectModify(projectFolder.mProject))
|
||||
NewClass(projectFolder);
|
||||
GenerateCode(projectFolder);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if ((projectItem != null) && (projectItem is ProjectSource) && (!isProject))
|
||||
{
|
||||
item = menu.AddItem("Regenerate");
|
||||
item.mOnMenuItemSelected.Add(new (item) =>
|
||||
{
|
||||
Regenerate(false);
|
||||
});
|
||||
}
|
||||
|
||||
item = menu.AddItem("Import File...");
|
||||
item.mOnMenuItemSelected.Add(new (item) => { mImportFileDeferred = true; /* ImportFile();*/ });
|
||||
|
||||
|
|
|
@ -420,6 +420,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mInternalTypeDef = NULL;
|
||||
mPlatformTypeDef = NULL;
|
||||
mCompilerTypeDef = NULL;
|
||||
mCompilerGeneratorTypeDef = NULL;
|
||||
mDiagnosticsDebugTypeDef = NULL;
|
||||
mIDisposableTypeDef = NULL;
|
||||
mIIntegerTypeDef = NULL;
|
||||
|
@ -6765,6 +6766,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mInternalTypeDef = _GetRequiredType("System.Internal");
|
||||
mPlatformTypeDef = _GetRequiredType("System.Platform");
|
||||
mCompilerTypeDef = _GetRequiredType("System.Compiler");
|
||||
mCompilerGeneratorTypeDef = _GetRequiredType("System.Compiler.Generator");
|
||||
mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug");
|
||||
mIDisposableTypeDef = _GetRequiredType("System.IDisposable");
|
||||
mIIntegerTypeDef = _GetRequiredType("System.IInteger");
|
||||
|
@ -8087,6 +8089,149 @@ String BfCompiler::GetTypeDefList()
|
|||
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
|
||||
{
|
||||
public:
|
||||
|
@ -8580,9 +8725,9 @@ String BfCompiler::GetTypeDefMatches(const StringImpl& searchStr)
|
|||
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 sep = (int)inTypeName.IndexOf(':');
|
||||
|
@ -8595,7 +8740,7 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
|||
String typeName;
|
||||
int genericCount = 0;
|
||||
int pendingGenericCount = 0;
|
||||
for ( ; idx < (int)inTypeName.length(); idx++)
|
||||
for (; idx < (int)inTypeName.length(); idx++)
|
||||
{
|
||||
char c = inTypeName[idx];
|
||||
if (c == '<')
|
||||
|
@ -8606,7 +8751,7 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
|||
genericCount++;
|
||||
else if (c == '>')
|
||||
{
|
||||
pendingGenericCount = genericCount;
|
||||
pendingGenericCount = genericCount;
|
||||
genericCount = 0;
|
||||
}
|
||||
}
|
||||
|
@ -8620,10 +8765,10 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
|||
typeName += c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool isGlobals = false;
|
||||
if (typeName == ":static")
|
||||
{
|
||||
{
|
||||
typeName.clear();
|
||||
isGlobals = true;
|
||||
}
|
||||
|
@ -8637,63 +8782,73 @@ String BfCompiler::GetTypeDefInfo(const StringImpl& inTypeName)
|
|||
if (typeName[i] == '+')
|
||||
typeName[i] = '.';
|
||||
|
||||
String result;
|
||||
TypeDefMatchHelper matchHelper(result);
|
||||
|
||||
BfAtomComposite nameComposite;
|
||||
BfAtomComposite nameComposite;
|
||||
if ((typeName.IsEmpty()) || (mSystem->ParseAtomComposite(typeName, nameComposite)))
|
||||
{
|
||||
{
|
||||
auto itr = mSystem->mTypeDefs.TryGet(nameComposite);
|
||||
while (itr)
|
||||
{
|
||||
{
|
||||
auto typeDef = *itr;
|
||||
if ((!typeDef->mIsPartial) &&
|
||||
(typeDef->mProject == project) &&
|
||||
(typeDef->mFullName == nameComposite) &&
|
||||
(typeDef->IsGlobalsContainer() == isGlobals) &&
|
||||
(typeDef->GetSelfGenericParamCount() == pendingGenericCount))
|
||||
{
|
||||
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);
|
||||
}
|
||||
{
|
||||
typeDefs.Add(typeDef);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -8970,6 +9125,30 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone()
|
|||
#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)
|
||||
{
|
||||
String& outString = *gTLStrReturn.Get();
|
||||
|
|
|
@ -374,6 +374,7 @@ public:
|
|||
BfTypeDef* mInternalTypeDef;
|
||||
BfTypeDef* mPlatformTypeDef;
|
||||
BfTypeDef* mCompilerTypeDef;
|
||||
BfTypeDef* mCompilerGeneratorTypeDef;
|
||||
BfTypeDef* mDiagnosticsDebugTypeDef;
|
||||
BfTypeDef* mIDisposableTypeDef;
|
||||
BfTypeDef* mIIntegerTypeDef;
|
||||
|
@ -511,9 +512,15 @@ public:
|
|||
void ProcessAutocompleteTempType();
|
||||
void GetSymbolReferences();
|
||||
void Cancel();
|
||||
void RequestFastFinish();
|
||||
void RequestFastFinish();
|
||||
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);
|
||||
int GetEmitSource(const StringImpl& fileName, StringImpl* outBuffer);
|
||||
|
||||
|
|
|
@ -11789,7 +11789,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
if (mExpectingType->IsFunction())
|
||||
{
|
||||
BfIRValue result;
|
||||
if ((hasIncompatibleCallingConventions) && (mModule->HasCompiledOutput()))
|
||||
if ((hasIncompatibleCallingConventions) && (mModule->HasExecutedOutput()))
|
||||
{
|
||||
//
|
||||
{
|
||||
|
@ -11949,7 +11949,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
|
||||
// Do we need a special delegate type for this?
|
||||
if (((captureThisByValue) || (needsSplat) || (implicitParamCount > 0) /*|| (hasIncompatibleCallingConventions)*/) &&
|
||||
(mModule->HasCompiledOutput()))
|
||||
(mModule->HasExecutedOutput()))
|
||||
{
|
||||
hasCaptures = true;
|
||||
auto curProject = mModule->mCurTypeInstance->mTypeDef->mProject;
|
||||
|
@ -12030,7 +12030,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
// Do we need specialized calling code for this?
|
||||
BfIRValue funcValue;
|
||||
if (((needsSplat) || (implicitParamCount > 0) || (hasIncompatibleCallingConventions)) &&
|
||||
(mModule->HasCompiledOutput()))
|
||||
(mModule->HasExecutedOutput()))
|
||||
{
|
||||
int fieldIdx = 0;
|
||||
for (int implicitParamIdx = bindMethodInstance->HasThis() ? -1 : 0; implicitParamIdx < implicitParamCount; implicitParamIdx++)
|
||||
|
@ -12208,7 +12208,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
|
||||
// >> delegate.mTarget = bindResult.mTarget
|
||||
BfIRValue valPtr;
|
||||
if (mModule->HasCompiledOutput())
|
||||
if (mModule->HasExecutedOutput())
|
||||
{
|
||||
if ((implicitParamCount > 0) || (needsSplat)) // Point back to self, it contains capture data
|
||||
valPtr = mModule->mBfIRBuilder->CreateBitCast(mResult.mValue, mModule->mBfIRBuilder->GetPrimitiveType(BfTypeCode_NullPtr));
|
||||
|
@ -12226,7 +12226,7 @@ void BfExprEvaluator::Visit(BfDelegateBindExpression* delegateBindExpr)
|
|||
|
||||
if (!funcValue)
|
||||
{
|
||||
if ((mModule->HasCompiledOutput()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
||||
if ((mModule->HasExecutedOutput()) && (!mModule->mBfIRBuilder->mIgnoreWrites))
|
||||
mModule->AssertErrorState();
|
||||
return;
|
||||
}
|
||||
|
@ -13188,7 +13188,7 @@ BfLambdaInstance* BfExprEvaluator::GetLambdaInstance(BfLambdaBindExpression* lam
|
|||
mModule->mIncompleteMethodCount++;
|
||||
SetAndRestoreValue<BfClosureState*> prevClosureState(mModule->mCurMethodState->mClosureState, &closureState);
|
||||
|
||||
if (mModule->HasCompiledOutput())
|
||||
if (mModule->HasExecutedOutput())
|
||||
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
|
||||
|
@ -14415,7 +14415,7 @@ void BfExprEvaluator::CreateObject(BfObjectCreateExpression* objCreateExpr, BfAs
|
|||
{
|
||||
if (!bindResult.mFunc)
|
||||
{
|
||||
BF_ASSERT((!mModule->HasCompiledOutput()) || (mModule->mBfIRBuilder->mIgnoreWrites));
|
||||
BF_ASSERT((!mModule->HasExecutedOutput()) || (mModule->mBfIRBuilder->mIgnoreWrites));
|
||||
appendSizeValue = mModule->GetConstValue(0);
|
||||
}
|
||||
else
|
||||
|
@ -19717,7 +19717,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (((mModule->HasCompiledOutput()) || (mModule->mIsComptimeModule)) &&
|
||||
else if (((mModule->HasExecutedOutput()) || (mModule->mIsComptimeModule)) &&
|
||||
(wantsChecks))
|
||||
{
|
||||
if (checkedKind == BfCheckedKind_NotSet)
|
||||
|
|
|
@ -9617,6 +9617,11 @@ bool BfModule::HasCompiledOutput()
|
|||
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
|
||||
void BfModule::SkipObjectAccessCheck(BfTypedValue typedVal)
|
||||
{
|
||||
|
@ -15818,7 +15823,7 @@ void BfModule::CreateStaticCtor()
|
|||
auto methodDef = mCurMethodInstance->mMethodDef;
|
||||
|
||||
BfIRBlock exitBB;
|
||||
if ((HasCompiledOutput()) && (!mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mChainType != BfMethodChainType_ChainMember))
|
||||
if ((HasExecutedOutput()) && (!mCurMethodInstance->mIsUnspecialized) && (mCurMethodInstance->mChainType != BfMethodChainType_ChainMember))
|
||||
{
|
||||
auto boolType = GetPrimitiveType(BfTypeCode_Boolean);
|
||||
auto didStaticInitVarAddr = mBfIRBuilder->CreateGlobalVariable(
|
||||
|
@ -17041,7 +17046,7 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
|||
break;
|
||||
}
|
||||
|
||||
if ((HasCompiledOutput()) && (matchedMethod != NULL))
|
||||
if ((HasExecutedOutput()) && (matchedMethod != NULL))
|
||||
{
|
||||
SizedArray<BfIRValue, 1> args;
|
||||
auto ctorBodyMethodInstance = GetMethodInstance(mCurTypeInstance->mBaseType, matchedMethod, BfTypeVector());
|
||||
|
@ -18486,7 +18491,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
return;
|
||||
}
|
||||
|
||||
if (HasCompiledOutput())
|
||||
if (HasExecutedOutput())
|
||||
{
|
||||
BF_ASSERT(mIsModuleMutable);
|
||||
}
|
||||
|
@ -19713,7 +19718,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
skipBody = true;
|
||||
skipEndChecks = true;
|
||||
|
||||
if ((HasCompiledOutput()) || (mIsComptimeModule))
|
||||
if (HasExecutedOutput())
|
||||
{
|
||||
// Clear out DebugLoc - to mark the ".addr" code as part of prologue
|
||||
mBfIRBuilder->ClearDebugLocation();
|
||||
|
@ -19977,7 +19982,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
else if ((mCurTypeInstance->IsEnum()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
|
||||
{
|
||||
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
|
||||
if ((HasCompiledOutput()) || (mIsComptimeModule))
|
||||
if (HasExecutedOutput())
|
||||
{
|
||||
EmitEnumToStringBody();
|
||||
}
|
||||
|
@ -19990,7 +19995,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
else if ((mCurTypeInstance->IsTuple()) && (!mCurTypeInstance->IsBoxed()) && (methodDef->mName == BF_METHODNAME_TO_STRING))
|
||||
{
|
||||
auto enumType = ResolveTypeDef(mCompiler->mEnumTypeDef);
|
||||
if ((HasCompiledOutput()) || (mIsComptimeModule))
|
||||
if (HasExecutedOutput())
|
||||
{
|
||||
EmitTupleToStringBody();
|
||||
}
|
||||
|
@ -20032,7 +20037,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
{
|
||||
mBfIRBuilder->CreateRetVoid();
|
||||
}
|
||||
else if ((HasCompiledOutput()) || (mIsComptimeModule))
|
||||
else if (HasExecutedOutput())
|
||||
{
|
||||
String autoPropName = typeDef->GetAutoPropertyName(propertyDeclaration);
|
||||
BfFieldInstance* fieldInstance = GetFieldByName(mCurTypeInstance, autoPropName);
|
||||
|
|
|
@ -1633,6 +1633,7 @@ public:
|
|||
bool IsTargetingBeefBackend();
|
||||
bool WantsLifetimes();
|
||||
bool HasCompiledOutput();
|
||||
bool HasExecutedOutput();
|
||||
void SkipObjectAccessCheck(BfTypedValue typedVal);
|
||||
void EmitObjectAccessCheck(BfTypedValue typedVal);
|
||||
void EmitEnsureInstructionAt();
|
||||
|
|
|
@ -1288,7 +1288,7 @@ void CeBuilder::Build()
|
|||
auto methodInstance = mCeFunction->mMethodInstance;
|
||||
|
||||
if (methodInstance != NULL)
|
||||
{
|
||||
{
|
||||
BfMethodInstance dupMethodInstance;
|
||||
dupMethodInstance.CopyFrom(methodInstance);
|
||||
auto methodDef = methodInstance->mMethodDef;
|
||||
|
@ -1638,10 +1638,10 @@ void CeBuilder::Build()
|
|||
EmitBinaryOp(CeOp_Shl_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||
break;
|
||||
case BeBinaryOpKind_RightShift:
|
||||
EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||
EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||
break;
|
||||
case BeBinaryOpKind_ARightShift:
|
||||
EmitBinaryOp(CeOp_Shr_U8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||
EmitBinaryOp(CeOp_Shr_I8, CeOp_InvalidOp, ceLHS, ceRHS, result);
|
||||
break;
|
||||
default:
|
||||
Fail("Invalid binary op");
|
||||
|
@ -2476,7 +2476,18 @@ void CeBuilder::Build()
|
|||
EmitFrameOffset(ceSize);
|
||||
}
|
||||
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:
|
||||
// Nothing to do
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue